Performance improvements

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@4273 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 1999-05-20 09:20:46 +00:00
parent f2d8bc8b52
commit 5063e7bbfc
6 changed files with 1021 additions and 734 deletions

View file

@ -1,3 +1,11 @@
Thu May 20 10:40:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* 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 <richard@brainstorm.co.uk>
* Source/GSeq.h: New file to replace NSGSequence stuff

View file

@ -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

View file

@ -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
#

View file

@ -41,6 +41,28 @@
#include <base/Unicode.h>
#include <base/fast.x>
/*
* 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 <GSeq.h>
#define GSEQ_STRCOMP strCompCsUs
#define GSEQ_STRRANGE strRangeCsUs
#define GSEQ_O GSEQ_US
#define GSEQ_S GSEQ_CS
#include <GSeq.h>
#define GSEQ_STRCOMP strCompCsCs
#define GSEQ_STRRANGE strRangeCsCs
#define GSEQ_O GSEQ_CS
#define GSEQ_S GSEQ_CS
#include <GSeq.h>
/*
* 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

View file

@ -47,6 +47,28 @@
#include <base/fast.x>
#include <base/Unicode.h>
/*
* 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 <GSeq.h>
#define GSEQ_STRCOMP strCompUsUs
#define GSEQ_STRRANGE strRangeUsUs
#define GSEQ_O GSEQ_US
#define GSEQ_S GSEQ_US
#include <GSeq.h>
#define GSEQ_STRCOMP strCompUsCs
#define GSEQ_STRRANGE strRangeUsCs
#define GSEQ_O GSEQ_CS
#define GSEQ_S GSEQ_US
#include <GSeq.h>
/*
* 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

View file

@ -71,7 +71,6 @@
#include <base/GetDefEncoding.h>
#include <base/NSGString.h>
#include <base/NSGCString.h>
#include <GSeq.h>
#include <base/fast.x>
@ -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 <GSeq.h>
/*
* 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;