diff --git a/ChangeLog b/ChangeLog index 64c0bb8b2..fe27f767b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Thu May 20 10:40:00 1999 Richard Frith-Macdonald + + * Source/GSeq.h: Add support for comparison and search. + * Source/NSString.m: Use comparison and search functions from GSeq.h + * Source/NSGString.m: Use comparison and search functions from GSeq.h + * Source/NSGCString.m: Use comparison and search functions from GSeq.h + * Source/Makefile.postamble: Make all string files depend on GSeq.h + Wed May 19 21:25:00 1999 Richard Frith-Macdonald * Source/GSeq.h: New file to replace NSGSequence stuff diff --git a/Source/GSeq.h b/Source/GSeq.h index 909b87154..c027ab58f 100644 --- a/Source/GSeq.h +++ b/Source/GSeq.h @@ -23,21 +23,57 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + * Warning - this contains hairy code - handle with care. + * The first part of this file contains variable and constant definitions + * plus inline function definitions for handling sequences of unicode + * characters. It is bracketed in preprocessor conditionals so that it + * is only ever included once. + * The second part of the file contains inline function definitions that + * are designed to be modified depending on the defined macros at the + * point where they are included. This is meant to be included multiple + * times so the same code can be used for NSString, NSGString, and + * NSGCString objects. + */ + +#ifndef __GSeq_h_GNUSTEP_BASE_INCLUDE +#define __GSeq_h_GNUSTEP_BASE_INCLUDE + +/* + * Some standard selectors for frequently used methods. + */ +static SEL caiSel = @selector(characterAtIndex:); +static SEL gcrSel = @selector(getCharacters:range:); +static SEL ranSel = @selector(rangeOfComposedCharacterSequenceAtIndex:); + +/* + * The maximum decompostion level for composite unicode characters. + */ #define MAXDEC 18 +/* + * The structure definition for handling a unicode character sequence + * for a single character. + */ typedef struct { unichar *chars; unsigned count; unsigned capacity; BOOL normalized; } GSeqStruct; - typedef GSeqStruct *GSeq; +/* + * A macro to define a GSeqStruct variable capable of holding a + * unicode character sequence of the specified length. + */ #define GSEQ_MAKE(BUF, SEQ, LEN) \ unichar BUF[LEN * MAXDEC + 1]; \ GSeqStruct SEQ = { BUF, LEN, LEN * MAXDEC, 0 } +/* + * A function to normalize a unicode character sequence. + */ static inline void GSeq_normalize(GSeq seq) { unsigned count = seq->count; @@ -123,6 +159,10 @@ static inline void GSeq_normalize(GSeq seq) } } +/* + * A function to compare two unicode character sequences normalizing if + * required. + */ static inline NSComparisonResult GSeq_compare(GSeq s0, GSeq s1) { unsigned i; @@ -176,3 +216,814 @@ static inline void GSeq_uppercase(GSeq seq) s[i] = uni_toupper(s[i]); } +/* + * Specify NSString, NSGString or NSGCString + */ +#define GSEQ_NS 0 +#define GSEQ_US 1 +#define GSEQ_CS 2 + +/* + * Structures to access NSGString and NSGCString ivars. + */ +typedef struct { + @defs(NSGString) +} NSGStringStruct; + +typedef struct { + @defs(NSGCString) +} NSGCStringStruct; + +/* + * Definitions for bitmask of search options. These MUST match the + * enumeration in NSString.h + */ +#define FCLS 3 +#define BCLS 7 +#define FLS 2 +#define BLS 6 +#define FCS 1 +#define BCS 5 +#define FS 0 +#define BS 4 +#define FCLAS 11 +#define BCLAS 15 +#define FLAS 10 +#define BLAS 14 +#define FCAS 9 +#define BCAS 13 +#define FAS 8 +#define BAS 12 + +#endif /* __GSeq_h_GNUSTEP_BASE_INCLUDE */ + +/* + * Set up macros for dealing with 'self' on the basis of GSQ_S + */ +#if GSEQ_S == GSEQ_US +#define GSEQ_ST NSGStringStruct* +#define GSEQ_SLEN s->_count +#define GSEQ_SGETC(I) s->_contents_chars[I] +#define GSEQ_SGETR(B,R) memcpy(B, &s->_contents_chars[R.location], 2*(R).length) +#define GSEQ_SRANGE(I) (*srImp)((id)s, ranSel, I) +#else +#if GSEQ_S == GSEQ_CS +#define GSEQ_ST NSGCStringStruct* +#define GSEQ_SLEN s->_count +#define GSEQ_SGETC(I) (unichar)s->_contents_chars[I] +#define GSEQ_SGETR(B,R) ( { \ + unsigned _lcount = 0; \ + while (_lcount < (R).length) \ + { \ + (B)[_lcount] = (unichar)s->_contents_chars[(R).location + _lcount]; \ + _lcount++; \ + } \ +} ) +#define GSEQ_SRANGE(I) (NSRange){I,1} +#else +#define GSEQ_ST NSString* +#define GSEQ_SLEN [s length] +#define GSEQ_SGETC(I) (*scImp)(s, caiSel, I) +#define GSEQ_SGETR(B,R) (*sgImp)(s, gcrSel, B, R) +#define GSEQ_SRANGE(I) (*srImp)(s, ranSel, I) +#endif +#endif + +/* + * Set up macros for dealing with 'other' string on the basis of GSQ_O + */ +#if GSEQ_O == GSEQ_US +#define GSEQ_OT NSGStringStruct* +#define GSEQ_OLEN o->_count +#define GSEQ_OGETC(I) o->_contents_chars[I] +#define GSEQ_OGETR(B,R) memcpy(B, &o->_contents_chars[R.location], 2*(R).length) +#define GSEQ_ORANGE(I) (*orImp)((id)o, ranSel, I) +#else +#if GSEQ_O == GSEQ_CS +#define GSEQ_OT NSGCStringStruct* +#define GSEQ_OLEN o->_count +#define GSEQ_OGETC(I) (unichar)o->_contents_chars[I] +#define GSEQ_OGETR(B,R) ( { \ + unsigned _lcount = 0; \ + while (_lcount < (R).length) \ + { \ + (B)[_lcount] = (unichar)o->_contents_chars[(R).location + _lcount]; \ + _lcount++; \ + } \ +} ) +#define GSEQ_ORANGE(I) (NSRange){I,1} +#else +#define GSEQ_OT NSString* +#define GSEQ_OLEN [o length] +#define GSEQ_OGETC(I) (*ocImp)(o, caiSel, I) +#define GSEQ_OGETR(B,R) (*ogImp)(o, gcrSel, B, R) +#define GSEQ_ORANGE(I) (*orImp)(o, ranSel, I) +#endif +#endif + +/* + * If a string comparison function is required, implement it. + */ +#ifdef GSEQ_STRCOMP +static inline NSComparisonResult +GSEQ_STRCOMP(NSString *ss, NSString *os, unsigned mask, NSRange aRange) +{ + GSEQ_ST s = (GSEQ_ST)ss; + GSEQ_OT o = (GSEQ_OT)os; + unsigned oLength; /* Length of other. */ + unsigned sLength = GSEQ_SLEN; + + if (aRange.location > sLength) + [NSException raise: NSRangeException format: @"Invalid location."]; + if (aRange.length > (sLength - aRange.location)) + [NSException raise: NSRangeException format: @"Invalid location+length."]; + + oLength = GSEQ_OLEN; + if (sLength - aRange.location == 0) + { + if (oLength == 0) + { + return NSOrderedSame; + } + return NSOrderedAscending; + } + else if (oLength == 0) + { + return NSOrderedDescending; + } + + if (mask & NSLiteralSearch) + { + unsigned i; + unsigned sLen = aRange.length; + unsigned oLen = oLength; + unsigned end; +#if GSEQ_S == GSEQ_NS + void (*sgImp)(NSString*, SEL, unichar*, NSRange); + unichar sBuf[sLen]; +#else +#if GSEQ_S == GSEQ_US + unichar *sBuf; +#else + char *sBuf; +#endif +#endif +#if GSEQ_O == GSEQ_NS + void (*ogImp)(NSString*, SEL, unichar*, NSRange); + unichar oBuf[oLen]; +#else +#if GSEQ_O == GSEQ_US + unichar *oBuf; +#else + char *oBuf; +#endif +#endif + +#if GSEQ_S == GSEQ_NS + sgImp = (void (*)())[(id)s methodForSelector: gcrSel]; + GSEQ_SGETR(sBuf, aRange); +#else + sBuf = &s->_contents_chars[aRange.location]; +#endif +#if GSEQ_O == GSEQ_NS + ogImp = (void (*)())[(id)o methodForSelector: gcrSel]; + GSEQ_OGETR(oBuf, NSMakeRange(0, oLen)); +#else + oBuf = o->_contents_chars; +#endif + + if (oLen < sLen) + end = oLen; + else + end = sLen; + + if (mask & NSCaseInsensitiveSearch) + { + for (i = 0; i < end; i++) + { + unichar c1 = uni_tolower((unichar)sBuf[i]); + unichar c2 = uni_tolower((unichar)oBuf[i]); + + if (c1 < c2) + return NSOrderedAscending; + if (c1 > c2) + return NSOrderedDescending; + } + } + else + { + for (i = 0; i < end; i++) + { + if ((unichar)sBuf[i] < (unichar)oBuf[i]) + return NSOrderedAscending; + if ((unichar)sBuf[i] > (unichar)oBuf[i]) + return NSOrderedDescending; + } + } + if (sLen > oLen) + return NSOrderedDescending; + else if (sLen < oLen) + return NSOrderedAscending; + else + return NSOrderedSame; + } + else + { + unsigned start = aRange.location; + unsigned end = start + aRange.length; + unsigned sCount = start; + unsigned oCount = 0; + NSComparisonResult result; +#if GSEQ_S == GSEQ_NS || GSEQ_S == GSEQ_US + NSRange (*srImp)(NSString*, SEL, unsigned); +#endif +#if GSEQ_O == GSEQ_NS || GSEQ_O == GSEQ_US + NSRange (*orImp)(NSString*, SEL, unsigned); +#endif +#if GSEQ_S == GSEQ_NS + void (*sgImp)(NSString*, SEL, unichar*, NSRange); +#endif +#if GSEQ_O == GSEQ_NS + void (*ogImp)(NSString*, SEL, unichar*, NSRange); +#endif + +#if GSEQ_S == GSEQ_NS || GSEQ_S == GSEQ_US + srImp = (NSRange (*)())[(id)s methodForSelector: ranSel]; +#endif +#if GSEQ_O == GSEQ_NS || GSEQ_O == GSEQ_US + orImp = (NSRange (*)())[(id)o methodForSelector: ranSel]; +#endif +#if GSEQ_S == GSEQ_NS + sgImp = (void (*)())[(id)s methodForSelector: gcrSel]; +#endif +#if GSEQ_O == GSEQ_NS + ogImp = (void (*)())[(id)o methodForSelector: gcrSel]; +#endif + + + while (sCount < end) + { + if (oCount >= oLength) + { + return NSOrderedDescending; + } + else if (sCount >= sLength) + { + return NSOrderedAscending; + } + else + { + NSRange sRange = GSEQ_SRANGE(sCount); + NSRange oRange = GSEQ_ORANGE(oCount); + GSEQ_MAKE(sBuf, sSeq, sRange.length); + GSEQ_MAKE(oBuf, oSeq, oRange.length); + + GSEQ_SGETR(sBuf, sRange); + GSEQ_OGETR(oBuf, oRange); + + result = GSeq_compare(&sSeq, &oSeq); + + if (result != NSOrderedSame) + { + if (mask & NSCaseInsensitiveSearch) + { + GSeq_lowercase(&oSeq); + GSeq_lowercase(&sSeq); + result = GSeq_compare(&sSeq, &oSeq); + if (result != NSOrderedSame) + { + return result; + } + } + else + { + return result; + } + } + + sCount += sRange.length; + oCount += oRange.length; + } + } + if (oCount < oLength) + return NSOrderedAscending; + return NSOrderedSame; + } +} +#undef GSEQ_STRCOMP +#endif + +/* + * If a string search function is required, implement it. + */ +#ifdef GSEQ_STRRANGE +static inline NSRange +GSEQ_STRRANGE(NSString *ss, NSString *os, unsigned mask, NSRange aRange) +{ + GSEQ_ST s = (GSEQ_ST)ss; + GSEQ_OT o = (GSEQ_OT)os; + unsigned myLength; + unsigned myIndex; + unsigned myEndIndex; + unsigned strLength; +#if GSEQ_S == GSEQ_NS + unichar (*scImp)(NSString*, SEL, unsigned); + void (*sgImp)(NSString*, SEL, unichar*, NSRange); +#endif +#if GSEQ_O == GSEQ_NS + unichar (*ocImp)(NSString*, SEL, unsigned); + void (*ogImp)(NSString*, SEL, unichar*, NSRange); +#endif +#if GSEQ_S == GSEQ_NS || GSEQ_S == GSEQ_US + NSRange (*srImp)(NSString*, SEL, unsigned); +#endif +#if GSEQ_O == GSEQ_NS || GSEQ_O == GSEQ_US + NSRange (*orImp)(NSString*, SEL, unsigned); +#endif + + /* Check that the search range is reasonable */ + myLength = GSEQ_SLEN; + if (aRange.location > myLength) + [NSException raise: NSRangeException format: @"Invalid location."]; + if (aRange.length > (myLength - aRange.location)) + [NSException raise: NSRangeException format: @"Invalid location+length."]; + + + /* Ensure the string can be found */ + strLength = GSEQ_OLEN; + if (strLength > aRange.length || strLength == 0) + return (NSRange){0, 0}; + + /* + * Cache method implementations for getting characters and ranges + */ +#if GSEQ_S == GSEQ_NS + scImp = (unichar (*)())[(id)s methodForSelector: caiSel]; + sgImp = (void (*)())[(id)s methodForSelector: gcrSel]; +#endif +#if GSEQ_O == GSEQ_NS + ocImp = (unichar (*)())[(id)o methodForSelector: caiSel]; + ogImp = (void (*)())[(id)o methodForSelector: gcrSel]; +#endif +#if GSEQ_S == GSEQ_NS || GSEQ_S == GSEQ_US + srImp = (NSRange (*)())[(id)s methodForSelector: ranSel]; +#endif +#if GSEQ_O == GSEQ_NS || GSEQ_O == GSEQ_US + orImp = (NSRange (*)())[(id)o methodForSelector: ranSel]; +#endif + + switch (mask) + { + case FCLS : + case FCLAS : + { + unichar strFirstCharacter = GSEQ_OGETC(0); + + myIndex = aRange.location; + myEndIndex = aRange.location + aRange.length - strLength; + + if (mask & NSAnchoredSearch) + myEndIndex = myIndex; + + for (;;) + { + unsigned i = 1; + unichar myCharacter = GSEQ_SGETC(myIndex); + unichar strCharacter = strFirstCharacter; + + for (;;) + { + if ((myCharacter != strCharacter) && + ((uni_tolower(myCharacter) != uni_tolower(strCharacter)))) + break; + if (i == strLength) + return (NSRange){myIndex, strLength}; + myCharacter = GSEQ_SGETC(myIndex + i); + strCharacter = GSEQ_OGETC(i); + i++; + } + if (myIndex == myEndIndex) + break; + myIndex++; + } + return (NSRange){0, 0}; + } + + case BCLS : + case BCLAS : + { + unichar strFirstCharacter = GSEQ_OGETC(0); + + myIndex = aRange.location + aRange.length - strLength; + myEndIndex = aRange.location; + + if (mask & NSAnchoredSearch) + myEndIndex = myIndex; + + for (;;) + { + unsigned i = 1; + unichar myCharacter = GSEQ_SGETC(myIndex); + unichar strCharacter = strFirstCharacter; + + for (;;) + { + if ((myCharacter != strCharacter) && + ((uni_tolower(myCharacter) != uni_tolower(strCharacter)))) + break; + if (i == strLength) + return (NSRange){myIndex, strLength}; + myCharacter = GSEQ_SGETC(myIndex + i); + strCharacter = GSEQ_OGETC(i); + i++; + } + if (myIndex == myEndIndex) + break; + myIndex--; + } + return (NSRange){0, 0}; + } + + case FLS : + case FLAS : + { + unichar strFirstCharacter = GSEQ_OGETC(0); + + myIndex = aRange.location; + myEndIndex = aRange.location + aRange.length - strLength; + + if (mask & NSAnchoredSearch) + myEndIndex = myIndex; + + for (;;) + { + unsigned i = 1; + unichar myCharacter = GSEQ_SGETC(myIndex); + unichar strCharacter = strFirstCharacter; + + for (;;) + { + if (myCharacter != strCharacter) + break; + if (i == strLength) + return (NSRange){myIndex, strLength}; + myCharacter = GSEQ_SGETC(myIndex + i); + strCharacter = GSEQ_OGETC(i); + i++; + } + if (myIndex == myEndIndex) + break; + myIndex++; + } + return (NSRange){0, 0}; + } + + case BLS : + case BLAS : + { + unichar strFirstCharacter = GSEQ_OGETC(0); + + myIndex = aRange.location + aRange.length - strLength; + myEndIndex = aRange.location; + + if (mask & NSAnchoredSearch) + myEndIndex = myIndex; + + for (;;) + { + unsigned i = 1; + unichar myCharacter = GSEQ_SGETC(myIndex); + unichar strCharacter = strFirstCharacter; + + for (;;) + { + if (myCharacter != strCharacter) + break; + if (i == strLength) + return (NSRange){myIndex, strLength}; + myCharacter = GSEQ_SGETC(myIndex + i); + strCharacter = GSEQ_OGETC(i); + i++; + } + if (myIndex == myEndIndex) + break; + myIndex--; + } + return (NSRange){0, 0}; + } + + case FCS : + case FCAS : + { + unsigned strBaseLength; + NSRange iRange; + + strBaseLength = [(NSString*)o _baseLength]; + + myIndex = aRange.location; + myEndIndex = aRange.location + aRange.length - strBaseLength; + + if (mask & NSAnchoredSearch) + myEndIndex = myIndex; + + iRange = GSEQ_ORANGE(0); + if (iRange.length) + { + GSEQ_MAKE(iBuf, iSeq, iRange.length); + + GSEQ_OGETR(iBuf, iRange); + GSeq_lowercase(&iSeq); + + for (;;) + { + NSRange sRange = GSEQ_SRANGE(myIndex); + GSEQ_MAKE(sBuf, sSeq, sRange.length); + + GSEQ_SGETR(sBuf, sRange); + GSeq_lowercase(&sSeq); + + if (GSeq_compare(&iSeq, &sSeq) == NSOrderedSame) + { + unsigned myCount = sRange.length; + unsigned strCount = iRange.length; + + if (strCount >= strLength) + { + return (NSRange){myIndex, myCount}; + } + for (;;) + { + NSRange r0 = GSEQ_SRANGE(myIndex + myCount); + GSEQ_MAKE(b0, s0, r0.length); + NSRange r1 = GSEQ_ORANGE(strCount); + GSEQ_MAKE(b1, s1, r1.length); + + GSEQ_SGETR(b0, r0); + GSEQ_OGETR(b1, r1); + + if (GSeq_compare(&s0, &s1) != NSOrderedSame) + { + GSeq_lowercase(&s0); + GSeq_lowercase(&s1); + if (GSeq_compare(&s0, &s1) != NSOrderedSame) + { + break; + } + } + myCount += r0.length; + strCount += r1.length; + if (strCount >= strLength) + { + return (NSRange){myIndex, myCount}; + } + } + } + myIndex += sRange.length; + if (myIndex >= myEndIndex) + break; + } + } + return (NSRange){0, 0}; + } + + case BCS : + case BCAS : + { + unsigned strBaseLength; + NSRange iRange; + + strBaseLength = [(NSString*)o _baseLength]; + + myIndex = aRange.location + aRange.length - strBaseLength; + myEndIndex = aRange.location; + + if (mask & NSAnchoredSearch) + myEndIndex = myIndex; + + iRange = GSEQ_ORANGE(0); + if (iRange.length) + { + GSEQ_MAKE(iBuf, iSeq, iRange.length); + + GSEQ_OGETR(iBuf, iRange); + GSeq_lowercase(&iSeq); + + for (;;) + { + NSRange sRange = GSEQ_SRANGE(myIndex); + GSEQ_MAKE(sBuf, sSeq, sRange.length); + + GSEQ_SGETR(sBuf, sRange); + GSeq_lowercase(&sSeq); + + if (GSeq_compare(&iSeq, &sSeq) == NSOrderedSame) + { + unsigned myCount = sRange.length; + unsigned strCount = iRange.length; + + if (strCount >= strLength) + { + return (NSRange){myIndex, myCount}; + } + for (;;) + { + NSRange r0 = GSEQ_SRANGE(myIndex + myCount); + GSEQ_MAKE(b0, s0, r0.length); + NSRange r1 = GSEQ_ORANGE(strCount); + GSEQ_MAKE(b1, s1, r1.length); + + GSEQ_SGETR(b0, r0); + GSEQ_OGETR(b1, r1); + + if (GSeq_compare(&s0, &s1) != NSOrderedSame) + { + GSeq_lowercase(&s0); + GSeq_lowercase(&s1); + if (GSeq_compare(&s0, &s1) != NSOrderedSame) + { + break; + } + } + myCount += r0.length; + strCount += r1.length; + if (strCount >= strLength) + { + return (NSRange){myIndex, myCount}; + } + } + } + if (myIndex <= myEndIndex) + break; + myIndex--; + while (uni_isnonsp(GSEQ_SGETC(myIndex)) + && (myIndex > 0)) + myIndex--; + } + } + return (NSRange){0, 0}; + } + + case BS : + case BAS : + { + unsigned strBaseLength; + NSRange iRange; + + strBaseLength = [(NSString*)o _baseLength]; + + myIndex = aRange.location + aRange.length - strBaseLength; + myEndIndex = aRange.location; + + if (mask & NSAnchoredSearch) + myEndIndex = myIndex; + + iRange = GSEQ_ORANGE(0); + if (iRange.length) + { + GSEQ_MAKE(iBuf, iSeq, iRange.length); + + GSEQ_OGETR(iBuf, iRange); + + for (;;) + { + NSRange sRange = GSEQ_SRANGE(myIndex); + GSEQ_MAKE(sBuf, sSeq, sRange.length); + + GSEQ_SGETR(sBuf, sRange); + + if (GSeq_compare(&iSeq, &sSeq) == NSOrderedSame) + { + unsigned myCount = sRange.length; + unsigned strCount = iRange.length; + + if (strCount >= strLength) + { + return (NSRange){myIndex, myCount}; + } + for (;;) + { + NSRange r0 = GSEQ_SRANGE(myIndex + myCount); + GSEQ_MAKE(b0, s0, r0.length); + NSRange r1 = GSEQ_ORANGE(strCount); + GSEQ_MAKE(b1, s1, r1.length); + + GSEQ_SGETR(b0, r0); + GSEQ_OGETR(b1, r1); + + if (GSeq_compare(&s0, &s1) != NSOrderedSame) + { + break; + } + myCount += r0.length; + strCount += r1.length; + if (strCount >= strLength) + { + return (NSRange){myIndex, myCount}; + } + } + } + if (myIndex <= myEndIndex) + break; + myIndex--; + while (uni_isnonsp(GSEQ_SGETC(myIndex)) + && (myIndex > 0)) + myIndex--; + } + } + return (NSRange){0, 0}; + } + + case FS : + case FAS : + default : + { + unsigned strBaseLength; + NSRange iRange; + + strBaseLength = [(NSString*)o _baseLength]; + + myIndex = aRange.location; + myEndIndex = aRange.location + aRange.length - strBaseLength; + + if (mask & NSAnchoredSearch) + myEndIndex = myIndex; + + iRange = GSEQ_ORANGE(0); + if (iRange.length) + { + GSEQ_MAKE(iBuf, iSeq, iRange.length); + + GSEQ_OGETR(iBuf, iRange); + + for (;;) + { + NSRange sRange = GSEQ_SRANGE(myIndex); + GSEQ_MAKE(sBuf, sSeq, sRange.length); + + GSEQ_SGETR(sBuf, sRange); + + if (GSeq_compare(&iSeq, &sSeq) == NSOrderedSame) + { + unsigned myCount = sRange.length; + unsigned strCount = iRange.length; + + if (strCount >= strLength) + { + return (NSRange){myIndex, myCount}; + } + for (;;) + { + NSRange r0 = GSEQ_SRANGE(myIndex + myCount); + GSEQ_MAKE(b0, s0, r0.length); + NSRange r1 = GSEQ_ORANGE(strCount); + GSEQ_MAKE(b1, s1, r1.length); + + GSEQ_SGETR(b0, r0); + GSEQ_OGETR(b1, r1); + + if (GSeq_compare(&s0, &s1) != NSOrderedSame) + { + break; + } + myCount += r0.length; + strCount += r1.length; + if (strCount >= strLength) + { + return (NSRange){myIndex, myCount}; + } + } + } + myIndex += sRange.length; + if (myIndex >= myEndIndex) + break; + } + } + return (NSRange){0, 0}; + } + } + return (NSRange){0, 0}; +} +#undef GSEQ_STRRANGE +#endif + +/* + * Clean up macro namespace + */ +#ifdef GSEQ_S +#undef GSEQ_SLEN +#undef GSEQ_SGETC +#undef GSEQ_SGETR +#undef GSEQ_SRANGE +#undef GSEQ_ST +#undef GSEQ_S +#endif + +#ifdef GSEQ_O +#undef GSEQ_OLEN +#undef GSEQ_OGETC +#undef GSEQ_OGETR +#undef GSEQ_ORANGE +#undef GSEQ_OT +#undef GSEQ_O +#endif + diff --git a/Source/Makefile.postamble b/Source/Makefile.postamble index dde5cfe89..faf4f5aab 100644 --- a/Source/Makefile.postamble +++ b/Source/Makefile.postamble @@ -258,6 +258,8 @@ $(GNUSTEP_OBJ_DIR)/NSGCString.o \ # Files that include GSeq.h will need a rebuild if it is changed. # $(GNUSTEP_OBJ_DIR)/NSString.o \ +$(GNUSTEP_OBJ_DIR)/NSGString.o \ +$(GNUSTEP_OBJ_DIR)/NSGCString.o \ : GSeq.h # diff --git a/Source/NSGCString.m b/Source/NSGCString.m index 7f0fe704a..7f746ad08 100644 --- a/Source/NSGCString.m +++ b/Source/NSGCString.m @@ -41,6 +41,28 @@ #include #include +/* + * Include sequence handling code with instructions to generate search + * and compare functions for NSString objects. + */ +#define GSEQ_STRCOMP strCompCsNs +#define GSEQ_STRRANGE strRangeCsNs +#define GSEQ_O GSEQ_NS +#define GSEQ_S GSEQ_CS +#include + +#define GSEQ_STRCOMP strCompCsUs +#define GSEQ_STRRANGE strRangeCsUs +#define GSEQ_O GSEQ_US +#define GSEQ_S GSEQ_CS +#include + +#define GSEQ_STRCOMP strCompCsCs +#define GSEQ_STRRANGE strRangeCsCs +#define GSEQ_O GSEQ_CS +#define GSEQ_S GSEQ_CS +#include + /* * Include property-list parsing code configured for ascii characters. */ @@ -418,7 +440,8 @@ static IMP msInitImp; /* designated initialiser for mutable */ return NO; c = fastClassOfInstance(anObject); - if (c == _fastCls._NSGCString || c == _fastCls._NSGMutableCString || c == _fastCls._NXConstantString) + if (c == _fastCls._NSGCString || c == _fastCls._NSGMutableCString + || c == _fastCls._NXConstantString) { NSGCString *other = (NSGCString*)anObject; @@ -434,6 +457,12 @@ static IMP msInitImp; /* designated initialiser for mutable */ return NO; return YES; } + else if (c == _fastCls._NSGString || c == _fastCls._NSGMutableString) + { + if (strCompCsUs(self, anObject, 0, (NSRange){0,_count}) == NSOrderedSame) + return YES; + return NO; + } else if (c == nil) return NO; else if (fastClassIsKindOfClass(c, _fastCls._NSString)) @@ -452,7 +481,8 @@ static IMP msInitImp; /* designated initialiser for mutable */ if (aString == nil) return NO; c = fastClassOfInstance(aString); - if (c == _fastCls._NSGCString || c == _fastCls._NSGMutableCString || c == _fastCls._NXConstantString) + if (c == _fastCls._NSGCString || c == _fastCls._NSGMutableCString + || c == _fastCls._NXConstantString) { NSGCString *other = (NSGCString*)aString; @@ -468,6 +498,12 @@ static IMP msInitImp; /* designated initialiser for mutable */ return NO; return YES; } + else if (c == _fastCls._NSGString || c == _fastCls._NSGMutableString) + { + if (strCompCsUs(self, aString, 0, (NSRange){0,_count}) == NSOrderedSame) + return YES; + return NO; + } else if (c == nil) return NO; else if (fastClassIsKindOfClass(c, _fastCls._NSString)) @@ -656,6 +692,35 @@ static IMP msInitImp; /* designated initialiser for mutable */ return NSMakeRange(anIndex, 1); } +- (NSComparisonResult) compare: (NSString*)aString + options: (unsigned int)mask + range: (NSRange)aRange +{ + Class c = fastClass(aString); + + if (c == _fastCls._NSGString || c == _fastCls._NSGMutableString) + return strCompCsUs(self, aString, mask, aRange); + else if (c == _fastCls._NSGCString || c == _fastCls._NSGMutableCString + || c == _fastCls._NXConstantString) + return strCompCsCs(self, aString, mask, aRange); + else + return strCompCsNs(self, aString, mask, aRange); +} + +- (NSRange) rangeOfString: (NSString *) aString + options: (unsigned int) mask + range: (NSRange) aRange +{ + Class c = fastClass(aString); + + if (c == _fastCls._NSGString || c == _fastCls._NSGMutableString) + return strRangeCsUs(self, aString, mask, aRange); + else if (c == _fastCls._NSGCString || c == _fastCls._NSGMutableCString + || c == _fastCls._NXConstantString) + return strRangeCsCs(self, aString, mask, aRange); + else + return strRangeCsNs(self, aString, mask, aRange); +} @end diff --git a/Source/NSGString.m b/Source/NSGString.m index 62b8c6157..f61486510 100644 --- a/Source/NSGString.m +++ b/Source/NSGString.m @@ -47,6 +47,28 @@ #include #include +/* + * Include sequence handling code with instructions to generate search + * and compare functions for NSString objects. + */ +#define GSEQ_STRCOMP strCompUsNs +#define GSEQ_STRRANGE strRangeUsNs +#define GSEQ_O GSEQ_NS +#define GSEQ_S GSEQ_US +#include + +#define GSEQ_STRCOMP strCompUsUs +#define GSEQ_STRRANGE strRangeUsUs +#define GSEQ_O GSEQ_US +#define GSEQ_S GSEQ_US +#include + +#define GSEQ_STRCOMP strCompUsCs +#define GSEQ_STRRANGE strRangeUsCs +#define GSEQ_O GSEQ_CS +#define GSEQ_S GSEQ_US +#include + /* * Include property-list parsing code configured for unicode characters. */ @@ -91,20 +113,37 @@ if (anObject == nil) return NO; c = fastClassOfInstance(anObject); - if (c == _fastCls._NSGString || c == _fastCls._NSGMutableString || - c == _fastCls._NSGCString || c == _fastCls._NSGMutableCString || - c == _fastCls._NXConstantString) + if (c == _fastCls._NSGString || c == _fastCls._NSGMutableString + || c == _fastCls._NSGCString || c == _fastCls._NSGMutableCString + || c == _fastCls._NXConstantString) { NSGString *other = (NSGString*)anObject; + NSRange r = {0, _count}; + /* + * First see if the has is the same - if not, we can't be equal. + */ if (_hash == 0) _hash = _fastImp._NSString_hash(self, @selector(hash)); if (other->_hash == 0) other->_hash = _fastImp._NSString_hash(other, @selector(hash)); if (_hash != other->_hash) return NO; - return _fastImp._NSString_isEqualToString_(self, - @selector(isEqualToString:), other); + + /* + * Do a compare depending on the type of the other string. + */ + if (c == _fastCls._NSGString || c == _fastCls._NSGMutableString) + { + if (strCompUsUs(self, other, 0, r) == NSOrderedSame) + return YES; + } + else + { + if (strCompUsCs(self, other, 0, r) == NSOrderedSame) + return YES; + } + return NO; } else if (c == nil) return NO; @@ -387,6 +426,36 @@ return NSMakeRange(start, end-start); } +- (NSComparisonResult) compare: (NSString*)aString + options: (unsigned int)mask + range: (NSRange)aRange +{ + Class c = fastClass(aString); + + if (c == _fastCls._NSGString || c == _fastCls._NSGMutableString) + return strCompUsUs(self, aString, mask, aRange); + else if (c == _fastCls._NSGCString || c == _fastCls._NSGMutableCString + || c == _fastCls._NXConstantString) + return strCompUsCs(self, aString, mask, aRange); + else + return strCompUsNs(self, aString, mask, aRange); +} + +- (NSRange) rangeOfString: (NSString *) aString + options: (unsigned int) mask + range: (NSRange) aRange +{ + Class c = fastClass(aString); + + if (c == _fastCls._NSGString || c == _fastCls._NSGMutableString) + return strRangeUsUs(self, aString, mask, aRange); + else if (c == _fastCls._NSGCString || c == _fastCls._NSGMutableCString + || c == _fastCls._NXConstantString) + return strRangeUsCs(self, aString, mask, aRange); + else + return strRangeUsNs(self, aString, mask, aRange); +} + @end diff --git a/Source/NSString.m b/Source/NSString.m index 72417f121..e09fd81a0 100644 --- a/Source/NSString.m +++ b/Source/NSString.m @@ -71,7 +71,6 @@ #include #include #include -#include #include @@ -101,9 +100,15 @@ static Class NSString_class; /* For speed */ -static SEL caiSel = @selector(characterAtIndex:); -static SEL gcrSel = @selector(getCharacters:range:); -static SEL ranSel = @selector(rangeOfComposedCharacterSequenceAtIndex:); +/* + * Include sequence handling code with instructions to generate search + * and compare functions for NSString objects. + */ +#define GSEQ_STRCOMP strCompNsNs +#define GSEQ_STRRANGE strRangeNsNs +#define GSEQ_O GSEQ_NS +#define GSEQ_S GSEQ_NS +#include /* * Include property-list parsing code configured for unicode characters. @@ -649,7 +654,7 @@ handle_printf_atsign (FILE *stream, /* Inefficient. Should be overridden */ - (void) getCharacters: (unichar*)buffer - range: (NSRange)aRange + range: (NSRange)aRange { int i; for (i = 0; i < aRange.length; i++) @@ -764,7 +769,7 @@ handle_printf_atsign (FILE *stream, } - (NSRange) rangeOfCharacterFromSet: (NSCharacterSet*)aSet - options: (unsigned int)mask + options: (unsigned int)mask { NSRange all = NSMakeRange(0, [self length]); return [self rangeOfCharacterFromSet: aSet @@ -834,514 +839,10 @@ handle_printf_atsign (FILE *stream, } - (NSRange) rangeOfString: (NSString *) aString - options: (unsigned int) mask - range: (NSRange) aRange + options: (unsigned int) mask + range: (NSRange) aRange { -#define FCLS 3 -#define BCLS 7 -#define FLS 2 -#define BLS 6 -#define FCS 1 -#define BCS 5 -#define FS 0 -#define BS 4 -#define FCLAS 11 -#define BCLAS 15 -#define FLAS 10 -#define BLAS 14 -#define FCAS 9 -#define BCAS 13 -#define FAS 8 -#define BAS 12 - - unsigned myLength; - unsigned myIndex; - unsigned myEndIndex; - unsigned strLength; - unichar (*scImp)(NSString*, SEL, unsigned); - unichar (*ocImp)(NSString*, SEL, unsigned); - void (*sgImp)(NSString*, SEL, unichar*, NSRange); - void (*ogImp)(NSString*, SEL, unichar*, NSRange); - NSRange (*srImp)(NSString*, SEL, unsigned); - NSRange (*orImp)(NSString*, SEL, unsigned); - - /* Check that the search range is reasonable */ - myLength = [self length]; - if (aRange.location > myLength) - [NSException raise: NSRangeException format: @"Invalid location."]; - if (aRange.length > (myLength - aRange.location)) - [NSException raise: NSRangeException format: @"Invalid location+length."]; - - - /* Ensure the string can be found */ - strLength = [aString length]; - if (strLength > aRange.length || strLength == 0) - return (NSRange){0, 0}; - - /* - * Cache method implementations fo getting characters and ranges - */ - scImp = (unichar (*)())[self methodForSelector: caiSel]; - ocImp = (unichar (*)())[aString methodForSelector: caiSel]; - sgImp = (void (*)())[self methodForSelector: gcrSel]; - ogImp = (void (*)())[aString methodForSelector: gcrSel]; - srImp = (NSRange (*)())[self methodForSelector: ranSel]; - orImp = (NSRange (*)())[aString methodForSelector: ranSel]; - - switch (mask) - { - case FCLS : - case FCLAS : - { - unichar strFirstCharacter = (*ocImp)(aString, caiSel, 0); - - myIndex = aRange.location; - myEndIndex = aRange.location + aRange.length - strLength; - - if (mask & NSAnchoredSearch) - myEndIndex = myIndex; - - for (;;) - { - unsigned i = 1; - unichar myCharacter = (*scImp)(self, caiSel, myIndex); - unichar strCharacter = strFirstCharacter; - - for (;;) - { - if ((myCharacter != strCharacter) && - ((uni_tolower(myCharacter) != uni_tolower(strCharacter)))) - break; - if (i == strLength) - return (NSRange){myIndex, strLength}; - myCharacter = (*scImp)(self, caiSel, myIndex + i); - strCharacter = (*ocImp)(aString, caiSel, i); - i++; - } - if (myIndex == myEndIndex) - break; - myIndex++; - } - return (NSRange){0, 0}; - } - - case BCLS : - case BCLAS : - { - unichar strFirstCharacter = (*ocImp)(aString, caiSel, 0); - - myIndex = aRange.location + aRange.length - strLength; - myEndIndex = aRange.location; - - if (mask & NSAnchoredSearch) - myEndIndex = myIndex; - - for (;;) - { - unsigned i = 1; - unichar myCharacter = (*scImp)(self, caiSel, myIndex); - unichar strCharacter = strFirstCharacter; - - for (;;) - { - if ((myCharacter != strCharacter) && - ((uni_tolower(myCharacter) != uni_tolower(strCharacter)))) - break; - if (i == strLength) - return (NSRange){myIndex, strLength}; - myCharacter = (*scImp)(self, caiSel, myIndex + i); - strCharacter = (*ocImp)(aString, caiSel, i); - i++; - } - if (myIndex == myEndIndex) - break; - myIndex--; - } - return (NSRange){0, 0}; - } - - case FLS : - case FLAS : - { - unichar strFirstCharacter = (*ocImp)(aString, caiSel, 0); - - myIndex = aRange.location; - myEndIndex = aRange.location + aRange.length - strLength; - - if (mask & NSAnchoredSearch) - myEndIndex = myIndex; - - for (;;) - { - unsigned i = 1; - unichar myCharacter = (*scImp)(self, caiSel, myIndex); - unichar strCharacter = strFirstCharacter; - - for (;;) - { - if (myCharacter != strCharacter) - break; - if (i == strLength) - return (NSRange){myIndex, strLength}; - myCharacter = (*scImp)(self, caiSel, myIndex + i); - strCharacter = (*ocImp)(aString, caiSel, i); - i++; - } - if (myIndex == myEndIndex) - break; - myIndex++; - } - return (NSRange){0, 0}; - } - - case BLS : - case BLAS : - { - unichar strFirstCharacter = (*ocImp)(aString, caiSel, 0); - - myIndex = aRange.location + aRange.length - strLength; - myEndIndex = aRange.location; - - if (mask & NSAnchoredSearch) - myEndIndex = myIndex; - - for (;;) - { - unsigned i = 1; - unichar myCharacter = (*scImp)(self, caiSel, myIndex); - unichar strCharacter = strFirstCharacter; - - for (;;) - { - if (myCharacter != strCharacter) - break; - if (i == strLength) - return (NSRange){myIndex, strLength}; - myCharacter = (*scImp)(self, caiSel, myIndex + i); - strCharacter = (*ocImp)(aString, caiSel, i); - i++; - } - if (myIndex == myEndIndex) - break; - myIndex--; - } - return (NSRange){0, 0}; - } - - case FCS : - case FCAS : - { - unsigned strBaseLength; - NSRange iRange; - - strBaseLength = [aString _baseLength]; - - myIndex = aRange.location; - myEndIndex = aRange.location + aRange.length - strBaseLength; - - if (mask & NSAnchoredSearch) - myEndIndex = myIndex; - - iRange = (*orImp)(aString, ranSel, 0); - if (iRange.length) - { - GSEQ_MAKE(iBuf, iSeq, iRange.length); - - (*ogImp)(aString, gcrSel, iBuf, iRange); - GSeq_normalize(&iSeq); - GSeq_lowercase(&iSeq); - - for (;;) - { - NSRange sRange = (*srImp)(self, ranSel, myIndex); - GSEQ_MAKE(sBuf, sSeq, sRange.length); - - (*sgImp)(self, gcrSel, sBuf, sRange); - GSeq_normalize(&sSeq); - GSeq_lowercase(&sSeq); - - if (GSeq_compare(&iSeq, &sSeq) == NSOrderedSame) - { - unsigned myCount = sRange.length; - unsigned strCount = iRange.length; - - if (strCount >= strLength) - { - return (NSRange){myIndex, myCount}; - } - for (;;) - { - NSRange r0 = - (*srImp)(self, ranSel, myIndex + myCount); - GSEQ_MAKE(b0, s0, r0.length); - NSRange r1 = - (*orImp)(aString, ranSel, strCount); - GSEQ_MAKE(b1, s1, r1.length); - - (*sgImp)(self, gcrSel, b0, r0); - (*ogImp)(aString, gcrSel, b1, r1); - - GSeq_normalize(&s0); - GSeq_normalize(&s1); - if (GSeq_compare(&s0, &s1) != NSOrderedSame) - { - GSeq_lowercase(&s0); - GSeq_lowercase(&s1); - if (GSeq_compare(&s0, &s1) != NSOrderedSame) - { - break; - } - } - myCount += r0.length; - strCount += r1.length; - if (strCount >= strLength) - { - return (NSRange){myIndex, myCount}; - } - } - } - myIndex += sRange.length; - if (myIndex >= myEndIndex) - break; - } - } - return (NSRange){0, 0}; - } - - case BCS : - case BCAS : - { - unsigned strBaseLength; - NSRange iRange; - - strBaseLength = [aString _baseLength]; - - myIndex = aRange.location + aRange.length - strBaseLength; - myEndIndex = aRange.location; - - if (mask & NSAnchoredSearch) - myEndIndex = myIndex; - - iRange = (*orImp)(aString, ranSel, 0); - if (iRange.length) - { - GSEQ_MAKE(iBuf, iSeq, iRange.length); - - (*ogImp)(aString, gcrSel, iBuf, iRange); - GSeq_normalize(&iSeq); - GSeq_lowercase(&iSeq); - - for (;;) - { - NSRange sRange = (*srImp)(self, ranSel, myIndex); - GSEQ_MAKE(sBuf, sSeq, sRange.length); - - (*sgImp)(self, gcrSel, sBuf, sRange); - GSeq_normalize(&sSeq); - GSeq_lowercase(&sSeq); - - if (GSeq_compare(&iSeq, &sSeq) == NSOrderedSame) - { - unsigned myCount = sRange.length; - unsigned strCount = iRange.length; - - if (strCount >= strLength) - { - return (NSRange){myIndex, myCount}; - } - for (;;) - { - NSRange r0 = - (*srImp)(self, ranSel, myIndex + myCount); - GSEQ_MAKE(b0, s0, r0.length); - NSRange r1 = - (*orImp)(aString, ranSel, strCount); - GSEQ_MAKE(b1, s1, r1.length); - - (*sgImp)(self, gcrSel, b0, r0); - (*ogImp)(aString, gcrSel, b1, r1); - - GSeq_normalize(&s0); - GSeq_normalize(&s1); - if (GSeq_compare(&s0, &s1) != NSOrderedSame) - { - GSeq_lowercase(&s0); - GSeq_lowercase(&s1); - if (GSeq_compare(&s0, &s1) != NSOrderedSame) - { - break; - } - } - myCount += r0.length; - strCount += r1.length; - if (strCount >= strLength) - { - return (NSRange){myIndex, myCount}; - } - } - } - if (myIndex <= myEndIndex) - break; - myIndex--; - while (uni_isnonsp((*scImp)(self, caiSel, myIndex)) - && (myIndex > 0)) - myIndex--; - } - } - return (NSRange){0, 0}; - } - - case BS : - case BAS : - { - unsigned strBaseLength; - NSRange iRange; - - strBaseLength = [aString _baseLength]; - - myIndex = aRange.location + aRange.length - strBaseLength; - myEndIndex = aRange.location; - - if (mask & NSAnchoredSearch) - myEndIndex = myIndex; - - iRange = (*orImp)(aString, ranSel, 0); - if (iRange.length) - { - GSEQ_MAKE(iBuf, iSeq, iRange.length); - - (*ogImp)(aString, gcrSel, iBuf, iRange); - GSeq_normalize(&iSeq); - - for (;;) - { - NSRange sRange = (*srImp)(self, ranSel, myIndex); - GSEQ_MAKE(sBuf, sSeq, sRange.length); - - (*sgImp)(self, gcrSel, sBuf, sRange); - GSeq_normalize(&sSeq); - - if (GSeq_compare(&iSeq, &sSeq) == NSOrderedSame) - { - unsigned myCount = sRange.length; - unsigned strCount = iRange.length; - - if (strCount >= strLength) - { - return (NSRange){myIndex, myCount}; - } - for (;;) - { - NSRange r0 = - (*srImp)(self, ranSel, myIndex + myCount); - GSEQ_MAKE(b0, s0, r0.length); - NSRange r1 = - (*orImp)(aString, ranSel, strCount); - GSEQ_MAKE(b1, s1, r1.length); - - (*sgImp)(self, gcrSel, b0, r0); - (*ogImp)(aString, gcrSel, b1, r1); - - GSeq_normalize(&s0); - GSeq_normalize(&s1); - if (GSeq_compare(&s0, &s1) != NSOrderedSame) - { - break; - } - myCount += r0.length; - strCount += r1.length; - if (strCount >= strLength) - { - return (NSRange){myIndex, myCount}; - } - } - } - if (myIndex <= myEndIndex) - break; - myIndex--; - while (uni_isnonsp((*scImp)(self, caiSel, myIndex)) - && (myIndex > 0)) - myIndex--; - } - } - return (NSRange){0, 0}; - } - - case FS : - case FAS : - default : - { - unsigned strBaseLength; - NSRange iRange; - - strBaseLength = [aString _baseLength]; - - myIndex = aRange.location; - myEndIndex = aRange.location + aRange.length - strBaseLength; - - if (mask & NSAnchoredSearch) - myEndIndex = myIndex; - - iRange = (*orImp)(aString, ranSel, 0); - if (iRange.length) - { - GSEQ_MAKE(iBuf, iSeq, iRange.length); - - (*ogImp)(aString, gcrSel, iBuf, iRange); - GSeq_normalize(&iSeq); - - for (;;) - { - NSRange sRange = (*srImp)(self, ranSel, myIndex); - GSEQ_MAKE(sBuf, sSeq, sRange.length); - - (*sgImp)(self, gcrSel, sBuf, sRange); - GSeq_normalize(&sSeq); - - if (GSeq_compare(&iSeq, &sSeq) == NSOrderedSame) - { - unsigned myCount = sRange.length; - unsigned strCount = iRange.length; - - if (strCount >= strLength) - { - return (NSRange){myIndex, myCount}; - } - for (;;) - { - NSRange r0 = - (*srImp)(self, ranSel, myIndex + myCount); - GSEQ_MAKE(b0, s0, r0.length); - NSRange r1 = - (*orImp)(aString, ranSel, strCount); - GSEQ_MAKE(b1, s1, r1.length); - - (*sgImp)(self, gcrSel, b0, r0); - (*ogImp)(aString, gcrSel, b1, r1); - - GSeq_normalize(&s0); - GSeq_normalize(&s1); - if (GSeq_compare(&s0, &s1) != NSOrderedSame) - { - break; - } - myCount += r0.length; - strCount += r1.length; - if (strCount >= strLength) - { - return (NSRange){myIndex, myCount}; - } - } - } - myIndex += sRange.length; - if (myIndex >= myEndIndex) - break; - } - } - return (NSRange){0, 0}; - } - } - return (NSRange){0, 0}; + return strRangeNsNs(self, aString, mask, aRange); } // Determining Composed Character Sequences @@ -1383,144 +884,7 @@ handle_printf_atsign (FILE *stream, options: (unsigned int)mask range: (NSRange)aRange { - unsigned oLength; /* Length of other. */ - unsigned sLength = [self length]; - - if (aRange.location > sLength) - [NSException raise: NSRangeException format: @"Invalid location."]; - if (aRange.length > (sLength - aRange.location)) - [NSException raise: NSRangeException format: @"Invalid location+length."]; - - oLength = [aString length]; - if (sLength - aRange.location == 0) - { - if (oLength == 0) - { - return NSOrderedSame; - } - return NSOrderedAscending; - } - else if (oLength == 0) - { - return NSOrderedDescending; - } - - if (mask & NSLiteralSearch) - { - unsigned i; - unsigned sLen = aRange.length; - unsigned oLen = oLength; - unsigned end; - unichar s[sLen+1]; - unichar o[oLen+1]; - - [self getCharacters: s range: aRange]; - s[sLen] = (unichar)0; - [aString getCharacters: o]; - o[oLen] = (unichar)0; - if (oLen < sLen) - end = oLen + 1; - else - end = sLen + 1; - - if (mask & NSCaseInsensitiveSearch) - { - for (i = 0; i < end; i++) - { - unichar c1 = uni_tolower(s[i]); - unichar c2 = uni_tolower(o[i]); - - if (c1 < c2) - return NSOrderedAscending; - if (c1 > c2) - return NSOrderedDescending; - } - } - else - { - for (i = 0; i < end; i++) - { - if (s[i] < o[i]) - return NSOrderedAscending; - if (s[i] > o[i]) - return NSOrderedDescending; - } - } - if (sLen > oLen) - return NSOrderedDescending; - else if (sLen < oLen) - return NSOrderedAscending; - else - return NSOrderedSame; - } - else - { - unsigned start = aRange.location; - unsigned end = start + aRange.length; - unsigned sCount = start; - unsigned oCount = 0; - void (*sgImp)(NSString*, SEL, unichar*, NSRange); - void (*ogImp)(NSString*, SEL, unichar*, NSRange); - NSRange (*srImp)(NSString*, SEL, unsigned); - NSRange (*orImp)(NSString*, SEL, unsigned); - NSComparisonResult result; - - sgImp = (void (*)())[self methodForSelector: gcrSel]; - ogImp = (void (*)())[aString methodForSelector: gcrSel]; - srImp = (NSRange (*)())[self methodForSelector: ranSel]; - orImp = (NSRange (*)())[aString methodForSelector: ranSel]; - - while (sCount < end) - { - if (oCount >= oLength) - { - return NSOrderedDescending; - } - else if (sCount >= sLength) - { - return NSOrderedAscending; - } - else - { - NSRange sRange = (*srImp)(self, ranSel, sCount); - NSRange oRange = (*orImp)(aString, ranSel, oCount); - GSEQ_MAKE(sBuf, sSeq, sRange.length); - GSEQ_MAKE(oBuf, oSeq, oRange.length); - - (*sgImp)(self, gcrSel, sBuf, sRange); - (*ogImp)(aString, gcrSel, oBuf, oRange); - - GSeq_normalize(&sSeq); - GSeq_normalize(&oSeq); - - result = GSeq_compare(&sSeq, &oSeq); - - if (result != NSOrderedSame) - { - if (mask & NSCaseInsensitiveSearch) - { - GSeq_lowercase(&oSeq); - GSeq_lowercase(&sSeq); - result = GSeq_compare(&sSeq, &oSeq); - if (result != NSOrderedSame) - { - return result; - } - } - else - { - return result; - } - } - - sCount += sRange.length; - oCount += oRange.length; - } - } - if (oCount < oLength) - return NSOrderedAscending; - return NSOrderedSame; - } + return strCompNsNs(self, aString, mask, aRange); } - (BOOL) hasPrefix: (NSString*)aString @@ -1556,82 +920,12 @@ handle_printf_atsign (FILE *stream, - (BOOL) isEqualToString: (NSString*)aString { - unsigned myLength; - unsigned strLength; - unsigned myIndex = 0; - unsigned strIndex = 0; - unichar (*scImp)(NSString*, SEL, unsigned); - unichar (*ocImp)(NSString*, SEL, unsigned); - void (*sgImp)(NSString*, SEL, unichar*, NSRange); - void (*ogImp)(NSString*, SEL, unichar*, NSRange); - NSRange (*srImp)(NSString*, SEL, unsigned); - NSRange (*orImp)(NSString*, SEL, unsigned); - BOOL gotRangeImps = NO; - BOOL gotFetchImps = NO; - if ([self hash] != [aString hash]) return NO; - myLength = [self length]; - strLength = [aString length]; - if ((!myLength) && (!strLength)) + if (strCompNsNs(self, aString, 0, (NSRange){0, [self length]}) + == NSOrderedSame) return YES; - if (!myLength) - return NO; - if (!strLength) - return NO; - - scImp = (unichar (*)())[self methodForSelector: caiSel]; - ocImp = (unichar (*)())[aString methodForSelector: caiSel]; - - while ((myIndex < myLength) && (strIndex < strLength)) - if ((*scImp)(self, caiSel, myIndex) == (*ocImp)(aString, caiSel, strIndex)) - { - myIndex++; - strIndex++; - } - else - { - NSRange r0; - NSRange r1; - - if (gotRangeImps == NO) - { - gotRangeImps = YES; - srImp = (NSRange (*)())[self methodForSelector: ranSel]; - orImp = (NSRange (*)())[aString methodForSelector: ranSel]; - } - r0 = (*srImp)(self, ranSel, myIndex); - r1 = (*orImp)(aString, ranSel, strIndex); - if ((r0.length < 2) || (r1.length < 2)) - return NO; - else - { - unichar buf0[r0.length * MAXDEC + 1]; - unichar buf1[r1.length * MAXDEC + 1]; - GSeqStruct s0 = { buf0, r0.length, r0.length * MAXDEC, 0 }; - GSeqStruct s1 = { buf1, r1.length, r1.length * MAXDEC, 0 }; - - if (gotFetchImps == NO) - { - gotFetchImps = YES; - sgImp = (void (*)())[self methodForSelector: gcrSel]; - ogImp = (void (*)())[aString methodForSelector: gcrSel]; - } - (*sgImp)(self, gcrSel, buf0, r0); - (*ogImp)(aString, gcrSel, buf1, r1); - if (GSeq_compare(&s0, &s1) == NSOrderedSame) - { - myIndex += r0.length; - strIndex += r1.length; - } - else - return NO; - } - } - if ((myIndex == myLength) && (strIndex == strLength)) - return YES; - else - return NO; + return NO; } - (unsigned int) hash @@ -1781,8 +1075,6 @@ handle_printf_atsign (FILE *stream, (*sgImp)(self, gcrSel, sBuf, sRange); (*ogImp)(aString, gcrSel, oBuf, oRange); - GSeq_normalize(&sSeq); - GSeq_normalize(&oSeq); if (GSeq_compare(&sSeq, &oSeq) == NSOrderedSame) { sIndex += sRange.length;