ooRexx  4.2.0-source
About: ooRexx (Open Object Rexx) is a free implementation of Object Rexx. Object Rexx is an enhancement of the classic Rexx interpreter; a full-featured programming language with a human-oriented syntax.
  Fossies Dox: ooRexx-4.2.0-source.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

StringClassMisc.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel */
40 /* */
41 /* Miscellaneous REXX string methods */
42 /* */
43 /******************************************************************************/
44 
45 #include <ctype.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <math.h>
49 #include "RexxCore.h"
50 #include "StringClass.hpp"
51 #include "SourceFile.hpp"
52 #include "ActivityManager.hpp"
53 #include "StringUtil.hpp"
54 
56 /*********************************************************************/
57 /* */
58 /* Function: determines valid rexx symbols and returns */
59 /* a type indicator for valid symbols that can */
60 /* be passed on to the dictionary routines. */
61 /* */
62 /*********************************************************************/
63 {
64  const char *Scan; /* string scan pointer */
65  size_t Compound; /* count of periods */
66  size_t i; /* loop counter */
67  const char *Linend; /* end of line */
68  int Type; /* return type */
69 
70  /* name too long */
71  /* or too short */
72  if (this->getLength() > (size_t)MAX_SYMBOL_LENGTH || this->getLength() == 0)
73  {
74  return STRING_BAD_VARIABLE; /* set a bad type */
75  }
76 
77  /* step to end */
78  Linend = this->getStringData() + this->getLength();
79 
80  Compound = 0; /* set compound name is no */
81  Scan = this->getStringData(); /* save start position */
82  /* while still part of symbol */
83  while (Scan < Linend && RexxSource::isSymbolCharacter(*Scan))
84  {
85 
86  if (*Scan == '.') /* a dot found.. */
87  {
88  Compound++; /* indicate a compound var */
89  }
90 
91  Scan++; /* step the pointer */
92  } /* len of symbol */
93  /* now check for exponent */
94  if (((Scan + 1) < Linend) &&
95  (*Scan == '-' || *Scan == '+') &&
96  (isdigit(this->getChar(0)) || *Scan == '.') &&
97  (toupper(*(Scan - 1)) == 'E'))
98  {
99  Scan++; /* step to next */
100 
101  while (Scan < Linend)
102  { /* while more characters */
103  if (!isdigit(*Scan)) /* if not a digit */
104  {
105  return STRING_BAD_VARIABLE; /* this isn't valid */
106  }
107  Scan++; /* step to next char */
108  }
109  }
110  if (Scan < Linend) /* use the entire string? */
111  {
112  return STRING_BAD_VARIABLE; /* no, can't be good */
113  }
114  /* now determine symbol type */
115  /* possible number? */
116  if (this->getChar(0) == '.' || isdigit(this->getChar(0)))
117  {
118 
119  /* only a period? */
120  if (Compound == 1 && this->getLength() == 1)
121  {
122  Type = STRING_LITERAL_DOT; /* yes, set the token type */
123  }
124  else if (Compound > 1) /* too many periods? */
125  {
126  Type = STRING_LITERAL; /* yes, just a literal token */
127  }
128  else
129  { /* check for a real number */
130  Type = STRING_NUMERIC; /* assume numeric for now */
131  Scan = this->getStringData(); /* point to symbol */
132  /* scan symbol, validating */
133  for (i = this->getLength() ; i; i-- )
134  {
135  if (!isdigit(*Scan) && /* if not a digit and */
136  *Scan != '.') /* and not a period... */
137  {
138  break; /* finished */
139  }
140  Scan++; /* step to next character */
141  }
142  if (i > 1 && /* if tripped over an 'E' */
143  toupper(*Scan) == 'E')
144  { /* could be exponential */
145  Scan++; /* step past E */
146  i--; /* count the character */
147  /* +/- case already validated */
148  if (*Scan != '+' && *Scan != '-')
149  {
150  for (; i; i--)
151  { /* scan rest of symbol */
152  if (!isdigit(*Scan))
153  { /* if not a digit... */
154  Type = STRING_LITERAL; /* not a number */
155  break;
156  }
157  Scan++; /* step to next character */
158  }
159  }
160  }
161  else if (i) /* literal if stuff left */
162  {
163  Type = STRING_LITERAL; /* yes, just a literal token */
164  }
165  }
166  }
167 
168  else if (!Compound)
169  { /* not a compound so... */
170  Type = STRING_NAME; /* set the token type */
171  }
172  /* is it a stem? */
173  else if (Compound == 1 && *(Scan - 1) == '.')
174  {
175  Type = STRING_STEM; /* yes, set the token type */
176  }
177  else
178  {
179  Type = STRING_COMPOUND_NAME; /* otherwise just plain */
180  }
181  /* compound */
182  return Type; /* return the type info */
183 }
184 
186  RexxString *info, /* target compared value */
187  RexxInteger *_length) /* minimum length */
188 /******************************************************************************/
189 /* Function: ABBREV string method */
190 /******************************************************************************/
191 {
192  size_t Len1; /* length of string1 */
193  size_t Len2; /* length of string1 */
194  size_t ChkLen; /* required check length */
195  int rc; /* compare result */
196 
197  info = stringArgument(info, ARG_ONE); /* process the information string */
198  Len2 = info->getLength(); /* get the length also */
199  /* get the optional check length */
200  /* get the optional check length */
201  ChkLen = optionalLengthArgument(_length, Len2, ARG_TWO);
202  Len1 = this->getLength(); /* get this length */
203 
204  if (ChkLen == 0 && Len2 == 0) /* if null string match */
205  {
206  rc = 1; /* then we have an abbrev */
207  }
208  else if (Len1 == 0L || /* len 1 is zero, */
209  (Len2 < ChkLen) || /* or second is too short */
210  (Len1 < Len2)) /* or second is too long */
211  {
212  rc = 0; /* not an abbreviation */
213  }
214 
215  else /* now we have to check it */
216  {
217  /* do the comparison */
218  rc = !(memcmp(this->getStringData(), info->getStringData(), Len2));
219  }
220  /* return proper string value */
221  return(rc) ? IntegerOne : IntegerZero;
222 }
223 
224 
226 {
227  // the info must be a string value
228  info = stringArgument(info, ARG_ONE);
229  stringsize_t len2 = info->getLength();
230  // the check length is optional, and defaults to the length of info.
231  stringsize_t chkLen = optionalLengthArgument(_length, len2, ARG_TWO);
232 
233  stringsize_t len1 = this->getLength();
234 
235  // if a null string match is allowed, this is true
236  if (chkLen == 0 && len2 == 0)
237  {
238  return TheTrueObject;
239  }
240 
241  // if the info is a null string, no match is possible
242  // if the target string is shorter than the check length, also no match
243  // if the info string is shorter than this string, not a match.
244  if (len1 == 0 || (len2 < chkLen) || (len1 < len2))
245  {
246  return TheFalseObject;
247  }
248  /* do the comparison */
250 }
251 
252 
254  RexxString *string2, /* other string to compare against */
255  RexxString *pad) /* optional padding character */
256 /******************************************************************************/
257 /* Function: String class COMPARE method/function. */
258 /******************************************************************************/
259 {
260  char PadChar; /* pad character */
261  size_t MisMatch; /* mismatch location */
262  RexxInteger *Retval; /* returned result */
263  const char *String1; /* string 1 pointer */
264  const char *String2; /* string 2 pointer */
265  size_t Lead; /* leading length */
266  size_t Remainder; /* trailing length */
267  size_t i; /* loop index */
268  size_t Length1; /* first string length */
269  size_t Length2; /* second string length */
270 
271  Length1 = this->getLength(); /* get this strings length */
272  /* validate the compare string */
273  string2 = stringArgument(string2, ARG_ONE);
274  Length2 = string2->getLength(); /* get the length also */
275  PadChar = optionalPadArgument(pad, ' ', ARG_TWO);/* get the pad character */
276  if (Length1 > Length2)
277  { /* first longer? */
278  String1 = this->getStringData(); /* make arg 1 first string */
279  /* arg 2 is second string */
280  String2 = string2->getStringData();
281  Lead = Length2; /* get shorter length */
282  Remainder = Length1 - Lead; /* get trailing size */
283  }
284  else
285  { /* make arg 2 first string */
286  String1 = string2->getStringData();
287  String2 = this->getStringData(); /* arg 1 is second string */
288  Lead = Length1; /* get shorter length */
289  Remainder = Length2 - Lead; /* get trailing size */
290  }
291  MisMatch = 0; /* assume they are equal */
292  i = 0; /* set the start */
293  while (i < Lead)
294  { /* if have leading compare */
295  if (String1[i] != String2[i])
296  { /* not the same? */
297  MisMatch = i + 1; /* save position, origin one */
298  break; /* exit the loop */
299  }
300  i++; /* step the index */
301  }
302  if (!MisMatch && Remainder)
303  { /* need to handle padding? */
304  String1 += Lead; /* step to remainder */
305  for (i = 0; i < Remainder; i++)
306  { /* scan the remainder */
307  if (String1[i] != PadChar)
308  { /* pad mismatch? */
309  MisMatch = Lead + i + 1; /* get mismatch position */
310  break; /* finished */
311  }
312  }
313  }
314  if (!MisMatch)
315  {
316  Retval = IntegerZero; /* this is zero */
317  }
318  else
319  {
320  Retval = new_integer(MisMatch); /* make an integer return value */
321  }
322  return Retval; /* return result string */
323 }
324 
325 
336 {
337  stringsize_t length1 = this->getLength(); /* get this strings length */
338  /* validate the compare string */
339  other = stringArgument(other, ARG_ONE);
340  stringsize_t length2 = other->getLength(); /* get the length also */
341  // we uppercase the pad character now since this is caseless
342  char padChar = toupper(optionalPadArgument(pad, ' ', ARG_TWO));
343 
344  const char *string1;
345  const char *string2;
346  stringsize_t lead;
347  stringsize_t _remainder;
348 
349  // is the first longer?
350  if (length1 > length2)
351  {
352  string1 = this->getStringData(); /* make arg 1 first string */
353  /* arg 2 is second string */
354  string2 = other->getStringData();
355  lead = length2; /* get shorter length */
356  _remainder = length1 - lead; /* get trailing size */
357  }
358  else
359  {
360  string1 = other->getStringData(); /* make arg 2 first string */
361  string2 = this->getStringData(); /* arg 1 is second string */
362  lead = length1; /* get shorter length */
363  _remainder = length2 - lead; /* get trailing size */
364  }
365  stringsize_t i = 0; /* set the start */
366  // compare the leading parts
367  for (i = 0; i < lead; i++)
368  {
369  // have a mismatch?
370  if (toupper(string1[i]) != toupper(string2[i]))
371  {
372  return new_integer(i+1); // return the mismatch position
373  }
374  }
375  string1 += lead; // step to the remainder and scan
376  for (i = 0; i < _remainder; i++)
377  {
378  // mismatch on the pad?
379  if (toupper(string1[i]) != padChar)
380  {
381  // this is the mismatch position, return it
382  return new_integer(lead + i + 1);
383  }
384  }
385  return IntegerZero; // no mismatch, return the failure indicator
386 }
387 
388 
390 /******************************************************************************/
391 /* Function: String class COPIES method/function */
392 /******************************************************************************/
393 {
394  size_t Count; /* copies count */
395  RexxString *Retval; /* return value */
396  size_t Len; /* copy string length */
397  char *Temp; /* copy location */
398 
399  requiredArgument(_copies, ARG_ONE); /* the count is required */
400  /* get the copies count */
401  Count = _copies->requiredNonNegative(ARG_ONE);
402  Len = this->getLength(); /* get argument length */
403 
404  if (Count == 0 || /* no copies requested? */
405  Len == 0 ) /* or copying a null string */
406  {
407  Retval = OREF_NULLSTRING; /* just a null string */
408  }
409  else
410  { /* get storage size */
411  /* allocate storage needed */
412  /* allocate storage needed */
413  Retval = (RexxString *)raw_string(Len * Count);
414 
415  if (Len == 1)
416  { /* if only 1 char long */
417  /* just do this with memset */
418  memset(Retval->getWritableData(), this->getChar(0), Count);
419  }
420  /* if any copies */
421  else
422  {
423  /* point to the string */
424  Temp = Retval->getWritableData();
425  while (Count--)
426  { /* copy 2 thru n copies */
427  /* copy the string */
428  memcpy(Temp, this->getStringData(), Len);
429  Temp += Len;
430  }
431  }
432  }
433  return Retval; /* return copied string */
434 }
435 
437 /******************************************************************************/
438 /* Function: String class DATATYPE method/function */
439 /******************************************************************************/
440 {
441  if (pType != OREF_NULL)
442  { /* see if type was specified? */
443  /* yes, specified, get 1st char */
444  int type = optionalOptionArgument(pType, 0, ARG_ONE);
445  /* and call datatype routine to */
446  return StringUtil::dataType(this, type); /* determine if its type specified. */
447  }
448  /* type not specified, see if its a */
449  /* valid number */
450  return(StringUtil::dataType(this, 'N') == TheTrueObject
451  ? new_string("NUM",3) /* if so we return NUM */
452  : new_string("CHAR",4)); /* otherwise we return CHAR */
453 }
454 
455 
466 {
467  return StringUtil::lastPosRexx(getStringData(), getLength(), needle, _start, _range);
468 }
469 
470 
480 {
481  // validate that this is a good string argument
482  needle = stringArgument(needle, ARG_ONE);
483  // find out where to start the search. The default is at the very end.
484  size_t startPos = optionalPositionArgument(_start, getLength(), ARG_TWO);
485  size_t range = optionalLengthArgument(_range, getLength(), ARG_THREE);
486  // now perform the actual search.
487  return new_integer(StringUtil::caselessLastPos(getStringData(), getLength(), needle, startPos, range));
488 }
489 
490 
502 size_t RexxString::lastPos(RexxString *needle, size_t _start)
503 {
504  return StringUtil::lastPos(getStringData(), getLength(), needle, _start, getLength());
505 }
506 
507 
519 size_t RexxString::caselessLastPos(RexxString *needle, size_t _start)
520 {
521  return StringUtil::caselessLastPos(getStringData(), getLength(), needle, _start, getLength());
522 }
523 
525 /******************************************************************************/
526 /* Function: Count occurrences of one string in another. */
527 /******************************************************************************/
528 {
529  /* force needle to a string */
530  needle = stringArgument(needle, ARG_ONE);
531  // delegate the counting to the string util
533 }
534 
535 
537 /******************************************************************************/
538 /* Function: Count occurrences of one string in another. */
539 /******************************************************************************/
540 {
541  /* force needle to a string */
542  needle = stringArgument(needle, ARG_ONE);
543  // delegate the counting to the string util
545 }
546 
548 /******************************************************************************/
549 /* Function: Change strings into another string. */
550 /******************************************************************************/
551 {
552  size_t _start; /* converted start position */
553  size_t matchPos; /* last match position */
554  size_t needleLength; /* length of the needle */
555  size_t newLength; /* length of the replacement string */
556  size_t matches; /* number of replacements */
557  size_t copyLength; /* length to copy */
558  const char *source; /* point to the string source */
559  char *copyPtr; /* current copy position */
560  const char *newPtr; /* pointer to replacement data */
561  RexxString *result; /* returned result string */
562  size_t i;
563 
564  /* force needle to a string */
565  needle = stringArgument(needle, ARG_ONE);
566  /* newneedle must be a string two */
567  newNeedle = stringArgument(newNeedle, ARG_TWO);
568 
569  // we'll only change up to a specified count. If not there, we do everything.
570  size_t count = optionalPositive(countArg, Numerics::MAX_WHOLENUMBER, ARG_THREE);
571  matches = StringUtil::countStr(getStringData(), getLength(), needle); /* find the number of replacements */
572  if (matches > count) // the matches are bounded by the count
573  {
574  matches = count;
575  }
576  needleLength = needle->getLength(); /* get the length of the needle */
577  newLength = newNeedle->getLength(); /* and the replacement length */
578  /* get a proper sized string */
579  result = (RexxString *)raw_string(this->getLength() - (matches * needleLength) + (matches * newLength));
580  copyPtr = result->getWritableData(); /* point to the copy location */
581  source = this->getStringData(); /* and out own data */
582  /* and the string to replace */
583  newPtr = newNeedle->getStringData();
584  _start = 0; /* set a zero starting point */
585  for (i = 0; i < matches; i++)
586  { /* until we hit count or run out */
587  matchPos = pos(needle, _start); /* look for the next occurrence */
588  if (matchPos == 0) /* not found? */
589  {
590  break; /* get out of here */
591  }
592  copyLength = (matchPos - 1) - _start; /* get the next length to copy */
593  if (copyLength != 0)
594  { /* something to copy? */
595  /* add on the next string section */
596  memcpy(copyPtr, source + _start, copyLength);
597  copyPtr += copyLength; /* step over the copied part */
598  }
599  if (newLength != 0)
600  { /* something to replace with? */
601  memcpy(copyPtr, newPtr, newLength); /* copy over the new segment */
602  copyPtr += newLength; /* and step it over also */
603  }
604  _start = matchPos + needleLength - 1; /* step to the next position */
605  }
606  if (_start < this->getLength()) /* some remainder left? */
607  {
608  /* add it on */
609  memcpy(copyPtr, source + _start, this->getLength() - _start);
610  }
611  return result; /* finished */
612 }
613 
615 /******************************************************************************/
616 /* Function: Change strings into another string. */
617 /******************************************************************************/
618 {
619  size_t _start; /* converted start position */
620  size_t matchPos; /* last match position */
621  size_t needleLength; /* length of the needle */
622  size_t newLength; /* length of the replacement string */
623  size_t matches; /* number of replacements */
624  size_t copyLength; /* length to copy */
625  const char *source; /* point to the string source */
626  char * copyPtr; /* current copy position */
627  const char *newPtr; /* pointer to replacement data */
628  RexxString *result; /* returned result string */
629  size_t i;
630 
631  /* force needle to a string */
632  needle = stringArgument(needle, ARG_ONE);
633  /* newneedle must be a string two */
634  newNeedle = stringArgument(newNeedle, ARG_TWO);
635  // we'll only change up to a specified count. If not there, we do everything.
636  size_t count = optionalPositive(countArg, Numerics::MAX_WHOLENUMBER, ARG_THREE);
637 
638  matches = StringUtil::caselessCountStr(getStringData(), getLength(), needle); /* find the number of replacements */
639  if (matches > count) // the matches are bounded by the count
640  {
641  matches = count;
642  }
643  needleLength = needle->getLength(); /* get the length of the needle */
644  newLength = newNeedle->getLength(); /* and the replacement length */
645  /* get a proper sized string */
646  result = (RexxString *)raw_string(this->getLength() - (matches * needleLength) + (matches * newLength));
647  copyPtr = result->getWritableData(); /* point to the copy location */
648  source = this->getStringData(); /* and out own data */
649  /* and the string to replace */
650  newPtr = newNeedle->getStringData();
651  _start = 0; /* set a zero starting point */
652  for (i = 0; i < matches; i++)
653  { /* until we hit count or run out */
654  matchPos = this->caselessPos(needle, _start); /* look for the next occurrence */
655  if (matchPos == 0) /* not found? */
656  {
657  break; /* get out of here */
658  }
659  copyLength = (matchPos - 1) - _start; /* get the next length to copy */
660  if (copyLength != 0)
661  { /* something to copy? */
662  /* add on the next string section */
663  memcpy(copyPtr, source + _start, copyLength);
664  copyPtr += copyLength; /* step over the copied part */
665  }
666  if (newLength != 0)
667  { /* something to replace with? */
668  memcpy(copyPtr, newPtr, newLength); /* copy over the new segment */
669  copyPtr += newLength; /* and step it over also */
670  }
671  _start = matchPos + needleLength - 1; /* step to the next position */
672  }
673  if (_start < this->getLength()) /* some remainder left? */
674  {
675  /* add it on */
676  memcpy(copyPtr, source + _start, this->getLength() - _start);
677  }
678  return result; /* finished */
679 }
680 
681 
683 /******************************************************************************/
684 /* Function: String class POS method/function */
685 /******************************************************************************/
686 {
687  return StringUtil::posRexx(getStringData(), getLength(), needle, pstart, range);
688 }
689 
690 
701 {
702  /* force needle to a string */
703  needle = stringArgument(needle, ARG_ONE);
704  /* get the starting position */
705  size_t _start = optionalPositionArgument(pstart, 1, ARG_TWO);
706  size_t _range = optionalLengthArgument(range, getLength() - _start + 1, ARG_THREE);
707  /* pass on to the primitive function */
708  /* and return as an integer object */
709  return new_integer(StringUtil::caselessPos(getStringData(), getLength(), needle , _start - 1, _range));
710 }
711 
712 
721 size_t RexxString::pos(RexxString *needle, size_t _start)
722 {
723  return StringUtil::pos(getStringData(), getLength(), needle, _start, getLength());
724 }
725 
726 
735 size_t RexxString::caselessPos(RexxString *needle, size_t _start)
736 {
737  return StringUtil::caselessPos(getStringData(), getLength(), needle, _start, getLength());
738 }
739 
740 
742  RexxString *tableo, /* output table */
743  RexxString *tablei, /* input table */
744  RexxString *pad, /* pad character */
745  RexxInteger *_start, // start position to translate
746  RexxInteger *_range) // length to translate
747 /******************************************************************************/
748 /* Function: String class TRANSLATE method/function */
749 /******************************************************************************/
750 {
751  RexxString *Retval; /* return value */
752  const char *OutTable; /* output table */
753  size_t OutTableLength; /* length of output table */
754  const char *InTable; /* input table */
755  char *ScanPtr; /* scanning pointer */
756  size_t ScanLength; /* scanning length */
757  size_t InTableLength; /* length of input table */
758  char PadChar; /* pad character */
759  char ch; /* current character */
760  size_t Position; /* table position */
761 
762  /* just a simple uppercase? */
763  if (tableo == OREF_NULL && tablei == OREF_NULL && pad == OREF_NULL)
764  {
765  return this->upperRexx(_start, _range); /* return the uppercase version */
766  }
767  /* validate the tables */
768  /* validate the tables */
769  tableo = optionalStringArgument(tableo, OREF_NULLSTRING, ARG_ONE);
770  OutTableLength = tableo->getLength(); /* get the table length */
771  /* input table too */
772  tablei = optionalStringArgument(tablei, OREF_NULLSTRING, ARG_TWO);
773  InTableLength = tablei->getLength(); /* get the table length */
774  InTable = tablei->getStringData(); /* point at the input table */
775  OutTable = tableo->getStringData(); /* and the output table */
776  /* get the pad character */
777  PadChar = optionalPadArgument(pad, ' ', ARG_THREE);
778  size_t startPos = optionalPositionArgument(_start, 1, ARG_FOUR);
779  size_t range = optionalLengthArgument(_range, getLength() - startPos + 1, ARG_FOUR);
780 
781  // if nothing to translate, we can return now
782  if (startPos > getLength() || range == 0)
783  {
784  return this;
785  }
786  // cap the real range
787  range = Numerics::minVal(range, getLength() - startPos + 1);
788 
789  /* allocate space for answer */
790  /* and copy the string */
791  Retval = new_string(this->getStringData(), this->getLength());
792  ScanPtr = Retval->getWritableData() + startPos - 1; /* point to data */
793  ScanLength = range; /* get the length too */
794 
795  while (ScanLength--)
796  { /* spin thru input */
797  ch = *ScanPtr; /* get a character */
798 
799  if (tablei != OREF_NULLSTRING) /* input table specified? */
800  {
801  /* search for the character */
802  Position = StringUtil::memPos(InTable, InTableLength, ch);
803  }
804  else
805  {
806  Position = ((size_t)ch) & 0xFF; /* position is the character value */
807  }
808  if (Position != (size_t)(-1))
809  { /* found in the table? */
810  if (Position < OutTableLength) /* in the output table? */
811  {
812  /* convert the character */
813  *ScanPtr = *(OutTable + Position);
814  }
815  else
816  {
817  *ScanPtr = PadChar; /* else use the pad character */
818  }
819  }
820  ScanPtr++; /* step the pointer */
821  }
822  return Retval; /* return translated string */
823 }
824 
825 
827  RexxString *ref, /* compare reference string */
828  RexxString *option, /* Match/NoMatch option */
829  RexxInteger *_start, /* optional starg position */
830  RexxInteger *range) // length to search
831 /******************************************************************************/
832 /* Function: String class VERIFY function */
833 /******************************************************************************/
834 {
835  return StringUtil::verify(getStringData(), getLength(), ref, option, _start, range);
836 }
837 
838 
855 {
856  stringsize_t _start = positionArgument(start_, ARG_ONE);
857  // the start position must be within the string bounds
858  if (_start > getLength())
859  {
861  }
862  other = stringArgument(other, ARG_TWO);
863 
864  stringsize_t offset = optionalPositionArgument(offset_, 1, ARG_THREE);
865 
866  if (offset > other->getLength())
867  {
869  }
870 
871  stringsize_t len = optionalLengthArgument(len_, other->getLength() - offset + 1, ARG_FOUR);
872 
873  if ((offset + len - 1) > other->getLength())
874  {
876  }
877 
878  return primitiveMatch(_start, other, offset, len) ? TheTrueObject : TheFalseObject;
879 }
880 
881 
898 {
899  stringsize_t _start = positionArgument(start_, ARG_ONE);
900  // the start position must be within the string bounds
901  if (_start > getLength())
902  {
904  }
905  other = stringArgument(other, ARG_TWO);
906 
907  stringsize_t offset = optionalPositionArgument(offset_, 1, ARG_THREE);
908 
909  if (offset > other->getLength())
910  {
912  }
913 
914  stringsize_t len = optionalLengthArgument(len_, other->getLength() - offset + 1, ARG_FOUR);
915 
916  if ((offset + len - 1) > other->getLength())
917  {
919  }
920 
921  return primitiveCaselessMatch(_start, other, offset, len) ? TheTrueObject : TheFalseObject;
922 }
923 
924 
937 {
938  _start--; // make the starting point origin zero
939  offset--;
940 
941  // if the match is not possible in the target string, just return false now.
942  if ((_start + len) > getLength())
943  {
944  return false;
945  }
946 
947  return memcmp(getStringData() + _start, other->getStringData() + offset, len) == 0;
948 }
949 
950 
964 {
965  _start--; // make the starting point origin zero
966  offset--;
967 
968  // if the match is not possible in the target string, just return false now.
969  if ((_start + len) > getLength())
970  {
971  return false;
972  }
973 
974  return StringUtil::caselessCompare(getStringData() + _start, other->getStringData() + offset, len) == 0;
975 }
976 
977 
990 {
991  stringsize_t position = positionArgument(position_, ARG_ONE);
992  // the start position must be within the string bounds
993  if (position > getLength())
994  {
996  }
997  matchSet = stringArgument(matchSet, ARG_TWO);
998 
999  stringsize_t _setLength = matchSet->getLength();
1000  char _matchChar = getChar(position - 1);
1001 
1002  // iterate through the match set looking for a match
1003  for (stringsize_t i = 0; i < _setLength; i++)
1004  {
1005  if (_matchChar == matchSet->getChar(i))
1006  {
1007  return TheTrueObject;
1008  }
1009  }
1010  return TheFalseObject;
1011 }
1012 
1013 
1026 {
1027  stringsize_t position = positionArgument(position_, ARG_ONE);
1028  // the start position must be within the string bounds
1029  if (position > getLength())
1030  {
1032  }
1033  matchSet = stringArgument(matchSet, ARG_TWO);
1034 
1035  stringsize_t _setLength = matchSet->getLength();
1036  char _matchChar = getChar(position - 1);
1037  _matchChar = toupper(_matchChar);
1038 
1039  // iterate through the match set looking for a match, using a
1040  // caseless compare
1041  for (stringsize_t i = 0; i < _setLength; i++)
1042  {
1043  if (_matchChar == toupper(matchSet->getChar(i)))
1044  {
1045  return TheTrueObject;
1046  }
1047  }
1048  return TheFalseObject;
1049 }
1050 
1051 
1062 {
1063  other = stringArgument(other, ARG_ONE);
1064 
1065  stringsize_t _start = optionalPositionArgument(start_, 1, ARG_TWO);
1066  stringsize_t len = optionalLengthArgument(len_, Numerics::maxVal(getLength(), other->getLength()) - _start + 1, ARG_THREE);
1067 
1068  return primitiveCompareTo(other, _start, len);
1069 }
1070 
1071 
1084 {
1085  stringsize_t myLength = getLength();
1086  stringsize_t otherLength = other->getLength();
1087 
1088  // if doing the compare outside of the string length, we're less than the other string
1089  // unless the start is
1090  if (_start > myLength)
1091  {
1092  return _start > otherLength ? IntegerZero : IntegerMinusOne;
1093  }
1094  // if beyond the other length, they we're the larger
1095  if (_start > otherLength)
1096  {
1097  return IntegerOne;
1098  }
1099 
1100  _start--; // make the starting point origin zero
1101 
1102  myLength = Numerics::minVal(len, myLength - _start);
1103  otherLength = Numerics::minVal(len, otherLength - _start);
1104 
1105  len = Numerics::minVal(myLength, otherLength);
1106 
1107  wholenumber_t result = memcmp(getStringData() + _start, other->getStringData() + _start, len);
1108 
1109  // if they compare equal, then they are only
1110  if (result == 0)
1111  {
1112  if (myLength == otherLength)
1113  {
1114  return IntegerZero;
1115  }
1116  else if (myLength > otherLength)
1117  {
1118  return IntegerOne;
1119  }
1120  else
1121  {
1122  return IntegerMinusOne;
1123  }
1124  }
1125  else if (result > 0)
1126  {
1127  return IntegerOne;
1128  }
1129  else
1130  {
1131  return IntegerMinusOne;
1132  }
1133 }
1134 
1135 
1136 
1137 
1148 {
1149  other = stringArgument(other, ARG_ONE);
1150 
1151  stringsize_t _start = optionalPositionArgument(start_, 1, ARG_TWO);
1152  stringsize_t len = optionalLengthArgument(len_, Numerics::maxVal(getLength(), other->getLength()) - _start + 1, ARG_THREE);
1153 
1154  return primitiveCaselessCompareTo(other, _start, len);
1155 }
1156 
1157 
1158 
1159 
1172 {
1173  stringsize_t myLength = getLength();
1174  stringsize_t otherLength = other->getLength();
1175 
1176  // if doing the compare outside of the string length, we're less than the other string
1177  // unless the start is
1178  if (_start > myLength)
1179  {
1180  return _start > otherLength ? IntegerZero : IntegerMinusOne;
1181  }
1182  // if beyond the other length, they we're the larger
1183  if (_start > otherLength)
1184  {
1185  return IntegerOne;
1186  }
1187 
1188  _start--; // make the starting point origin zero
1189 
1190  myLength = Numerics::minVal(len, myLength - _start);
1191  otherLength = Numerics::minVal(len, otherLength - _start);
1192 
1193  len = Numerics::minVal(myLength, otherLength);
1194 
1195  wholenumber_t result = StringUtil::caselessCompare(getStringData() + _start, other->getStringData() + _start, len);
1196 
1197  // if they compare equal, then they are only
1198  if (result == 0)
1199  {
1200  if (myLength == otherLength)
1201  {
1202  return IntegerZero;
1203  }
1204  else if (myLength > otherLength)
1205  {
1206  return IntegerOne;
1207  }
1208  else
1209  {
1210  return IntegerMinusOne;
1211  }
1212  }
1213  else if (result > 0)
1214  {
1215  return IntegerOne;
1216  }
1217  else
1218  {
1219  return IntegerMinusOne;
1220  }
1221 }
RexxString::matchChar
RexxInteger * matchChar(RexxInteger *position_, RexxString *matchSet)
Definition: StringClassMisc.cpp:989
RexxString::caselessPosRexx
RexxInteger * caselessPosRexx(RexxString *, RexxInteger *, RexxInteger *)
Definition: StringClassMisc.cpp:700
RexxString::caselessMatchChar
RexxInteger * caselessMatchChar(RexxInteger *position_, RexxString *matchSet)
Definition: StringClassMisc.cpp:1025
StringUtil.hpp
RexxString::caselessCompareToRexx
RexxInteger * caselessCompareToRexx(RexxString *other, RexxInteger *start_, RexxInteger *len_)
Definition: StringClassMisc.cpp:1147
RexxString::upperRexx
RexxString * upperRexx(RexxInteger *, RexxInteger *)
Definition: StringClass.cpp:1615
RexxString::primitiveCaselessCompareTo
RexxInteger * primitiveCaselessCompareTo(RexxString *other, stringsize_t start, stringsize_t len)
Definition: StringClassMisc.cpp:1171
RexxString::lastPos
size_t lastPos(RexxString *needle, size_t start)
Definition: StringClassMisc.cpp:502
TheFalseObject
#define TheFalseObject
Definition: RexxCore.h:184
STRING_NAME
#define STRING_NAME
Definition: StringClass.hpp:59
StringUtil::caselessCompare
static int caselessCompare(const char *, const char *, size_t)
Definition: StringUtil.cpp:571
new_integer
RexxInteger * new_integer(wholenumber_t v)
Definition: IntegerClass.hpp:198
type
int type
Definition: cmdparse.cpp:1965
optionalLengthArgument
size_t optionalLengthArgument(RexxObject *o, size_t d, size_t p)
Definition: RexxCore.h:336
StringUtil::posRexx
static RexxInteger * posRexx(const char *stringData, size_t length, RexxString *needle, RexxInteger *pstart, RexxInteger *range)
Definition: StringUtil.cpp:130
RexxString::compareToRexx
RexxInteger * compareToRexx(RexxString *other, RexxInteger *start_, RexxInteger *len_)
Definition: StringClassMisc.cpp:1061
RexxString::isSymbol
int isSymbol()
Definition: StringClassMisc.cpp:55
ActivityManager.hpp
RexxString::caselessCompare
RexxInteger * caselessCompare(RexxString *, RexxString *)
Definition: StringClassMisc.cpp:335
RexxString::pos
size_t pos(RexxString *, size_t)
Definition: StringClassMisc.cpp:721
STRING_COMPOUND_NAME
#define STRING_COMPOUND_NAME
Definition: StringClass.hpp:55
Numerics::maxVal
static wholenumber_t maxVal(wholenumber_t n1, wholenumber_t n2)
Definition: Numerics.hpp:118
RexxString::getLength
size_t getLength()
Definition: StringClass.hpp:330
requiredArgument
void requiredArgument(RexxObject *object, size_t position)
Definition: RexxCore.h:284
ARG_TWO
const int ARG_TWO
Definition: RexxCore.h:81
RexxString::countStrRexx
RexxInteger * countStrRexx(RexxString *)
Definition: StringClassMisc.cpp:524
reportException
void reportException(wholenumber_t error)
Definition: ActivityManager.hpp:136
RexxString::getWritableData
char * getWritableData()
Definition: StringClass.hpp:334
RexxString::copies
RexxString * copies(RexxInteger *)
Definition: StringClassMisc.cpp:389
RexxString::caselessAbbrev
RexxInteger * caselessAbbrev(RexxString *, RexxInteger *)
Definition: StringClassMisc.cpp:225
Numerics::MAX_WHOLENUMBER
static const wholenumber_t MAX_WHOLENUMBER
Definition: Numerics.hpp:62
TheTrueObject
#define TheTrueObject
Definition: RexxCore.h:185
RexxString::getStringData
const char * getStringData()
Definition: StringClass.hpp:333
RexxString::getChar
char getChar(size_t p)
Definition: StringClass.hpp:338
StringUtil::pos
static size_t pos(const char *stringData, size_t haystack_length, RexxString *needle, size_t _start, size_t _range)
Definition: StringUtil.cpp:154
IntegerZero
#define IntegerZero
Definition: RexxCore.h:188
IntegerMinusOne
#define IntegerMinusOne
Definition: RexxCore.h:198
RexxString::abbrev
RexxInteger * abbrev(RexxString *, RexxInteger *)
Definition: StringClassMisc.cpp:185
RexxString::caselessMatch
RexxInteger * caselessMatch(RexxInteger *start_, RexxString *other, RexxInteger *offset_, RexxInteger *len_)
Definition: StringClassMisc.cpp:897
RexxString::caselessCountStrRexx
RexxInteger * caselessCountStrRexx(RexxString *)
Definition: StringClassMisc.cpp:536
raw_string
RexxString * raw_string(stringsize_t l)
Definition: StringClass.hpp:529
RexxString::changeStr
RexxString * changeStr(RexxString *, RexxString *, RexxInteger *)
Definition: StringClassMisc.cpp:547
optionalPositionArgument
size_t optionalPositionArgument(RexxObject *o, size_t d, size_t p)
Definition: RexxCore.h:344
new_string
RexxString * new_string(const char *s, stringsize_t l)
Definition: StringClass.hpp:524
RexxString::dataType
RexxObject * dataType(RexxString *)
Definition: StringClassMisc.cpp:436
ARG_ONE
const int ARG_ONE
Definition: RexxCore.h:80
optionalStringArgument
RexxString * optionalStringArgument(RexxObject *o, RexxString *d, size_t p)
Definition: RexxCore.h:321
OREF_NULL
#define OREF_NULL
Definition: RexxCore.h:60
Error_Incorrect_method_position
#define Error_Incorrect_method_position
Definition: RexxErrorCodes.h:476
ARG_THREE
const int ARG_THREE
Definition: RexxCore.h:82
STRING_BAD_VARIABLE
#define STRING_BAD_VARIABLE
Definition: StringClass.hpp:53
RexxSource::isSymbolCharacter
static bool isSymbolCharacter(char ch)
Definition: SourceFile.hpp:374
RexxObject::requiredNonNegative
stringsize_t requiredNonNegative(size_t position, size_t precision=Numerics::ARGUMENT_DIGITS)
Definition: ObjectClass.cpp:1442
StringClass.hpp
StringUtil::verify
static RexxInteger * verify(const char *data, size_t stringLen, RexxString *ref, RexxString *option, RexxInteger *_start, RexxInteger *range)
Definition: StringUtil.cpp:1411
optionalPadArgument
char optionalPadArgument(RexxObject *o, char d, size_t p)
Definition: RexxCore.h:351
RexxString::lastPosRexx
RexxInteger * lastPosRexx(RexxString *, RexxInteger *, RexxInteger *)
Definition: StringClassMisc.cpp:465
StringUtil::lastPosRexx
static RexxInteger * lastPosRexx(const char *stringData, size_t haystackLen, RexxString *needle, RexxInteger *_start, RexxInteger *_range)
Definition: StringUtil.cpp:254
RexxString::primitiveCompareTo
RexxInteger * primitiveCompareTo(RexxString *other, stringsize_t start, stringsize_t len)
Definition: StringClassMisc.cpp:1083
optionalPositive
size_t optionalPositive(RexxObject *o, size_t d, size_t p)
Definition: RexxCore.h:368
IntegerOne
#define IntegerOne
Definition: RexxCore.h:189
STRING_LITERAL_DOT
#define STRING_LITERAL_DOT
Definition: StringClass.hpp:57
RexxString::caselessLastPosRexx
RexxInteger * caselessLastPosRexx(RexxString *, RexxInteger *, RexxInteger *)
Definition: StringClassMisc.cpp:479
STRING_STEM
#define STRING_STEM
Definition: StringClass.hpp:54
Numerics::minVal
static wholenumber_t minVal(wholenumber_t n1, wholenumber_t n2)
Definition: Numerics.hpp:116
RexxString::primitiveCaselessMatch
bool primitiveCaselessMatch(stringsize_t start, RexxString *other, stringsize_t offset, stringsize_t len)
Definition: StringClassMisc.cpp:963
StringUtil::caselessLastPos
static size_t caselessLastPos(const char *stringData, size_t hastackLen, RexxString *needle, size_t _start, size_t range)
Definition: StringUtil.cpp:358
RexxString::posRexx
RexxInteger * posRexx(RexxString *, RexxInteger *, RexxInteger *)
Definition: StringClassMisc.cpp:682
RexxString::caselessLastPos
size_t caselessLastPos(RexxString *needle, size_t start)
Definition: StringClassMisc.cpp:519
STRING_LITERAL
#define STRING_LITERAL
Definition: StringClass.hpp:56
wholenumber_t
ssize_t wholenumber_t
Definition: rexx.h:229
stringsize_t
size_t stringsize_t
Definition: rexx.h:228
optionalOptionArgument
char optionalOptionArgument(RexxObject *o, char d, size_t p)
Definition: RexxCore.h:358
STRING_NUMERIC
#define STRING_NUMERIC
Definition: StringClass.hpp:58
ARG_FOUR
const int ARG_FOUR
Definition: RexxCore.h:83
StringUtil::caselessCountStr
static size_t caselessCountStr(const char *hayStack, size_t hayStackLength, RexxString *needle)
Definition: StringUtil.cpp:1363
StringUtil::lastPos
static size_t lastPos(const char *stringData, size_t hastackLen, RexxString *needle, size_t _start, size_t _range)
Definition: StringUtil.cpp:276
RexxString::caselessChangeStr
RexxString * caselessChangeStr(RexxString *, RexxString *, RexxInteger *)
Definition: StringClassMisc.cpp:614
positionArgument
stringsize_t positionArgument(RexxObject *argument, size_t position)
Definition: StringClassUtil.cpp:82
Error_Incorrect_method_length
#define Error_Incorrect_method_length
Definition: RexxErrorCodes.h:475
stringArgument
RexxString * stringArgument(RexxObject *object, size_t position)
Definition: RexxCore.h:296
StringUtil::caselessPos
static size_t caselessPos(const char *stringData, size_t haystack_length, RexxString *needle, size_t _start, size_t _range)
Definition: StringUtil.cpp:204
RexxCore.h
RexxString::translate
RexxString * translate(RexxString *, RexxString *, RexxString *, RexxInteger *, RexxInteger *)
Definition: StringClassMisc.cpp:741
StringUtil::countStr
static size_t countStr(const char *hayStack, size_t hayStackLength, RexxString *needle)
Definition: StringUtil.cpp:1338
RexxString::compare
RexxInteger * compare(RexxString *, RexxString *)
Definition: StringClassMisc.cpp:253
RexxString::match
RexxInteger * match(RexxInteger *start_, RexxString *other, RexxInteger *offset_, RexxInteger *len_)
Definition: StringClassMisc.cpp:854
MAX_SYMBOL_LENGTH
const int MAX_SYMBOL_LENGTH
Definition: RexxCore.h:74
StringUtil::memPos
static size_t memPos(const char *string, size_t length, char target)
Definition: StringUtil.cpp:1378
RexxInteger
Definition: IntegerClass.hpp:56
StringUtil::dataType
static RexxObject * dataType(RexxString *String, char Option)
Definition: StringUtil.cpp:1061
RexxString::caselessPos
size_t caselessPos(RexxString *, size_t)
Definition: StringClassMisc.cpp:735
RexxString::primitiveMatch
bool primitiveMatch(stringsize_t start, RexxString *other, stringsize_t offset, stringsize_t len)
Definition: StringClassMisc.cpp:936
SourceFile.hpp
RexxObject
Definition: ObjectClass.hpp:311
RexxString
Definition: StringClass.hpp:119
RexxString::verify
RexxInteger * verify(RexxString *, RexxString *, RexxInteger *, RexxInteger *)
Definition: StringClassMisc.cpp:826