libs-base/Source/GSeq.h
Richard Frith-MacDonald b618b41512 Another use of tolower() found and removed ... retain tolower() when the
internal 8bit encoding in not latin1 and uni_tolower() is therefore not
usable.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@35386 72102866-910b-0410-8b05-ffd578937521
2012-08-09 18:57:20 +00:00

1152 lines
26 KiB
C

/* Implementation of composite character sequence functions for GNUSTEP
Copyright (C) 1999 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Date: May 1999
Based on code by: Stevo Crvenkovski <stevo@btinternet.com>
Date: March 1997
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 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, and subclasses.
*/
#ifndef __GSeq_h_GNUSTEP_GSEQ_BASE_INCLUDE
#define __GSeq_h_GNUSTEP_GSEQ_BASE_INCLUDE
/*
* Some standard selectors for frequently used methods. Set in NSString
* +initialize or the GSString.m setup() function.
*/
static SEL caiSel = NULL;
static SEL gcrSel = NULL;
static SEL ranSel = NULL;
/*
* 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;
NSUInteger count;
NSUInteger 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 ... produces a
* sequence containing composed characters in a well defined order and
* with a nul terminator as well as a character count.
*/
static inline void GSeq_normalize(GSeq seq)
{
NSUInteger count = seq->count;
if (count)
{
unichar *source = seq->chars;
unichar target[count*MAXDEC+1];
NSUInteger base = 0;
/*
* Pre-scan ... anything with a code under 0x00C0 is not a decomposable
* character, so we don't need to expand it.
* If there are no decomposable characters or composed sequences, the
* sequence is already normalised and we don't need to make any changes.
*/
while (base < count)
{
if (source[base] >= 0x00C0)
{
break;
}
base++;
}
source[count] = (unichar)(0);
if (base < count)
{
/*
* Now expand decomposable characters into the long format.
* Use the 'base' value to avoid re-checking characters which have
* already been expanded.
*/
while (base < count)
{
unichar *spoint = &source[base];
unichar *tpoint = &target[base];
NSUInteger newbase = 0;
do
{
unichar *dpoint = uni_is_decomp(*spoint);
if (!dpoint)
{
*tpoint++ = *spoint;
}
else
{
while (*dpoint)
{
*tpoint++ = *dpoint++;
}
if (newbase <= 0)
{
newbase = (spoint - source) + 1;
}
}
}
while (*spoint++);
count = tpoint - target;
memcpy(&source[base], &target[base], 2*(count - base));
source[count] = (unichar)(0);
if (newbase > 0)
{
base = newbase;
}
else
{
base = count;
}
}
seq->count = count;
/*
* Now standardise ordering of all composed character sequences.
*/
if (count > 1)
{
BOOL notdone = YES;
while (notdone)
{
unichar *first = seq->chars;
unichar *second = first + 1;
NSUInteger i;
notdone = NO;
for (i = 1; i < count; i++)
{
if (GSPrivateUniCop(*second))
{
if (GSPrivateUniCop(*first)
> GSPrivateUniCop(*second))
{
unichar tmp = *first;
*first = *second;
*second = tmp;
notdone = YES;
}
else if (GSPrivateUniCop(*first)
== GSPrivateUniCop(*second))
{
if (*first > *second)
{
unichar tmp = *first;
*first = *second;
*second = tmp;
notdone = YES;
}
}
}
first++;
second++;
}
}
}
}
seq->normalized = YES;
}
}
/*
* A function to compare two unicode character sequences normalizing if
* required.
*/
static inline NSComparisonResult GSeq_compare(GSeq s0, GSeq s1)
{
NSUInteger i;
NSUInteger end;
NSUInteger len0;
NSUInteger len1;
unichar *c0 = s0->chars;
unichar *c1 = s1->chars;
len0 = s0->count;
len1 = s1->count;
if (len0 == len1)
{
for (i = 0; i < len1; i++)
{
if (c0[i] != c1[i])
{
break;
}
}
if (i == len0)
{
return NSOrderedSame;
}
}
if (s0->normalized == NO)
GSeq_normalize(s0);
if (s1->normalized == NO)
GSeq_normalize(s1);
len0 = s0->count;
len1 = s1->count;
if (len0 < len1)
end = len0;
else
end = len1;
for (i = 0; i < end; i++)
{
if (c0[i] < c1[i])
return NSOrderedAscending;
if (c0[i] > c1[i])
return NSOrderedDescending;
}
if (len0 < len1)
return NSOrderedAscending;
if (len0 > len1)
return NSOrderedDescending;
return NSOrderedSame;
}
static inline void GSeq_lowercase(GSeq seq)
{
unichar *s = seq->chars;
NSUInteger len = seq->count;
NSUInteger i;
for (i = 0; i < len; i++)
s[i] = uni_tolower(s[i]);
}
static inline void GSeq_uppercase(GSeq seq)
{
unichar *s = seq->chars;
NSUInteger len = seq->count;
NSUInteger i;
for (i = 0; i < len; i++)
s[i] = uni_toupper(s[i]);
}
/*
* Specify NSString, GSUString or GSCString
*/
#define GSEQ_NS 0
#define GSEQ_US 1
#define GSEQ_CS 2
/*
* Definitions for bitmask of search options. These MUST match the
* enumeration in NSString.h
*/
#define GSEQ_FCLS 3
#define GSEQ_BCLS 7
#define GSEQ_FLS 2
#define GSEQ_BLS 6
#define GSEQ_FCS 1
#define GSEQ_BCS 5
#define GSEQ_FS 0
#define GSEQ_BS 4
#define GSEQ_FCLAS 11
#define GSEQ_BCLAS 15
#define GSEQ_FLAS 10
#define GSEQ_BLAS 14
#define GSEQ_FCAS 9
#define GSEQ_BCAS 13
#define GESQ_FAS 8
#define GSEQ_BAS 12
#endif /* __GSeq_h_GNUSTEP_GSEQ_BASE_INCLUDE */
/*
* Set up macros for dealing with 'self' on the basis of GSQ_S
*/
#if GSEQ_S == GSEQ_US
#define GSEQ_ST GSStr
#define GSEQ_SLEN s->_count
#define GSEQ_SGETC(I) s->_contents.u[I]
#define GSEQ_SGETR(B,R) memcpy(B, &s->_contents.u[R.location], 2*(R).length)
#define GSEQ_SRANGE(I) (*srImp)((id)s, ranSel, I)
#else
#if GSEQ_S == GSEQ_CS
#define GSEQ_ST GSStr
#define GSEQ_SLEN s->_count
#define GSEQ_SGETC(I) (unichar)s->_contents.c[I]
#define GSEQ_SGETR(B,R) ( { \
NSUInteger _lcount = 0; \
while (_lcount < (R).length) \
{ \
(B)[_lcount] = (unichar)s->_contents.c[(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 GSStr
#define GSEQ_OLEN o->_count
#define GSEQ_OGETC(I) o->_contents.u[I]
#define GSEQ_OGETR(B,R) memcpy(B, &o->_contents.u[R.location], 2*(R).length)
#define GSEQ_ORANGE(I) (*orImp)((id)o, ranSel, I)
#else
#if GSEQ_O == GSEQ_CS
#define GSEQ_OT GSStr
#define GSEQ_OLEN o->_count
#define GSEQ_OGETC(I) (unichar)o->_contents.c[I]
#define GSEQ_OGETR(B,R) ( { \
NSUInteger _lcount = 0; \
while (_lcount < (R).length) \
{ \
(B)[_lcount] = (unichar)o->_contents.c[(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 NSComparisonResult
GSEQ_STRCOMP(NSString *ss, NSString *os, NSUInteger mask, NSRange aRange)
{
GSEQ_ST s = (GSEQ_ST)ss;
GSEQ_OT o = (GSEQ_OT)os;
NSUInteger oLength; /* Length of other. */
#if 0
/* Range should be checked in calling code */
if (aRange.location > GSEQ_SLEN)
[NSException raise: NSRangeException format: @"Invalid location."];
if (aRange.length > (GSEQ_SLEN - aRange.location))
[NSException raise: NSRangeException format: @"Invalid location+length."];
#endif
oLength = GSEQ_OLEN;
if (aRange.length == 0)
{
if (oLength == 0)
{
return NSOrderedSame;
}
return NSOrderedAscending;
}
else if (oLength == 0)
{
return NSOrderedDescending;
}
if (mask & NSLiteralSearch)
{
NSUInteger i;
NSUInteger sLen = aRange.length;
NSUInteger oLen = oLength;
NSUInteger end;
#if GSEQ_S == GSEQ_NS
void (*sgImp)(NSString*, SEL, unichar*, NSRange);
unichar sBuf[sLen];
#else
#if GSEQ_S == GSEQ_US
unichar *sBuf;
#else
unsigned 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
unsigned char *oBuf;
#endif
#endif
#if GSEQ_S == GSEQ_NS
sgImp = (void (*)(NSString*,SEL,unichar*,NSRange))
[(id)s methodForSelector: gcrSel];
GSEQ_SGETR(sBuf, aRange);
#else
#if GSEQ_S == GSEQ_CS
sBuf = &s->_contents.c[aRange.location];
#else
sBuf = &s->_contents.u[aRange.location];
#endif
#endif
#if GSEQ_O == GSEQ_NS
ogImp = (void (*)(NSString*,SEL,unichar*,NSRange))
[(id)o methodForSelector: gcrSel];
GSEQ_OGETR(oBuf, NSMakeRange(0, oLen));
#else
#if GSEQ_O == GSEQ_CS
oBuf = o->_contents.c;
#else
oBuf = o->_contents.u;
#endif
#endif
if (oLen < sLen)
end = oLen;
else
end = sLen;
if (mask & NSCaseInsensitiveSearch)
{
#if GSEQ_O == GSEQ_CS || GSEQ_S == GSEQ_CS
if (GSPrivateDefaultCStringEncoding() == NSISOLatin1StringEncoding)
{
/* Using latin1 internally, rather than native encoding,
* so we can't use native tolower() function.
*/
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
{
/* We are not using latin1 encoding internally, so we trust
* that the internal encoding matches the native encoding
* and the native tolower() function will work.
*/
for (i = 0; i < end; i++)
{
#if GSEQ_S == GSEQ_CS
unichar c1 = tolower(sBuf[i]);
#else
unichar c1 = uni_tolower((unichar)sBuf[i]);
#endif
#if GSEQ_O == GSEQ_CS
unichar c2 = tolower(oBuf[i]);
#else
unichar c2 = uni_tolower((unichar)oBuf[i]);
#endif
if (c1 < c2)
return NSOrderedAscending;
if (c1 > c2)
return NSOrderedDescending;
}
}
#else
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;
}
#endif
}
else
{
for (i = 0; i < end; i++)
{
#if GSEQ_O == GSEQ_CS && GSEQ_S == GSEQ_CS
if (sBuf[i] < oBuf[i])
return NSOrderedAscending;
if (sBuf[i] > oBuf[i])
return NSOrderedDescending;
#else
if ((unichar)sBuf[i] < (unichar)oBuf[i])
return NSOrderedAscending;
if ((unichar)sBuf[i] > (unichar)oBuf[i])
return NSOrderedDescending;
#endif
}
}
if (sLen > oLen)
return NSOrderedDescending;
else if (sLen < oLen)
return NSOrderedAscending;
else
return NSOrderedSame;
}
else
{
NSUInteger start = aRange.location;
NSUInteger end = start + aRange.length;
NSUInteger sLength = GSEQ_SLEN;
NSUInteger sCount = start;
NSUInteger oCount = 0;
NSComparisonResult result;
#if GSEQ_S == GSEQ_NS || GSEQ_S == GSEQ_US
NSRange (*srImp)(NSString*, SEL, NSUInteger);
#endif
#if GSEQ_O == GSEQ_NS || GSEQ_O == GSEQ_US
NSRange (*orImp)(NSString*, SEL, NSUInteger);
#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 (*)(NSString*, SEL, NSUInteger))
[(id)s methodForSelector: ranSel];
#endif
#if GSEQ_O == GSEQ_NS || GSEQ_O == GSEQ_US
orImp = (NSRange (*)(NSString*, SEL, NSUInteger))
[(id)o methodForSelector: ranSel];
#endif
#if GSEQ_S == GSEQ_NS
sgImp = (void (*)(NSString*, SEL, unichar*, NSRange))
[(id)s methodForSelector: gcrSel];
#endif
#if GSEQ_O == GSEQ_NS
ogImp = (void (*)(NSString*, SEL, unichar*, NSRange))
[(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 NSRange
GSEQ_STRRANGE(NSString *ss, NSString *os, NSUInteger mask, NSRange aRange)
{
GSEQ_ST s = (GSEQ_ST)ss;
GSEQ_OT o = (GSEQ_OT)os;
NSUInteger myIndex;
NSUInteger myEndIndex;
NSUInteger strLength;
#if GSEQ_S == GSEQ_NS
unichar (*scImp)(NSString*, SEL, NSUInteger);
void (*sgImp)(NSString*, SEL, unichar*, NSRange);
#endif
#if GSEQ_O == GSEQ_NS
unichar (*ocImp)(NSString*, SEL, NSUInteger);
void (*ogImp)(NSString*, SEL, unichar*, NSRange);
#endif
#if GSEQ_S == GSEQ_NS || GSEQ_S == GSEQ_US
NSRange (*srImp)(NSString*, SEL, NSUInteger);
#endif
#if GSEQ_O == GSEQ_NS || GSEQ_O == GSEQ_US
NSRange (*orImp)(NSString*, SEL, NSUInteger);
#endif
#if 0
/* Check that the search range is reasonable */
NSUInteger myLength = GSEQ_SLEN;
/* Range should be checked in calling code */
if (aRange.location > myLength)
[NSException raise: NSRangeException format: @"Invalid location."];
if (aRange.length > (myLength - aRange.location))
[NSException raise: NSRangeException format: @"Invalid location+length."];
#endif
/* Ensure the string can be found */
strLength = GSEQ_OLEN;
if (strLength > aRange.length || strLength == 0)
return (NSRange){NSNotFound, 0};
/*
* Cache method implementations for getting characters and ranges
*/
#if GSEQ_S == GSEQ_NS
scImp = (unichar (*)(NSString*,SEL,NSUInteger))
[(id)s methodForSelector: caiSel];
sgImp = (void (*)(NSString*,SEL,unichar*,NSRange))
[(id)s methodForSelector: gcrSel];
#endif
#if GSEQ_O == GSEQ_NS
ocImp = (unichar (*)(NSString*,SEL,NSUInteger))
[(id)o methodForSelector: caiSel];
ogImp = (void (*)(NSString*,SEL,unichar*,NSRange))
[(id)o methodForSelector: gcrSel];
#endif
#if GSEQ_S == GSEQ_NS || GSEQ_S == GSEQ_US
srImp = (NSRange (*)(NSString*,SEL,NSUInteger))
[(id)s methodForSelector: ranSel];
#endif
#if GSEQ_O == GSEQ_NS || GSEQ_O == GSEQ_US
orImp = (NSRange (*)(NSString*,SEL,NSUInteger))
[(id)o methodForSelector: ranSel];
#endif
switch (mask)
{
case GSEQ_FCLS:
case GSEQ_FCLAS:
{
unichar strFirstCharacter = GSEQ_OGETC(0);
myIndex = aRange.location;
myEndIndex = aRange.location + aRange.length - strLength;
if (mask & NSAnchoredSearch)
myEndIndex = myIndex;
for (;;)
{
NSUInteger 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){NSNotFound, 0};
}
case GSEQ_BCLS:
case GSEQ_BCLAS:
{
unichar strFirstCharacter = GSEQ_OGETC(0);
myIndex = aRange.location + aRange.length - strLength;
myEndIndex = aRange.location;
if (mask & NSAnchoredSearch)
myEndIndex = myIndex;
for (;;)
{
NSUInteger 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){NSNotFound, 0};
}
case GSEQ_FLS:
case GSEQ_FLAS:
{
unichar strFirstCharacter = GSEQ_OGETC(0);
myIndex = aRange.location;
myEndIndex = aRange.location + aRange.length - strLength;
if (mask & NSAnchoredSearch)
myEndIndex = myIndex;
for (;;)
{
NSUInteger 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){NSNotFound, 0};
}
case GSEQ_BLS:
case GSEQ_BLAS:
{
unichar strFirstCharacter = GSEQ_OGETC(0);
myIndex = aRange.location + aRange.length - strLength;
myEndIndex = aRange.location;
if (mask & NSAnchoredSearch)
myEndIndex = myIndex;
for (;;)
{
NSUInteger 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){NSNotFound, 0};
}
case GSEQ_FCS:
case GSEQ_FCAS:
{
NSUInteger 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)
{
NSUInteger myCount = sRange.length;
NSUInteger 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){NSNotFound, 0};
}
case GSEQ_BCS:
case GSEQ_BCAS:
{
NSUInteger 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)
{
NSUInteger myCount = sRange.length;
NSUInteger 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){NSNotFound, 0};
}
case GSEQ_BS:
case GSEQ_BAS:
{
NSUInteger 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)
{
NSUInteger myCount = sRange.length;
NSUInteger 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){NSNotFound, 0};
}
case GSEQ_FS:
case GESQ_FAS:
default:
{
NSUInteger 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)
{
NSUInteger myCount = sRange.length;
NSUInteger 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){NSNotFound, 0};
}
}
return (NSRange){NSNotFound, 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