From: <bi...@us...> - 2006-12-20 19:00:52
|
Revision: 86 http://svn.sourceforge.net/oorexx/?rev=86&view=rev Author: bigrixx Date: 2006-12-20 11:00:51 -0800 (Wed, 20 Dec 2006) Log Message: ----------- Some new string methods, plus a start at getting things to compile cleanly on Windows. Modified Paths: -------------- interpreter/trunk/Nmake.inc interpreter/trunk/api/platform/windows/rexxapitypes.h interpreter/trunk/kernel/api/InterpreterInstanceStubs.cpp interpreter/trunk/kernel/classes/ASCIIDBCSStrings.cpp interpreter/trunk/kernel/classes/StringClass.cpp interpreter/trunk/kernel/classes/StringClass.hpp interpreter/trunk/kernel/classes/StringClassMisc.cpp interpreter/trunk/kernel/expression/BuiltinFunctions.cpp interpreter/trunk/kernel/runtime/GlobalData.cpp interpreter/trunk/kernel/runtime/Setup.cpp Modified: interpreter/trunk/Nmake.inc =================================================================== --- interpreter/trunk/Nmake.inc 2006-12-16 04:43:33 UTC (rev 85) +++ interpreter/trunk/Nmake.inc 2006-12-20 19:00:51 UTC (rev 86) @@ -70,7 +70,7 @@ # CC = cl GLOBALCFLAGS = /DORX_VER=$(MAJOR) /DORX_REL=$(MINOR) /DORX_MOD=$(MOD_LVL) \ - $(VCPP_64_FLAG) /GX /Wp64 + $(VCPP_64_FLAG) /GX /Wp64 /D_CRT_SECURE_NO_DEPRECATE !IF "$(DEBUG)" == "1" CFLAGS = /c $(GLOBALCFLAGS) $(INCLUDES) /Zi /Od Modified: interpreter/trunk/api/platform/windows/rexxapitypes.h =================================================================== --- interpreter/trunk/api/platform/windows/rexxapitypes.h 2006-12-16 04:43:33 UTC (rev 85) +++ interpreter/trunk/api/platform/windows/rexxapitypes.h 2006-12-20 19:00:51 UTC (rev 86) @@ -74,7 +74,9 @@ } #endif +#ifndef SIZE_MAX #define SIZE_MAX (~((size_t)0)) +#endif #define SSIZE_MAX ((ssize_t)(SIZE_MAX >> 1)) #define SSIZE_MIN ((ssize_t)SIZE_MAX) Modified: interpreter/trunk/kernel/api/InterpreterInstanceStubs.cpp =================================================================== --- interpreter/trunk/kernel/api/InterpreterInstanceStubs.cpp 2006-12-16 04:43:33 UTC (rev 85) +++ interpreter/trunk/kernel/api/InterpreterInstanceStubs.cpp 2006-12-20 19:00:51 UTC (rev 86) @@ -72,6 +72,12 @@ context.instance->setTrace(setting != 0); } + +RexxBoolean RexxEntry CreateScriptContext(RexxInstance *c, RexxScriptContext **sc, RexxOption *o) +{ + return (RexxBoolean)false; +} + END_EXTERN_C() @@ -80,6 +86,7 @@ INSTANCE_INTERFACE_VERSION, Terminate, AttachThread, + CreateScriptContext, Halt, SetTrace, }; Modified: interpreter/trunk/kernel/classes/ASCIIDBCSStrings.cpp =================================================================== --- interpreter/trunk/kernel/classes/ASCIIDBCSStrings.cpp 2006-12-16 04:43:33 UTC (rev 85) +++ interpreter/trunk/kernel/classes/ASCIIDBCSStrings.cpp 2006-12-20 19:00:51 UTC (rev 86) @@ -69,7 +69,7 @@ /* compare the two bytes */ rc = memcmp(String1, String2, DBCS_BYTELEN); if (rc) { /* mismatch? */ - break; + break; } /* quit if not equal */ String1 += DBCS_BYTELEN; /* step the pointer */ String2 += DBCS_BYTELEN; /* step second pointer */ @@ -89,7 +89,7 @@ /* if characters aren't equal */ rc = (tolower(*String1++) - tolower(*String2++)); if (rc) { /* mismatch? */ - break; + break; } /* quit the loop */ String1++; /* step the pointer */ String2++; /* step second pointer */ @@ -106,50 +106,43 @@ /* Function: Do DBCS string type validation */ /*********************************************************************/ { - //CStr; /* current scan location */ - //EndStr; /* end location */ - //ChkFlag; /* Invalid string flag. */ - //StrLen; /* Input String length. */ - //DBCSNum; /* Number of DBCS bytes. */ - stringsize_t StrLen = STRLEN(String); /* get the length */ - bool ChkFlag = false; /* still valid */ stringsize_t DBCSNum = 0; /* no DBCS bytes */ - EndStr = CStr + StrLen; /* point to end of string */ + stringchar_t *CStr = STRPTR(String); + stringchar_t *EndStr = CStr + StrLen; /* point to end of string */ - /* initialize & declare at same time is faster as only calls one constructor - * also a for loop limits scope of local variables - * can declare two variables of same type in the <initialization> section of a for loop */ - for(stringchar_t * CStr = STRPTR(Sting), - EndStr = CStr + StrLen; CStr < EndStr;) { /* scan until invalid status */ - if (IsDBCS(*CStr)) { /* Current byte DBCS 1st? */ - if (++CStr >= EndStr) { /* but only byte left? */ - ChkFlag = true; /* flag the error */ - break; /* and quit */ + while (CStr < EndStr) + { + if (IsDBCS(*CStr)) { /* Current byte DBCS 1st? */ + // if we have a dangling final char, we can quit now + if (++CStr >= EndStr) + { + return INV_MIXED; } - else { + else + { DBCSNum += 2; /* bump the DBCS count */ } } CStr++; /* step one more character */ } - if (ChkFlag) { /* not valid? */ - return INV_MIXED; - } /* String is invalid. */ - else { /* String is valid */ - if (!DBCSNum) { /* Pure SBCS? */ - return PURE_SBCS; - } - else if (DBCSNum == StrLen) { /* Pure DBCS? */ - return PURE_DBCS; - } - else { - return MIXED; /* DBCS & SBCS combined. */ - } + + if (DBCSNum == 0) // no DBCS is pure single byte + { + return PURE_SBCS; } + else if (DBCSNum == StrLen) // if the DBCS byte count is the entire string, this is pure + { + return PURE_DBCS; + } + else // we have the two combined + { + return MIXED; + } } + stringsize_t RexxString::validDBCS() /*********************************************************************/ /* Function: Validate a character string, returning length */ @@ -160,29 +153,25 @@ { return this->getLength(); /* return quickly */ } - - //EndStr; /* end location */ - //String; /* string scan pointer */ - //Length; /* byte length of the string */ - //CharLength; /* Input HugeString length. */ - //BadChar[4]; /* working buffer for errors */ - //HexBadChar[4]; /* working buffer for errors */ - //HasDBCS; /* found a DBCS character */ stringsize_t Length = STRLEN(this); /* and the length */ stringsize_t CharLength = 0; /* no characters yet */ bool HasDBCS = false; /* no DBCS yet */ + stringchar_t *String = STRPTR(this); + stringchar_t *EndStr = String + Length; - for(stringchar_t * String = STRPTR(this), - EndStr = String + Length; String < Length;) { /* scan until invalid status */ - if (IsDBCS(*String)) { /* Current byte DBCS 1st? */ - if (++String >= EndStr) { /* but only byte left? */ - /* get as character data (and hex) */ - char BadChar[4]; - char HexBadChar[4]; + while (String < EndStr) + { + if (IsDBCS(*String)) + { /* Current byte DBCS 1st? */ + if (++String >= EndStr) + { /* but only byte left? */ + /* get as character data (and hex) */ + char BadChar[4]; + char HexBadChar[4]; sprintf(BadChar, "%c", *String); sprintf(HexBadChar, "%2X", *String); - /* raise an error */ + /* raise an error */ reportException(Error_Invalid_character_char, new_string(BadChar), new_string(HexBadChar)); @@ -192,7 +181,7 @@ String++; /* step one more byte */ CharLength++; /* count a character */ } - + if (!HasDBCS) /* no DBCS characters found? */ { this->Attributes |= STRING_NODBCS; /* flag as no DBCS possible */ @@ -200,6 +189,7 @@ return CharLength; /* return the length */ } + stringsize_t DBCS_CharacterCount( stringchar_t * String, /* string scan pointer */ stringsize_t Length ) /* string byte length */ @@ -208,9 +198,6 @@ /* string */ /*********************************************************************/ { - //EndStr; /* end location */ - //CharLength; /* Input HugeString length. */ - stringsize_t CharLength = 0; /* no characters yet */ for(stringchar_t * EndStr = String + Length; @@ -224,6 +211,7 @@ return CharLength; /* return the length */ } + RexxString *RequiredArg( RexxString *ArgString, /* validated argument string */ stringsize_t *Length, /* returned argument length */ @@ -239,6 +227,7 @@ return ArgString; /* return the string value */ } + RexxString *OptionalArg( RexxString *ArgString, /* validated argument string */ RexxString *Default, /* default value */ @@ -290,15 +279,12 @@ /* of characters */ /*********************************************************************/ { - //CStr; /* current string location */ - //EndStr; /* end of string */ - stringchar_t * CStr = *String; /* point to the string */ stringchar_t * EndStr = CStr + *Length; /* point to the end of string */ while (*CharLen) { /* while more characters */ if (CStr >= EndStr) { /* reached the end */ - break; + break; } /* This failed */ /* DBCS character? */ if (IsDBCS(*CStr)) { @@ -311,7 +297,6 @@ } *Length -= CStr - *String; /* reduce the length */ *String = CStr; /* set the new pointer */ - /* finished */ } void DBCS_IncByte( @@ -323,9 +308,6 @@ /* of bytes. Will not split a DBCS character */ /*********************************************************************/ { - //CStr; /* current string location */ - //EndStr; /* end of string */ - stringchar_t * CStr = *String; /* copy the pointer */ stringchar_t * EndStr = CStr + *Length; /* point to the end of string */ @@ -358,14 +340,9 @@ /* count. */ /*********************************************************************/ { - //stringchar_t * Scan; /* scan pointer */ - //stringsize_t Length; /* length to scan */ - stringchar_t * Scan = *String; /* point to data */ - - for(stringsize_t Length = *StringLength; - Length;) { /* scan entire string */ - + stringsize_t Length = *StringLength; + while (Length > 0) { if (*Scan == ch_SPACE) { /* if SBCS blank */ Length--; /* reduce the length by one */ Scan++; /* step the pointer one */ @@ -375,7 +352,7 @@ Scan += DBCS_BYTELEN; /* step pointer also */ } else { /* found a non-blank */ - break; + break; } /* just quit the loop */ } /* fell through, all blanks */ @@ -390,27 +367,29 @@ /* Function: Skip SBCS/DBCS non-blanks and decrement size.*/ /*********************************************************************/ { - //Scan; /* scan pointer */ - stringchar_t * Scan = *String; /* point to data */ + stringsize_t Length = *StringLength; - for(stringsize_t Length = *StringLength; - Length;) { /* scan entire string */ + while (Length > 0) + { if (*Scan == ch_SPACE || /* either SBCS or */ - IsDBCSBlank(Scan)) { /* DBCS blank? */ - + IsDBCSBlank(Scan)) + { /* DBCS blank? */ + break; - } /* done */ - else if (IsDBCS(*Scan)) { /* DBCS character? */ + } /* done */ + else if (IsDBCS(*Scan)) + { /* DBCS character? */ Length -= DBCS_BYTELEN; /* reduce length two */ Scan += DBCS_BYTELEN; /* step pointer also */ } - else { /* if SBCS blank */ + else + { /* if SBCS blank */ Length--; /* reduce the length by one */ Scan++; /* step the pointer one */ } } - /* fell through, all blanks */ + /* fell through, all blanks */ *String = Scan; /* set pointer one past */ *StringLength = Length; /* update the length */ } @@ -422,16 +401,12 @@ /* Function: Adjust string length, removing blanks */ /*********************************************************************/ { - //Count; /* size to scan */ - //BlankStr; /* start of last blank part */ - //Scan; /* scan pointer */ - stringchar_t * BlankStr = NULL; /* null the pointer */ stringchar_t * Scan = *String; /* copy the pointer */ /* loop through entire string */ for (stringsize_t Count = *StringLength; Count; ) { - /* should handle the same cases as the commented section below */ + /* should handle the same cases as the commented section below */ if(IsDBCSBlank(Scan) || IsDBCS(*Scan)) { if (!BlankStr) { BlankStr = Scan; @@ -496,41 +471,36 @@ int rc = COMP_EQUAL; /* Comparison default. */ - /* while still characters */ - /* left and they still compare */ - while (Length && rc == COMP_EQUAL) { - Cnt1 = IsDBCS(*Str1) ? DBCS_BYTELEN : SBCS_BYTELEN; - //if (IsDBCS(*Str1)) { /* if DBCS, then */ - // Cnt1 = DBCS_BYTELEN; /* compare two bytes */ - //} - //else { - // Cnt1 = SBCS_BYTELEN; /* else just a single byte */ - //} - Cnt2 = IsDBCS(*Str2) ? DBCS_BYTELEN : SBCS_BYTELEN; - //if (IsDBCS(*Str2)) { /* if DBCS, then */ - // Cnt2 = DBCS_BYTELEN; /* compare two bytes */ - //} - //else { - // Cnt2 = SBCS_BYTELEN; /* else just a single byte */ - //} - if (Cnt1 == Cnt2) { /* equal length? */ - if (Cnt1 == DBCS_BYTELEN) { /* Comparing DBCS characters? */ + /* while still characters */ + /* left and they still compare */ + while (Length && rc == COMP_EQUAL) + { + Cnt1 = IsDBCS(*Str1) ? DBCS_BYTELEN : SBCS_BYTELEN; + Cnt2 = IsDBCS(*Str2) ? DBCS_BYTELEN : SBCS_BYTELEN; + if (Cnt1 == Cnt2) + { /* equal length? */ + if (Cnt1 == DBCS_BYTELEN) + { /* Comparing DBCS characters? */ rc = *Str1++ == *Str2++; /* do the comparision */ - if (rc == 0) { /* compared equal? */ + if (rc == 0) + { /* compared equal? */ rc = *Str1++ == *Str2++; /* compare the second bytes */ - } + } } - else { /* compare the uppercase versions */ + else + { /* compare the uppercase versions */ rc = toupper(*Str1++) == toupper(*Str2++); } Length -= Cnt1; /* reduce the length */ } - else if (Cnt1 == DBCS_BYTELEN) { /* 1st DBCS and 2nd SBCS? */ + else if (Cnt1 == DBCS_BYTELEN) + { /* 1st DBCS and 2nd SBCS? */ return COMP_GREATER; /* the first is greater */ - } - else { /* 1st SBCS and 2nd DBCS */ + } + else + { /* 1st SBCS and 2nd DBCS */ return COMP_LESS; /* 2nd is the larger */ - } + } } return rc; /* Return the result. */ } @@ -554,10 +524,10 @@ *Diff = 0; /* Different position */ int rc = COMP_EQUAL; /* Comparison default. */ - + /* if no Pad, then PadSize 0 */ stringsize_t PadSize = (!Pad) ? 0 : strlen((char *)Pad); - + /* while still characters */ /* left and they still compare */ while (((Len1) || (Len2)) && (rc == COMP_EQUAL)) { @@ -582,7 +552,7 @@ Cnt1 = PadSize; /* use the pad length */ Comp1 = Pad; /* set compare location */ } - + if (Len2) { /* now repeat for Str2 */ Comp2 = Str2; /* set compare location */ if (IsDBCS(*Str2)) { /* if DBCS, then */ @@ -603,7 +573,7 @@ Cnt2 = PadSize; /* use the pad length */ Comp2 = Pad; /* set compare location */ } - + if (Cnt1 == Cnt2) { /* equal length? */ if (*Comp1 == *Comp2) { /* both equal? */ if (Cnt1 == DBCS_BYTELEN) { /* might be DBCS */ @@ -622,14 +592,14 @@ } /* bump char position */ } else { - rc = (*Comp1 > *Comp2) ? COMP_GREATER : COMP_LESS; + rc = (*Comp1 > *Comp2) ? COMP_GREATER : COMP_LESS; } } - else { + else { rc = (Cnt1 == DBCS_BYTELEN) ? COMP_GREATER : COMP_LESS; } } - + if (rc == COMP_EQUAL) { /* still equal? */ *Diff = 0; } /* no difference point */ @@ -652,13 +622,11 @@ /* returned */ /*********************************************************************/ { - //End; /* end of string */ - stringchar_t * Retval = NULL; /* set default return value */ - + if (NeedleLen <= HaystackLen) { /* short enough to search? */ /* point to end position */ - for (stringchar_t * End = Haystack + (HaystackLen - NeedleLen); + for (stringchar_t * End = Haystack + (HaystackLen - NeedleLen); Haystack < End;) { /* check this position */ if (!memcmp(Haystack, Needle, NeedleLen)) { @@ -705,10 +673,6 @@ stringchar_t * String, /* searched string */ stringsize_t Length ) /* size to search */ { - //EndStr; /* search end position */ - //Position; /* located position */ - //Count; /* character count */ - stringchar_t * EndStr = String + Length; /* step to the end */ stringsize_t Position = 0; /* set default position */ stringsize_t Count = 0; /* set initial character count */ @@ -1253,7 +1217,7 @@ stringchar_t conv[2]; /* DBCS 1ST and 2ND byte. */ } convert; - + int TableNum; /* current country table */ int TableChr; /* Table number for character. */ @@ -1318,13 +1282,13 @@ stringchar_t * *output ) /* Target SBCS. */ { stringsize_t i; /* Use for index of table. */ - + union convert { /* Use to get DBCS bytes */ uint16_t convchar; /* From unsigned int DBCS */ stringchar_t conv[2]; /* DBCS 1ST and 2ND byte. */ } convert; - + stringsize_t TableNum; stringchar_t * outspot = *output; /* copy the pointer */ @@ -1393,10 +1357,10 @@ if (CharLen >= 1) { /* If Charlen is zero or */ /* minus, NOP. */ - + stringsize_t TailLen; /* length of tail string */ stringchar_t * Cpos; /* character position */ - + if (Direction < 0) { /* Left. */ /* get front character length */ stringsize_t BaseLen = DBCS_CharacterCount(STRPTR(this), Start); @@ -1600,7 +1564,7 @@ /* validate the pad character */ stringchar_t * PadChar = ValidatePad(pad, (const stringchar_t *)" "); stringsize_t PadSize = strlen((char *)PadChar); /* get the pad size too */ - + if (!SubstrSize) { /* zero bytes requested? */ Retval = OREF_NULLSTRING; /* this is a null string */ } @@ -1645,15 +1609,6 @@ RexxString *RexxString::DBCSdelstr(RexxInteger *position, RexxInteger *plength) { - //StringChar; /* size of input string */ - //StartPos; /* substr start position */ - //DeleteSize; /* size of deletion */ - //StringLength; /* length of input string */ - //FrontLength; /* length of front part */ - //BackLength; /* length of back part */ - //FrontEnd; /* end of front part */ - //BackEnd; /* end of back part */ - //BackStart; /* start of back part */ RexxString *Retval; /* return string */ stringsize_t StringChar = ValidDBCS(this); /* get string length */ @@ -1668,7 +1623,7 @@ /* step to the start */ DBCS_IncChar(&FrontEnd, &StringLength, &StartPos); if (StartPos) { /* skip everything? */ - Retval = this; + Retval = this; } /* return string unchanged */ else { stringchar_t * BackStart = FrontEnd; /* copy the pointer */ @@ -1702,14 +1657,6 @@ RexxString *RexxString::DBCSsubWord(RexxInteger *position, RexxInteger *plength) { - //StringChar; /* size of input string */ - //StartPos; /* substr start position */ - //SubwordSize; /* size of substring */ - //StringLength; /* byte length of input string */ - //Scan; /* scan pointer */ - //SubwordPtr; /* pointer to subword part */ - //WordPtr; /* pointer to word end */ - // WordLength; /* length of word start */ RexxString *Retval; /* return string */ stringsize_t StringChar = ValidDBCS(this); /* get size of input string */ @@ -1771,15 +1718,6 @@ RexxString *RexxString::DBCSdelWord(RexxInteger *position, RexxInteger *plength) { - //StringChar; /* size of input string */ - //StartPos; /* substr start position */ - //DeleteSize; /* size of deletion */ - //StringLength; /* length of input string */ - //FrontLength; /* length of front part */ - //BackStart; /* start of back part */ - //FrontPtr; /* start of front part */ - //Scan; /* scanning pointer */ - //CopyPtr; /* pointer for copying strings */ RexxString *Retval; /* return string */ stringsize_t StringChar = ValidDBCS(this); /* get string length */ @@ -2086,9 +2024,8 @@ else { /* looking for pure DBCS */ return (MixedType == PURE_DBCS) ? TheTrueObject : - TheFalseObject; + TheFalseObject; } - return Retval; /* Return DBCS_datatype */ } /*********************************************************************/ Modified: interpreter/trunk/kernel/classes/StringClass.cpp =================================================================== --- interpreter/trunk/kernel/classes/StringClass.cpp 2006-12-16 04:43:33 UTC (rev 85) +++ interpreter/trunk/kernel/classes/StringClass.cpp 2006-12-20 19:00:51 UTC (rev 86) @@ -1157,6 +1157,8 @@ return this; /* return this unchanged */ } + + RexxString *RexxString::stringTrace() /******************************************************************************/ /* Function: Translate a string to "traceable" form, removing non-displayable*/ @@ -1220,6 +1222,7 @@ return newCopy; /* return the converted string */ } + RexxString *RexxString::lower() /******************************************************************************/ /* Function: Translate a string to lower case */ @@ -1273,6 +1276,128 @@ return newstring; /* return the new copy */ } + +/** + * Rexx exported method stub for the lower() method. + * + * @param start The optional starting location. Defaults to the first character + * if not specified. + * @param length The length to convert. Defaults to the segment from the start + * position to the end of the string. + * + * @return A new string object with the case conversion applied. + */ +RexxString *RexxString::lowerRexx(RexxInteger *start, RexxInteger *length) +{ + stringsize_t startPos = optionalPositionArgument(start, 1, ARG_ONE) - 1; + stringsize_t rangeLength = optionalLengthArgument(length, strLength(), ARG_TWO); + + // if we're starting beyond the end bounds, return unchanged + if (startPos > strLength()) + { + return this; + } + + rangeLength = min(rangeLength, strLength() - startPos); + + // a zero length value is also a non-change. + if (rangeLength == 0) + { + return this; + } + + return lower(startPos, rangeLength); +} + + +/** + * Rexx exported method stub for the upper() method. + * + * @param start The optional starting location. Defaults to the first character + * if not specified. + * @param length The length to convert. Defaults to the segment from the start + * position to the end of the string. + * + * @return A new string object with the case conversion applied. + */ +RexxString *RexxString::upperRexx(RexxInteger *start, RexxInteger *length) +{ + stringsize_t startPos = optionalPositionArgument(start, 1, ARG_ONE) - 1; + stringsize_t rangeLength = optionalLengthArgument(length, strLength(), ARG_TWO); + + // if we're starting beyond the end bounds, return unchanged + if (startPos > strLength()) + { + return this; + } + + rangeLength = min(rangeLength, strLength() - startPos); + + // a zero length value is also a non-change. + if (rangeLength == 0) + { + return this; + } + + return upper(startPos, rangeLength); +} + + + +/** + * Lowercase a portion of a Rexx string, returning a new string object. This + * method assumes the offset and length are already valid + * for this string object. + * + * @param start The starting offset of the segment to lowercase (origin 0). + * + * @param length The length to lowercase. + * + * @return A new string object with the case conversion applied. + */ +RexxString *RexxString::lower(stringsize_t offset, stringsize_t length) +{ + // get a copy of the string + RexxString *newstring = extract(0, strLength()); + + stringchar_t *data = (stringchar_t *)newstring->getStringData() + offset; + // now uppercase in place + for (i = 0; i < length; i++) { + *data = tolower(*data); + data++; + } + return newstring; +} + + + +/** + * Uppercase a portion of a Rexx string, returning a new string + * object. This method assumes the offset and length are + * already valid for this string object. + * + * @param start The starting offset of the segment to uppercase + * (origin 0). + * + * @param length The length to lowercase. + * + * @return A new string object with the case conversion applied. + */ +RexxString *RexxString::upper(stringsize_t offset, stringsize_t length) +{ + // get a copy of the string + RexxString *newstring = extract(0, strLength()); + + stringchar_t *data = (stringchar_t *)newstring->getStringData() + offset; + // now uppercase in place + for (i = 0; i < length; i++) { + *data = tolower(*data); + data++; + } + return newstring; +} + + RexxInteger *RexxString::integerValue( stringsize_t digits) /* precision to use */ /******************************************************************************/ Modified: interpreter/trunk/kernel/classes/StringClass.hpp =================================================================== --- interpreter/trunk/kernel/classes/StringClass.hpp 2006-12-16 04:43:33 UTC (rev 85) +++ interpreter/trunk/kernel/classes/StringClass.hpp 2006-12-20 19:00:51 UTC (rev 86) @@ -139,8 +139,12 @@ RexxString *concatBlank(RexxObject *); bool checkLower(); RexxString *upper(); + RexxString *upper(stringsize_t, stringsize_t); + RexxString *upperRexx(RexxInteger *, RexxInteger *); RexxString *stringTrace(); RexxString *lower(); + RexxString *lower(stringsize_t, stringsize_t); + RexxString *lowerRexx(RexxInteger *, RexxInteger *); void setNumberString(RexxObject *); RexxString *concatWith(RexxString *, stringchar_t); @@ -196,7 +200,8 @@ RexxInteger *compare(RexxString *, RexxString *); RexxString *copies(RexxInteger *); RexxObject *dataType(RexxString *); - RexxInteger *lastPos(RexxString *, RexxInteger *); + stringsize_t lastPos(RexxString *); + RexxInteger *lastPosRexx(RexxString *, RexxInteger *); RexxInteger *posRexx(RexxString *, RexxInteger *); RexxString *translate(RexxString *, RexxString *, RexxString *); RexxInteger *verify(RexxString *, RexxString *, RexxInteger *); Modified: interpreter/trunk/kernel/classes/StringClassMisc.cpp =================================================================== --- interpreter/trunk/kernel/classes/StringClassMisc.cpp 2006-12-16 04:43:33 UTC (rev 85) +++ interpreter/trunk/kernel/classes/StringClassMisc.cpp 2006-12-20 19:00:51 UTC (rev 86) @@ -590,7 +590,8 @@ return Retval; /* fall through, not found */ } -RexxInteger *RexxString::lastPos( + +RexxInteger *RexxString::lastPosRexx( RexxString *needle, /* target search string */ RexxInteger *start) /* starting position */ /******************************************************************************/ @@ -634,6 +635,46 @@ return Retval; /* return match location */ } + +/** + * Primitive implementation of a lastpos search. + * + * @param needle The search needle. + * @param start The starting position (origin 1). + * + * @return Returns the last match position, searching back from the start + * position. The starting position is the right-most character + * of the past possible match (as if the string was truncated + * at start). + */ +stringsize_t*RexxString::lastPos(RexxString *needle, stringsize_t start) +{ + stringsize_t haystackLen = this->getLength(); /* get the haystack length */ + stringsize_t needleLen = needle->getLength(); /* and get the length too */ + + // no match possible if either string is null + if (needleLen == 0 || haystackLen == 0) + { + return 0; + } + else + { + // get the start position for the search. + start = min(start, haystackLen); + /* do the search */ + stringchar_t *matchLocation = LStrStrb(needle->getStringData(), needleLen, (stringchar_t *)this->getStringData(), haystackLen); + if (matchLocation == NULL) + { + return 0; + } + else + { + return matchLocation - this->getStringData() + 1; + } + } +} + + stringsize_t RexxString::countStr(RexxString *needle) /******************************************************************************/ /* Function: Count occurrences of one string in another. */ @@ -739,6 +780,160 @@ return new_integer(this->pos(needle, start - 1)); } + +/** + * Extract the substring that occurs before a needle match postion. + * + * @param needle The search needle. If this is a null string, it will match to the end. + * + * @return The substring before the match needle match position. If the + * needle is not found, the entire string is returned. Like the + * parse instruction, a null string matches to the end. + */ +RexxString *RexxString::before( + RexxString *needle, + RexxInteger *start) +{ + + // the needle must be a string value + needle = REQUIRED_STRING(needle, ARG_ONE); + + stringsize_t searchStart = optionalPositionArgument(start, 1, ARG_TWO); + + // if this a null string, it matches everything. + if (needle->getLength() == 0) + { + if (searchStart == 1) + { + return this; + } + else { + return this->extract(searchStart - 1, strLength() - (searchStart - 1)); + } + } + + // look for the first match + match = this->pos(needle, searchStart - 1); + // no match, we return the entire string + if (match == 0) + { + if (searchStart == 1) + { + return this; + } + else { + return this->extract(searchStart - 1, strLength() - (searchStart - 1)); + } + } + else + { + // just extract the substring + return this->extract(searchStart - 1, match - searchStart); + } +} + + + +/** + * Extract the substring that occurs before a last needle match + * postion. + * + * @param needle The search needle. If this is a null string, + * it will match to the beginning. + * + * @return The substring before the match needle match position. If the + * needle is not found, the entire string is returned. Like the + * parse instruction, a null string matches to the end. + */ +RexxString *RexxString::beforeLast( + RexxString *needle) +{ + + // the needle must be a string value + needle = REQUIRED_STRING(needle, ARG_ONE); + + // if this a null string, it matches everything. + if (needle->getLength() == 0) + { + return this; + } + // look for the first match + match = this->pos(needle, 0); + // no match, we return the entire string + if (match == 0) + { + return this; + } + else + { + // just extract the substring + return this->extract(0, match - 1); + } +} + + + + +/** + * Extract the substring that occurs after a needle match + * postion. + * + * @param needle The search needle. If this is a null string, it will match to the end. + * + * @return The substring before the match needle match position. If the + * needle is not found, a null string is returned. Like + * the parse instruction, a null string matches to the + * end. + */ +RexxString *RexxString::after( + RexxString *needle, + RexxInteger *start) +{ + // the needle must be a string value + needle = REQUIRED_STRING(needle, ARG_ONE); + + stringsize_t searchStart = optionalPositionArgument(start, 0, ARG_TWO); + + // if this a null string, it matches to the end, so there's no + // "after life" + if (needle->getLength() == 0) + { + return OREF_NULLSTRING; + } + + // look for the first match + match = this->pos(needle, searchStart - 1); + // no match, we return a null string + if (match == 0) + { + if (searchStart == 1) + { + return this; + } + else { + return this->extract(searchStart - 1, strLength() - searchStart + 1); + } + } + else + { + // convert this to a 0-based offset for the extract, positioned after the needle. + match = match + needle->getLength() - 1; + stringsize_t length = this->getLength() - match; + + if (length == 0) + { + return OREF_NULLSTRING; + } + else + { + // just extract the substring + return this->extract(match, length); + + } + } +} + + stringsize_t RexxString::pos( RexxString *needle, /* Target needle string */ stringsize_t start) /* Start position */ Modified: interpreter/trunk/kernel/expression/BuiltinFunctions.cpp =================================================================== --- interpreter/trunk/kernel/expression/BuiltinFunctions.cpp 2006-12-16 04:43:33 UTC (rev 85) +++ interpreter/trunk/kernel/expression/BuiltinFunctions.cpp 2006-12-20 19:00:51 UTC (rev 86) @@ -269,7 +269,7 @@ /* start position is optional */ start = optionalInteger(LASTPOS, start); /* go perform the lastpos function */ - return haystack->lastPos(needle, start); + return haystack->lastPosRexx(needle, start); } #define REVERSE_MIN 1 Modified: interpreter/trunk/kernel/runtime/GlobalData.cpp =================================================================== --- interpreter/trunk/kernel/runtime/GlobalData.cpp 2006-12-16 04:43:33 UTC (rev 85) +++ interpreter/trunk/kernel/runtime/GlobalData.cpp 2006-12-20 19:00:51 UTC (rev 86) @@ -330,7 +330,7 @@ CPPM(RexxString::compare), CPPM(RexxString::copies), CPPM(RexxString::dataType), -CPPM(RexxString::lastPos), +CPPM(RexxString::lastPosRexx), CPPM(RexxString::posRexx), CPPM(RexxString::translate), CPPM(RexxString::verify), @@ -349,6 +349,8 @@ CPPM(RexxString::x2d), CPPM(RexxString::encodebase64), CPPM(RexxString::decodebase64), +CPPM(RexxString::upper), +CPPM(RexxString::lower), CPPM(RexxString::format), CPPM(RexxString::trunc), CPPM(RexxString::x2dC2d), Modified: interpreter/trunk/kernel/runtime/Setup.cpp =================================================================== --- interpreter/trunk/kernel/runtime/Setup.cpp 2006-12-16 04:43:33 UTC (rev 85) +++ interpreter/trunk/kernel/runtime/Setup.cpp 2006-12-20 19:00:51 UTC (rev 86) @@ -611,7 +611,7 @@ defineKernelMethod(CHAR_COMPARE ,TheStringBehaviour, CPPM(RexxString::compare), 2); defineKernelMethod(CHAR_COPIES ,TheStringBehaviour, CPPM(RexxString::copies), 1); defineKernelMethod(CHAR_COUNTSTR ,TheStringBehaviour, CPPM(RexxString::countStrRexx), 1); - defineKernelMethod(CHAR_LASTPOS ,TheStringBehaviour, CPPM(RexxString::lastPos), 2); + defineKernelMethod(CHAR_LASTPOS ,TheStringBehaviour, CPPM(RexxString::lastPosRexx), 2); defineKernelMethod(CHAR_POS ,TheStringBehaviour, CPPM(RexxString::posRexx), 2); defineKernelMethod(CHAR_TRANSLATE ,TheStringBehaviour, CPPM(RexxString::translate), 3); defineKernelMethod(CHAR_VERIFY ,TheStringBehaviour, CPPM(RexxString::verify), 3); @@ -628,6 +628,8 @@ defineKernelMethod(CHAR_X2D ,TheStringBehaviour, CPPM(RexxString::x2d), 1); defineKernelMethod(CHAR_ENCODEBASE64 ,TheStringBehaviour, CPPM(RexxString::encodebase64), 0); defineKernelMethod(CHAR_DECODEBASE64 ,TheStringBehaviour, CPPM(RexxString::decodebase64), 0); + defineKernelMethod(CHAR_LOWER ,TheStringBehaviour, CPPM(RexxString::lowerRexx), 0); + defineKernelMethod(CHAR_UPPER ,TheStringBehaviour, CPPM(RexxString::upperRexx), 0); defineKernelMethod(CHAR_MAKESTRING ,TheStringBehaviour, CPPM(RexxObject::makeStringRexx), 0); defineKernelMethod(CHAR_ABS ,TheStringBehaviour, CPPM(RexxString::abs), 0); defineKernelMethod(CHAR_MAX ,TheStringBehaviour, CPPM(RexxString::Max), A_COUNT); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |