• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **********************************************************************
3 *   Copyright (C) 1999-2007, International Business Machines
4 *   Corporation and others.  All Rights Reserved.
5 **********************************************************************
6 *   Date        Name        Description
7 *   10/20/99    alan        Creation.
8 **********************************************************************
9 */
10 
11 #include "unicode/utypes.h"
12 #include "unicode/uniset.h"
13 #include "unicode/parsepos.h"
14 #include "unicode/symtable.h"
15 #include "ruleiter.h"
16 #include "cmemory.h"
17 #include "cstring.h"
18 #include "uhash.h"
19 #include "util.h"
20 #include "uvector.h"
21 #include "charstr.h"
22 #include "ustrfmt.h"
23 #include "uassert.h"
24 #include "hash.h"
25 #include "bmpset.h"
26 #include "unisetspan.h"
27 
28 // Define UChar constants using hex for EBCDIC compatibility
29 // Used #define to reduce private static exports and memory access time.
30 #define SET_OPEN        ((UChar)0x005B) /*[*/
31 #define SET_CLOSE       ((UChar)0x005D) /*]*/
32 #define HYPHEN          ((UChar)0x002D) /*-*/
33 #define COMPLEMENT      ((UChar)0x005E) /*^*/
34 #define COLON           ((UChar)0x003A) /*:*/
35 #define BACKSLASH       ((UChar)0x005C) /*\*/
36 #define INTERSECTION    ((UChar)0x0026) /*&*/
37 #define UPPER_U         ((UChar)0x0055) /*U*/
38 #define LOWER_U         ((UChar)0x0075) /*u*/
39 #define OPEN_BRACE      ((UChar)123)    /*{*/
40 #define CLOSE_BRACE     ((UChar)125)    /*}*/
41 #define UPPER_P         ((UChar)0x0050) /*P*/
42 #define LOWER_P         ((UChar)0x0070) /*p*/
43 #define UPPER_N         ((UChar)78)     /*N*/
44 #define EQUALS          ((UChar)0x003D) /*=*/
45 
46 // HIGH_VALUE > all valid values. 110000 for codepoints
47 #define UNICODESET_HIGH 0x0110000
48 
49 // LOW <= all valid values. ZERO for codepoints
50 #define UNICODESET_LOW 0x000000
51 
52 // initial storage. Must be >= 0
53 #define START_EXTRA 16
54 
55 // extra amount for growth. Must be >= 0
56 #define GROW_EXTRA START_EXTRA
57 
58 U_NAMESPACE_BEGIN
59 
~SymbolTable()60 SymbolTable::~SymbolTable() {}
61 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeSet)62 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeSet)
63 
64 /**
65  * Modify the given UChar32 variable so that it is in range, by
66  * pinning values < UNICODESET_LOW to UNICODESET_LOW, and
67  * pinning values > UNICODESET_HIGH-1 to UNICODESET_HIGH-1.
68  * It modifies its argument in-place and also returns it.
69  */
70 static inline UChar32 pinCodePoint(UChar32& c) {
71     if (c < UNICODESET_LOW) {
72         c = UNICODESET_LOW;
73     } else if (c > (UNICODESET_HIGH-1)) {
74         c = (UNICODESET_HIGH-1);
75     }
76     return c;
77 }
78 
79 //----------------------------------------------------------------
80 // Debugging
81 //----------------------------------------------------------------
82 
83 // DO NOT DELETE THIS CODE.  This code is used to debug memory leaks.
84 // To enable the debugging, define the symbol DEBUG_MEM in the line
85 // below.  This will result in text being sent to stdout that looks
86 // like this:
87 //   DEBUG UnicodeSet: ct 0x00A39B20; 397 [\u0A81-\u0A83\u0A85-
88 //   DEBUG UnicodeSet: dt 0x00A39B20; 396 [\u0A81-\u0A83\u0A85-
89 // Each line lists a construction (ct) or destruction (dt) event, the
90 // object address, the number of outstanding objects after the event,
91 // and the pattern of the object in question.
92 
93 // #define DEBUG_MEM
94 
95 #ifdef DEBUG_MEM
96 #include <stdio.h>
97 static int32_t _dbgCount = 0;
98 
_dbgct(UnicodeSet * set)99 static inline void _dbgct(UnicodeSet* set) {
100     UnicodeString str;
101     set->toPattern(str, TRUE);
102     char buf[40];
103     str.extract(0, 39, buf, "");
104     printf("DEBUG UnicodeSet: ct 0x%08X; %d %s\n", set, ++_dbgCount, buf);
105 }
106 
_dbgdt(UnicodeSet * set)107 static inline void _dbgdt(UnicodeSet* set) {
108     UnicodeString str;
109     set->toPattern(str, TRUE);
110     char buf[40];
111     str.extract(0, 39, buf, "");
112     printf("DEBUG UnicodeSet: dt 0x%08X; %d %s\n", set, --_dbgCount, buf);
113 }
114 
115 #else
116 
117 #define _dbgct(set)
118 #define _dbgdt(set)
119 
120 #endif
121 
122 //----------------------------------------------------------------
123 // UnicodeString in UVector support
124 //----------------------------------------------------------------
125 
cloneUnicodeString(UHashTok * dst,UHashTok * src)126 static void U_CALLCONV cloneUnicodeString(UHashTok *dst, UHashTok *src) {
127     dst->pointer = new UnicodeString(*(UnicodeString*)src->pointer);
128 }
129 
compareUnicodeString(UHashTok t1,UHashTok t2)130 static int8_t U_CALLCONV compareUnicodeString(UHashTok t1, UHashTok t2) {
131     const UnicodeString &a = *(const UnicodeString*)t1.pointer;
132     const UnicodeString &b = *(const UnicodeString*)t2.pointer;
133     return a.compare(b);
134 }
135 
136 //----------------------------------------------------------------
137 // Constructors &c
138 //----------------------------------------------------------------
139 
140 /**
141  * Constructs an empty set.
142  */
UnicodeSet()143 UnicodeSet::UnicodeSet() :
144     len(1), capacity(1 + START_EXTRA), list(0), bmpSet(0), buffer(0),
145     bufferCapacity(0), patLen(0), pat(NULL), strings(NULL), stringSpan(NULL)
146 {
147     list = (UChar32*) uprv_malloc(sizeof(UChar32) * capacity);
148     if(list!=NULL){
149         list[0] = UNICODESET_HIGH;
150     }
151     UErrorCode status = U_ZERO_ERROR;
152     allocateStrings(status);
153     _dbgct(this);
154 }
155 
156 /**
157  * Constructs a set containing the given range. If <code>end >
158  * start</code> then an empty set is created.
159  *
160  * @param start first character, inclusive, of range
161  * @param end last character, inclusive, of range
162  */
UnicodeSet(UChar32 start,UChar32 end)163 UnicodeSet::UnicodeSet(UChar32 start, UChar32 end) :
164     len(1), capacity(1 + START_EXTRA), list(0), bmpSet(0), buffer(0),
165     bufferCapacity(0), patLen(0), pat(NULL), strings(NULL), stringSpan(NULL)
166 {
167     list = (UChar32*) uprv_malloc(sizeof(UChar32) * capacity);
168     if(list!=NULL){
169         UErrorCode status = U_ZERO_ERROR;
170 
171         list[0] = UNICODESET_HIGH;
172         allocateStrings(status);
173         complement(start, end);
174     }
175     _dbgct(this);
176 }
177 
178 /**
179  * Constructs a set that is identical to the given UnicodeSet.
180  */
UnicodeSet(const UnicodeSet & o)181 UnicodeSet::UnicodeSet(const UnicodeSet& o) :
182     UnicodeFilter(o),
183     len(0), capacity(o.isFrozen() ? o.len : o.len + GROW_EXTRA), list(0),
184     bmpSet(0),
185     buffer(0), bufferCapacity(0),
186     patLen(0), pat(NULL), strings(NULL), stringSpan(NULL)
187 {
188     list = (UChar32*) uprv_malloc(sizeof(UChar32) * capacity);
189     if(list!=NULL){
190         UErrorCode status = U_ZERO_ERROR;
191         allocateStrings(status);
192         *this = o;
193     }
194     _dbgct(this);
195 }
196 
197 // Copy-construct as thawed.
UnicodeSet(const UnicodeSet & o,UBool)198 UnicodeSet::UnicodeSet(const UnicodeSet& o, UBool /* asThawed */) :
199     UnicodeFilter(o),
200     len(0), capacity(o.len + GROW_EXTRA), list(0),
201     bmpSet(0),
202     buffer(0), bufferCapacity(0),
203     patLen(0), pat(NULL), strings(NULL), stringSpan(NULL)
204 {
205     list = (UChar32*) uprv_malloc(sizeof(UChar32) * capacity);
206     if(list!=NULL){
207         UErrorCode status = U_ZERO_ERROR;
208         allocateStrings(status);
209         // *this = o except for bmpSet and stringSpan
210         len = o.len;
211         uprv_memcpy(list, o.list, len*sizeof(UChar32));
212         strings->assign(*o.strings, cloneUnicodeString, status);
213         if (o.pat) {
214             setPattern(UnicodeString(o.pat, o.patLen));
215         }
216     }
217     _dbgct(this);
218 }
219 
220 /**
221  * Destructs the set.
222  */
~UnicodeSet()223 UnicodeSet::~UnicodeSet() {
224     _dbgdt(this); // first!
225     uprv_free(list);
226     delete bmpSet;
227     if (buffer) {
228         uprv_free(buffer);
229     }
230     delete strings;
231     delete stringSpan;
232     releasePattern();
233 }
234 
235 /**
236  * Assigns this object to be a copy of another.
237  */
operator =(const UnicodeSet & o)238 UnicodeSet& UnicodeSet::operator=(const UnicodeSet& o) {
239     if (this == &o) {
240         return *this;
241     }
242     if (isFrozen()) {
243         return *this;
244     }
245     ensureCapacity(o.len);
246     len = o.len;
247     uprv_memcpy(list, o.list, len*sizeof(UChar32));
248     if (o.bmpSet == NULL) {
249         bmpSet = NULL;
250     } else {
251         bmpSet = new BMPSet(*o.bmpSet, list, len);
252     }
253     UErrorCode ec = U_ZERO_ERROR;
254     strings->assign(*o.strings, cloneUnicodeString, ec);
255     if (o.stringSpan == NULL) {
256         stringSpan = NULL;
257     } else {
258         stringSpan = new UnicodeSetStringSpan(*o.stringSpan, *strings);
259     }
260     releasePattern();
261     if (o.pat) {
262         setPattern(UnicodeString(o.pat, o.patLen));
263     }
264     return *this;
265 }
266 
267 /**
268  * Returns a copy of this object.  All UnicodeMatcher objects have
269  * to support cloning in order to allow classes using
270  * UnicodeMatchers, such as Transliterator, to implement cloning.
271  */
clone() const272 UnicodeFunctor* UnicodeSet::clone() const {
273     return new UnicodeSet(*this);
274 }
275 
cloneAsThawed() const276 UnicodeFunctor *UnicodeSet::cloneAsThawed() const {
277     return new UnicodeSet(*this, TRUE);
278 }
279 
280 /**
281  * Compares the specified object with this set for equality.  Returns
282  * <tt>true</tt> if the two sets
283  * have the same size, and every member of the specified set is
284  * contained in this set (or equivalently, every member of this set is
285  * contained in the specified set).
286  *
287  * @param o set to be compared for equality with this set.
288  * @return <tt>true</tt> if the specified set is equal to this set.
289  */
operator ==(const UnicodeSet & o) const290 UBool UnicodeSet::operator==(const UnicodeSet& o) const {
291     if (len != o.len) return FALSE;
292     for (int32_t i = 0; i < len; ++i) {
293         if (list[i] != o.list[i]) return FALSE;
294     }
295     if (*strings != *o.strings) return FALSE;
296     return TRUE;
297 }
298 
299 /**
300  * Returns the hash code value for this set.
301  *
302  * @return the hash code value for this set.
303  * @see Object#hashCode()
304  */
hashCode(void) const305 int32_t UnicodeSet::hashCode(void) const {
306     int32_t result = len;
307     for (int32_t i = 0; i < len; ++i) {
308         result *= 1000003;
309         result += list[i];
310     }
311     return result;
312 }
313 
314 //----------------------------------------------------------------
315 // Public API
316 //----------------------------------------------------------------
317 
318 /**
319  * Returns the number of elements in this set (its cardinality),
320  * Note than the elements of a set may include both individual
321  * codepoints and strings.
322  *
323  * @return the number of elements in this set (its cardinality).
324  */
size(void) const325 int32_t UnicodeSet::size(void) const {
326     int32_t n = 0;
327     int32_t count = getRangeCount();
328     for (int32_t i = 0; i < count; ++i) {
329         n += getRangeEnd(i) - getRangeStart(i) + 1;
330     }
331     return n + strings->size();
332 }
333 
334 /**
335  * Returns <tt>true</tt> if this set contains no elements.
336  *
337  * @return <tt>true</tt> if this set contains no elements.
338  */
isEmpty(void) const339 UBool UnicodeSet::isEmpty(void) const {
340     return len == 1 && strings->size() == 0;
341 }
342 
343 /**
344  * Returns true if this set contains the given character.
345  * @param c character to be checked for containment
346  * @return true if the test condition is met
347  */
contains(UChar32 c) const348 UBool UnicodeSet::contains(UChar32 c) const {
349     // Set i to the index of the start item greater than ch
350     // We know we will terminate without length test!
351     // LATER: for large sets, add binary search
352     //int32_t i = -1;
353     //for (;;) {
354     //    if (c < list[++i]) break;
355     //}
356     if (bmpSet != NULL) {
357         return bmpSet->contains(c);
358     }
359     if (stringSpan != NULL) {
360         return stringSpan->contains(c);
361     }
362     if (c >= UNICODESET_HIGH) { // Don't need to check LOW bound
363         return FALSE;
364     }
365     int32_t i = findCodePoint(c);
366     return (UBool)(i & 1); // return true if odd
367 }
368 
369 /**
370  * Returns the smallest value i such that c < list[i].  Caller
371  * must ensure that c is a legal value or this method will enter
372  * an infinite loop.  This method performs a binary search.
373  * @param c a character in the range MIN_VALUE..MAX_VALUE
374  * inclusive
375  * @return the smallest integer i in the range 0..len-1,
376  * inclusive, such that c < list[i]
377  */
findCodePoint(UChar32 c) const378 int32_t UnicodeSet::findCodePoint(UChar32 c) const {
379     /* Examples:
380                                        findCodePoint(c)
381        set              list[]         c=0 1 3 4 7 8
382        ===              ==============   ===========
383        []               [110000]         0 0 0 0 0 0
384        [\u0000-\u0003]  [0, 4, 110000]   1 1 1 2 2 2
385        [\u0004-\u0007]  [4, 8, 110000]   0 0 0 1 1 2
386        [:Any:]          [0, 110000]      1 1 1 1 1 1
387      */
388 
389     // Return the smallest i such that c < list[i].  Assume
390     // list[len - 1] == HIGH and that c is legal (0..HIGH-1).
391     if (c < list[0])
392         return 0;
393     // High runner test.  c is often after the last range, so an
394     // initial check for this condition pays off.
395     int32_t lo = 0;
396     int32_t hi = len - 1;
397     if (lo >= hi || c >= list[hi-1])
398         return hi;
399     // invariant: c >= list[lo]
400     // invariant: c < list[hi]
401     for (;;) {
402         int32_t i = (lo + hi) >> 1;
403         if (i == lo) {
404             break; // Found!
405         } else if (c < list[i]) {
406             hi = i;
407         } else {
408             lo = i;
409         }
410     }
411     return hi;
412 }
413 
414 /**
415  * Returns true if this set contains every character
416  * of the given range.
417  * @param start first character, inclusive, of the range
418  * @param end last character, inclusive, of the range
419  * @return true if the test condition is met
420  */
contains(UChar32 start,UChar32 end) const421 UBool UnicodeSet::contains(UChar32 start, UChar32 end) const {
422     //int32_t i = -1;
423     //for (;;) {
424     //    if (start < list[++i]) break;
425     //}
426     int32_t i = findCodePoint(start);
427     return ((i & 1) != 0 && end < list[i]);
428 }
429 
430 /**
431  * Returns <tt>true</tt> if this set contains the given
432  * multicharacter string.
433  * @param s string to be checked for containment
434  * @return <tt>true</tt> if this set contains the specified string
435  */
contains(const UnicodeString & s) const436 UBool UnicodeSet::contains(const UnicodeString& s) const {
437     if (s.length() == 0) return FALSE;
438     int32_t cp = getSingleCP(s);
439     if (cp < 0) {
440         return strings->contains((void*) &s);
441     } else {
442         return contains((UChar32) cp);
443     }
444 }
445 
446 /**
447  * Returns true if this set contains all the characters and strings
448  * of the given set.
449  * @param c set to be checked for containment
450  * @return true if the test condition is met
451  */
containsAll(const UnicodeSet & c) const452 UBool UnicodeSet::containsAll(const UnicodeSet& c) const {
453     // The specified set is a subset if all of its pairs are contained in
454     // this set.  It's possible to code this more efficiently in terms of
455     // direct manipulation of the inversion lists if the need arises.
456     int32_t n = c.getRangeCount();
457     for (int i=0; i<n; ++i) {
458         if (!contains(c.getRangeStart(i), c.getRangeEnd(i))) {
459             return FALSE;
460         }
461     }
462     if (!strings->containsAll(*c.strings)) return FALSE;
463     return TRUE;
464 }
465 
466 /**
467  * Returns true if this set contains all the characters
468  * of the given string.
469  * @param s string containing characters to be checked for containment
470  * @return true if the test condition is met
471  */
containsAll(const UnicodeString & s) const472 UBool UnicodeSet::containsAll(const UnicodeString& s) const {
473     return (UBool)(span(s.getBuffer(), s.length(), USET_SPAN_CONTAINED) ==
474                    s.length());
475 }
476 
477 /**
478  * Returns true if this set contains none of the characters
479  * of the given range.
480  * @param start first character, inclusive, of the range
481  * @param end last character, inclusive, of the range
482  * @return true if the test condition is met
483  */
containsNone(UChar32 start,UChar32 end) const484 UBool UnicodeSet::containsNone(UChar32 start, UChar32 end) const {
485     //int32_t i = -1;
486     //for (;;) {
487     //    if (start < list[++i]) break;
488     //}
489     int32_t i = findCodePoint(start);
490     return ((i & 1) == 0 && end < list[i]);
491 }
492 
493 /**
494  * Returns true if this set contains none of the characters and strings
495  * of the given set.
496  * @param c set to be checked for containment
497  * @return true if the test condition is met
498  */
containsNone(const UnicodeSet & c) const499 UBool UnicodeSet::containsNone(const UnicodeSet& c) const {
500     // The specified set is a subset if all of its pairs are contained in
501     // this set.  It's possible to code this more efficiently in terms of
502     // direct manipulation of the inversion lists if the need arises.
503     int32_t n = c.getRangeCount();
504     for (int32_t i=0; i<n; ++i) {
505         if (!containsNone(c.getRangeStart(i), c.getRangeEnd(i))) {
506             return FALSE;
507         }
508     }
509     if (!strings->containsNone(*c.strings)) return FALSE;
510     return TRUE;
511 }
512 
513 /**
514  * Returns true if this set contains none of the characters
515  * of the given string.
516  * @param s string containing characters to be checked for containment
517  * @return true if the test condition is met
518  */
containsNone(const UnicodeString & s) const519 UBool UnicodeSet::containsNone(const UnicodeString& s) const {
520     return (UBool)(span(s.getBuffer(), s.length(), USET_SPAN_NOT_CONTAINED) ==
521                    s.length());
522 }
523 
524 /**
525  * Returns <tt>true</tt> if this set contains any character whose low byte
526  * is the given value.  This is used by <tt>RuleBasedTransliterator</tt> for
527  * indexing.
528  */
matchesIndexValue(uint8_t v) const529 UBool UnicodeSet::matchesIndexValue(uint8_t v) const {
530     /* The index value v, in the range [0,255], is contained in this set if
531      * it is contained in any pair of this set.  Pairs either have the high
532      * bytes equal, or unequal.  If the high bytes are equal, then we have
533      * aaxx..aayy, where aa is the high byte.  Then v is contained if xx <=
534      * v <= yy.  If the high bytes are unequal we have aaxx..bbyy, bb>aa.
535      * Then v is contained if xx <= v || v <= yy.  (This is identical to the
536      * time zone month containment logic.)
537      */
538     int32_t i;
539     int32_t rangeCount=getRangeCount();
540     for (i=0; i<rangeCount; ++i) {
541         UChar32 low = getRangeStart(i);
542         UChar32 high = getRangeEnd(i);
543         if ((low & ~0xFF) == (high & ~0xFF)) {
544             if ((low & 0xFF) <= v && v <= (high & 0xFF)) {
545                 return TRUE;
546             }
547         } else if ((low & 0xFF) <= v || v <= (high & 0xFF)) {
548             return TRUE;
549         }
550     }
551     if (strings->size() != 0) {
552         for (i=0; i<strings->size(); ++i) {
553             const UnicodeString& s = *(const UnicodeString*)strings->elementAt(i);
554             //if (s.length() == 0) {
555             //    // Empty strings match everything
556             //    return TRUE;
557             //}
558             // assert(s.length() != 0); // We enforce this elsewhere
559             UChar32 c = s.char32At(0);
560             if ((c & 0xFF) == v) {
561                 return TRUE;
562             }
563         }
564     }
565     return FALSE;
566 }
567 
568 /**
569  * Implementation of UnicodeMatcher::matches().  Always matches the
570  * longest possible multichar string.
571  */
matches(const Replaceable & text,int32_t & offset,int32_t limit,UBool incremental)572 UMatchDegree UnicodeSet::matches(const Replaceable& text,
573                                  int32_t& offset,
574                                  int32_t limit,
575                                  UBool incremental) {
576     if (offset == limit) {
577         // Strings, if any, have length != 0, so we don't worry
578         // about them here.  If we ever allow zero-length strings
579         // we much check for them here.
580         if (contains(U_ETHER)) {
581             return incremental ? U_PARTIAL_MATCH : U_MATCH;
582         } else {
583             return U_MISMATCH;
584         }
585     } else {
586         if (strings->size() != 0) { // try strings first
587 
588             // might separate forward and backward loops later
589             // for now they are combined
590 
591             // TODO Improve efficiency of this, at least in the forward
592             // direction, if not in both.  In the forward direction we
593             // can assume the strings are sorted.
594 
595             int32_t i;
596             UBool forward = offset < limit;
597 
598             // firstChar is the leftmost char to match in the
599             // forward direction or the rightmost char to match in
600             // the reverse direction.
601             UChar firstChar = text.charAt(offset);
602 
603             // If there are multiple strings that can match we
604             // return the longest match.
605             int32_t highWaterLength = 0;
606 
607             for (i=0; i<strings->size(); ++i) {
608                 const UnicodeString& trial = *(const UnicodeString*)strings->elementAt(i);
609 
610                 //if (trial.length() == 0) {
611                 //    return U_MATCH; // null-string always matches
612                 //}
613                 // assert(trial.length() != 0); // We ensure this elsewhere
614 
615                 UChar c = trial.charAt(forward ? 0 : trial.length() - 1);
616 
617                 // Strings are sorted, so we can optimize in the
618                 // forward direction.
619                 if (forward && c > firstChar) break;
620                 if (c != firstChar) continue;
621 
622                 int32_t matchLen = matchRest(text, offset, limit, trial);
623 
624                 if (incremental) {
625                     int32_t maxLen = forward ? limit-offset : offset-limit;
626                     if (matchLen == maxLen) {
627                         // We have successfully matched but only up to limit.
628                         return U_PARTIAL_MATCH;
629                     }
630                 }
631 
632                 if (matchLen == trial.length()) {
633                     // We have successfully matched the whole string.
634                     if (matchLen > highWaterLength) {
635                         highWaterLength = matchLen;
636                     }
637                     // In the forward direction we know strings
638                     // are sorted so we can bail early.
639                     if (forward && matchLen < highWaterLength) {
640                         break;
641                     }
642                     continue;
643                 }
644             }
645 
646             // We've checked all strings without a partial match.
647             // If we have full matches, return the longest one.
648             if (highWaterLength != 0) {
649                 offset += forward ? highWaterLength : -highWaterLength;
650                 return U_MATCH;
651             }
652         }
653         return UnicodeFilter::matches(text, offset, limit, incremental);
654     }
655 }
656 
657 /**
658  * Returns the longest match for s in text at the given position.
659  * If limit > start then match forward from start+1 to limit
660  * matching all characters except s.charAt(0).  If limit < start,
661  * go backward starting from start-1 matching all characters
662  * except s.charAt(s.length()-1).  This method assumes that the
663  * first character, text.charAt(start), matches s, so it does not
664  * check it.
665  * @param text the text to match
666  * @param start the first character to match.  In the forward
667  * direction, text.charAt(start) is matched against s.charAt(0).
668  * In the reverse direction, it is matched against
669  * s.charAt(s.length()-1).
670  * @param limit the limit offset for matching, either last+1 in
671  * the forward direction, or last-1 in the reverse direction,
672  * where last is the index of the last character to match.
673  * @return If part of s matches up to the limit, return |limit -
674  * start|.  If all of s matches before reaching the limit, return
675  * s.length().  If there is a mismatch between s and text, return
676  * 0
677  */
matchRest(const Replaceable & text,int32_t start,int32_t limit,const UnicodeString & s)678 int32_t UnicodeSet::matchRest(const Replaceable& text,
679                               int32_t start, int32_t limit,
680                               const UnicodeString& s) {
681     int32_t i;
682     int32_t maxLen;
683     int32_t slen = s.length();
684     if (start < limit) {
685         maxLen = limit - start;
686         if (maxLen > slen) maxLen = slen;
687         for (i = 1; i < maxLen; ++i) {
688             if (text.charAt(start + i) != s.charAt(i)) return 0;
689         }
690     } else {
691         maxLen = start - limit;
692         if (maxLen > slen) maxLen = slen;
693         --slen; // <=> slen = s.length() - 1;
694         for (i = 1; i < maxLen; ++i) {
695             if (text.charAt(start - i) != s.charAt(slen - i)) return 0;
696         }
697     }
698     return maxLen;
699 }
700 
701 /**
702  * Implement of UnicodeMatcher
703  */
addMatchSetTo(UnicodeSet & toUnionTo) const704 void UnicodeSet::addMatchSetTo(UnicodeSet& toUnionTo) const {
705     toUnionTo.addAll(*this);
706 }
707 
708 /**
709  * Returns the index of the given character within this set, where
710  * the set is ordered by ascending code point.  If the character
711  * is not in this set, return -1.  The inverse of this method is
712  * <code>charAt()</code>.
713  * @return an index from 0..size()-1, or -1
714  */
indexOf(UChar32 c) const715 int32_t UnicodeSet::indexOf(UChar32 c) const {
716     if (c < MIN_VALUE || c > MAX_VALUE) {
717         return -1;
718     }
719     int32_t i = 0;
720     int32_t n = 0;
721     for (;;) {
722         UChar32 start = list[i++];
723         if (c < start) {
724             return -1;
725         }
726         UChar32 limit = list[i++];
727         if (c < limit) {
728             return n + c - start;
729         }
730         n += limit - start;
731     }
732 }
733 
734 /**
735  * Returns the character at the given index within this set, where
736  * the set is ordered by ascending code point.  If the index is
737  * out of range, return (UChar32)-1.  The inverse of this method is
738  * <code>indexOf()</code>.
739  * @param index an index from 0..size()-1
740  * @return the character at the given index, or (UChar32)-1.
741  */
charAt(int32_t index) const742 UChar32 UnicodeSet::charAt(int32_t index) const {
743     if (index >= 0) {
744         // len2 is the largest even integer <= len, that is, it is len
745         // for even values and len-1 for odd values.  With odd values
746         // the last entry is UNICODESET_HIGH.
747         int32_t len2 = len & ~1;
748         for (int32_t i=0; i < len2;) {
749             UChar32 start = list[i++];
750             int32_t count = list[i++] - start;
751             if (index < count) {
752                 return (UChar32)(start + index);
753             }
754             index -= count;
755         }
756     }
757     return (UChar32)-1;
758 }
759 
760 /**
761  * Make this object represent the range <code>start - end</code>.
762  * If <code>end > start</code> then this object is set to an
763  * an empty range.
764  *
765  * @param start first character in the set, inclusive
766  * @rparam end last character in the set, inclusive
767  */
set(UChar32 start,UChar32 end)768 UnicodeSet& UnicodeSet::set(UChar32 start, UChar32 end) {
769     clear();
770     complement(start, end);
771     return *this;
772 }
773 
774 /**
775  * Adds the specified range to this set if it is not already
776  * present.  If this set already contains the specified range,
777  * the call leaves this set unchanged.  If <code>end > start</code>
778  * then an empty range is added, leaving the set unchanged.
779  *
780  * @param start first character, inclusive, of range to be added
781  * to this set.
782  * @param end last character, inclusive, of range to be added
783  * to this set.
784  */
add(UChar32 start,UChar32 end)785 UnicodeSet& UnicodeSet::add(UChar32 start, UChar32 end) {
786     if (pinCodePoint(start) < pinCodePoint(end)) {
787         UChar32 range[3] = { start, end+1, UNICODESET_HIGH };
788         add(range, 2, 0);
789     } else if (start == end) {
790         add(start);
791     }
792     return *this;
793 }
794 
795 // #define DEBUG_US_ADD
796 
797 #ifdef DEBUG_US_ADD
798 #include <stdio.h>
dump(UChar32 c)799 void dump(UChar32 c) {
800     if (c <= 0xFF) {
801         printf("%c", (char)c);
802     } else {
803         printf("U+%04X", c);
804     }
805 }
dump(const UChar32 * list,int32_t len)806 void dump(const UChar32* list, int32_t len) {
807     printf("[");
808     for (int32_t i=0; i<len; ++i) {
809         if (i != 0) printf(", ");
810         dump(list[i]);
811     }
812     printf("]");
813 }
814 #endif
815 
816 /**
817  * Adds the specified character to this set if it is not already
818  * present.  If this set already contains the specified character,
819  * the call leaves this set unchanged.
820  */
add(UChar32 c)821 UnicodeSet& UnicodeSet::add(UChar32 c) {
822     // find smallest i such that c < list[i]
823     // if odd, then it is IN the set
824     // if even, then it is OUT of the set
825     int32_t i = findCodePoint(pinCodePoint(c));
826 
827     // already in set?
828     if ((i & 1) != 0  || isFrozen()) return *this;
829 
830     // HIGH is 0x110000
831     // assert(list[len-1] == HIGH);
832 
833     // empty = [HIGH]
834     // [start_0, limit_0, start_1, limit_1, HIGH]
835 
836     // [..., start_k-1, limit_k-1, start_k, limit_k, ..., HIGH]
837     //                             ^
838     //                             list[i]
839 
840     // i == 0 means c is before the first range
841 
842 #ifdef DEBUG_US_ADD
843     printf("Add of ");
844     dump(c);
845     printf(" found at %d", i);
846     printf(": ");
847     dump(list, len);
848     printf(" => ");
849 #endif
850 
851     if (c == list[i]-1) {
852         // c is before start of next range
853         list[i] = c;
854         // if we touched the HIGH mark, then add a new one
855         if (c == (UNICODESET_HIGH - 1)) {
856             ensureCapacity(len+1);
857             list[len++] = UNICODESET_HIGH;
858         }
859         if (i > 0 && c == list[i-1]) {
860             // collapse adjacent ranges
861 
862             // [..., start_k-1, c, c, limit_k, ..., HIGH]
863             //                     ^
864             //                     list[i]
865 
866             //for (int32_t k=i-1; k<len-2; ++k) {
867             //    list[k] = list[k+2];
868             //}
869             UChar32* dst = list + i - 1;
870             UChar32* src = dst + 2;
871             UChar32* srclimit = list + len;
872             while (src < srclimit) *(dst++) = *(src++);
873 
874             len -= 2;
875         }
876     }
877 
878     else if (i > 0 && c == list[i-1]) {
879         // c is after end of prior range
880         list[i-1]++;
881         // no need to check for collapse here
882     }
883 
884     else {
885         // At this point we know the new char is not adjacent to
886         // any existing ranges, and it is not 10FFFF.
887 
888 
889         // [..., start_k-1, limit_k-1, start_k, limit_k, ..., HIGH]
890         //                             ^
891         //                             list[i]
892 
893         // [..., start_k-1, limit_k-1, c, c+1, start_k, limit_k, ..., HIGH]
894         //                             ^
895         //                             list[i]
896 
897         ensureCapacity(len+2);
898 
899         //for (int32_t k=len-1; k>=i; --k) {
900         //    list[k+2] = list[k];
901         //}
902         UChar32* src = list + len;
903         UChar32* dst = src + 2;
904         UChar32* srclimit = list + i;
905         while (src > srclimit) *(--dst) = *(--src);
906 
907         list[i] = c;
908         list[i+1] = c+1;
909         len += 2;
910     }
911 
912 #ifdef DEBUG_US_ADD
913     dump(list, len);
914     printf("\n");
915 
916     for (i=1; i<len; ++i) {
917         if (list[i] <= list[i-1]) {
918             // Corrupt array!
919             printf("ERROR: list has been corrupted\n");
920             exit(1);
921         }
922     }
923 #endif
924 
925     releasePattern();
926     return *this;
927 }
928 
929 /**
930  * Adds the specified multicharacter to this set if it is not already
931  * present.  If this set already contains the multicharacter,
932  * the call leaves this set unchanged.
933  * Thus "ch" => {"ch"}
934  * <br><b>Warning: you cannot add an empty string ("") to a UnicodeSet.</b>
935  * @param s the source string
936  * @return the modified set, for chaining
937  */
add(const UnicodeString & s)938 UnicodeSet& UnicodeSet::add(const UnicodeString& s) {
939     if (s.length() == 0 || isFrozen()) return *this;
940     int32_t cp = getSingleCP(s);
941     if (cp < 0) {
942         if (!strings->contains((void*) &s)) {
943             _add(s);
944             releasePattern();
945         }
946     } else {
947         add((UChar32)cp);
948     }
949     return *this;
950 }
951 
952 /**
953  * Adds the given string, in order, to 'strings'.  The given string
954  * must have been checked by the caller to not be empty and to not
955  * already be in 'strings'.
956  */
_add(const UnicodeString & s)957 void UnicodeSet::_add(const UnicodeString& s) {
958     if (isFrozen()) {
959         return;
960     }
961     UnicodeString* t = new UnicodeString(s);
962     UErrorCode ec = U_ZERO_ERROR;
963     strings->sortedInsert(t, compareUnicodeString, ec);
964 }
965 
966 /**
967  * @return a code point IF the string consists of a single one.
968  * otherwise returns -1.
969  * @param string to test
970  */
getSingleCP(const UnicodeString & s)971 int32_t UnicodeSet::getSingleCP(const UnicodeString& s) {
972     //if (s.length() < 1) {
973     //    throw new IllegalArgumentException("Can't use zero-length strings in UnicodeSet");
974     //}
975     if (s.length() > 2) return -1;
976     if (s.length() == 1) return s.charAt(0);
977 
978     // at this point, len = 2
979     UChar32 cp = s.char32At(0);
980     if (cp > 0xFFFF) { // is surrogate pair
981         return cp;
982     }
983     return -1;
984 }
985 
986 /**
987  * Adds each of the characters in this string to the set. Thus "ch" => {"c", "h"}
988  * If this set already any particular character, it has no effect on that character.
989  * @param the source string
990  * @return the modified set, for chaining
991  */
addAll(const UnicodeString & s)992 UnicodeSet& UnicodeSet::addAll(const UnicodeString& s) {
993     UChar32 cp;
994     for (int32_t i = 0; i < s.length(); i += UTF_CHAR_LENGTH(cp)) {
995         cp = s.char32At(i);
996         add(cp);
997     }
998     return *this;
999 }
1000 
1001 /**
1002  * Retains EACH of the characters in this string. Note: "ch" == {"c", "h"}
1003  * If this set already any particular character, it has no effect on that character.
1004  * @param the source string
1005  * @return the modified set, for chaining
1006  */
retainAll(const UnicodeString & s)1007 UnicodeSet& UnicodeSet::retainAll(const UnicodeString& s) {
1008     UnicodeSet set;
1009     set.addAll(s);
1010     retainAll(set);
1011     return *this;
1012 }
1013 
1014 /**
1015  * Complement EACH of the characters in this string. Note: "ch" == {"c", "h"}
1016  * If this set already any particular character, it has no effect on that character.
1017  * @param the source string
1018  * @return the modified set, for chaining
1019  */
complementAll(const UnicodeString & s)1020 UnicodeSet& UnicodeSet::complementAll(const UnicodeString& s) {
1021     UnicodeSet set;
1022     set.addAll(s);
1023     complementAll(set);
1024     return *this;
1025 }
1026 
1027 /**
1028  * Remove EACH of the characters in this string. Note: "ch" == {"c", "h"}
1029  * If this set already any particular character, it has no effect on that character.
1030  * @param the source string
1031  * @return the modified set, for chaining
1032  */
removeAll(const UnicodeString & s)1033 UnicodeSet& UnicodeSet::removeAll(const UnicodeString& s) {
1034     UnicodeSet set;
1035     set.addAll(s);
1036     removeAll(set);
1037     return *this;
1038 }
1039 
removeAllStrings()1040 UnicodeSet& UnicodeSet::removeAllStrings() {
1041     strings->removeAllElements();
1042     return *this;
1043 }
1044 
1045 
1046 /**
1047  * Makes a set from a multicharacter string. Thus "ch" => {"ch"}
1048  * <br><b>Warning: you cannot add an empty string ("") to a UnicodeSet.</b>
1049  * @param the source string
1050  * @return a newly created set containing the given string
1051  */
createFrom(const UnicodeString & s)1052 UnicodeSet* U_EXPORT2 UnicodeSet::createFrom(const UnicodeString& s) {
1053     UnicodeSet *set = new UnicodeSet();
1054     set->add(s);
1055     return set;
1056 }
1057 
1058 
1059 /**
1060  * Makes a set from each of the characters in the string. Thus "ch" => {"c", "h"}
1061  * @param the source string
1062  * @return a newly created set containing the given characters
1063  */
createFromAll(const UnicodeString & s)1064 UnicodeSet* U_EXPORT2 UnicodeSet::createFromAll(const UnicodeString& s) {
1065     UnicodeSet *set = new UnicodeSet();
1066     set->addAll(s);
1067     return set;
1068 }
1069 
1070 /**
1071  * Retain only the elements in this set that are contained in the
1072  * specified range.  If <code>end > start</code> then an empty range is
1073  * retained, leaving the set empty.
1074  *
1075  * @param start first character, inclusive, of range to be retained
1076  * to this set.
1077  * @param end last character, inclusive, of range to be retained
1078  * to this set.
1079  */
retain(UChar32 start,UChar32 end)1080 UnicodeSet& UnicodeSet::retain(UChar32 start, UChar32 end) {
1081     if (pinCodePoint(start) <= pinCodePoint(end)) {
1082         UChar32 range[3] = { start, end+1, UNICODESET_HIGH };
1083         retain(range, 2, 0);
1084     } else {
1085         clear();
1086     }
1087     return *this;
1088 }
1089 
retain(UChar32 c)1090 UnicodeSet& UnicodeSet::retain(UChar32 c) {
1091     return retain(c, c);
1092 }
1093 
1094 /**
1095  * Removes the specified range from this set if it is present.
1096  * The set will not contain the specified range once the call
1097  * returns.  If <code>end > start</code> then an empty range is
1098  * removed, leaving the set unchanged.
1099  *
1100  * @param start first character, inclusive, of range to be removed
1101  * from this set.
1102  * @param end last character, inclusive, of range to be removed
1103  * from this set.
1104  */
remove(UChar32 start,UChar32 end)1105 UnicodeSet& UnicodeSet::remove(UChar32 start, UChar32 end) {
1106     if (pinCodePoint(start) <= pinCodePoint(end)) {
1107         UChar32 range[3] = { start, end+1, UNICODESET_HIGH };
1108         retain(range, 2, 2);
1109     }
1110     return *this;
1111 }
1112 
1113 /**
1114  * Removes the specified character from this set if it is present.
1115  * The set will not contain the specified range once the call
1116  * returns.
1117  */
remove(UChar32 c)1118 UnicodeSet& UnicodeSet::remove(UChar32 c) {
1119     return remove(c, c);
1120 }
1121 
1122 /**
1123  * Removes the specified string from this set if it is present.
1124  * The set will not contain the specified character once the call
1125  * returns.
1126  * @param the source string
1127  * @return the modified set, for chaining
1128  */
remove(const UnicodeString & s)1129 UnicodeSet& UnicodeSet::remove(const UnicodeString& s) {
1130     if (s.length() == 0 || isFrozen()) return *this;
1131     int32_t cp = getSingleCP(s);
1132     if (cp < 0) {
1133         strings->removeElement((void*) &s);
1134         releasePattern();
1135     } else {
1136         remove((UChar32)cp, (UChar32)cp);
1137     }
1138     return *this;
1139 }
1140 
1141 /**
1142  * Complements the specified range in this set.  Any character in
1143  * the range will be removed if it is in this set, or will be
1144  * added if it is not in this set.  If <code>end > start</code>
1145  * then an empty range is xor'ed, leaving the set unchanged.
1146  *
1147  * @param start first character, inclusive, of range to be removed
1148  * from this set.
1149  * @param end last character, inclusive, of range to be removed
1150  * from this set.
1151  */
complement(UChar32 start,UChar32 end)1152 UnicodeSet& UnicodeSet::complement(UChar32 start, UChar32 end) {
1153     if (isFrozen()) {
1154         return *this;
1155     }
1156     if (pinCodePoint(start) <= pinCodePoint(end)) {
1157         UChar32 range[3] = { start, end+1, UNICODESET_HIGH };
1158         exclusiveOr(range, 2, 0);
1159     }
1160     releasePattern();
1161     return *this;
1162 }
1163 
complement(UChar32 c)1164 UnicodeSet& UnicodeSet::complement(UChar32 c) {
1165     return complement(c, c);
1166 }
1167 
1168 /**
1169  * This is equivalent to
1170  * <code>complement(MIN_VALUE, MAX_VALUE)</code>.
1171  */
complement(void)1172 UnicodeSet& UnicodeSet::complement(void) {
1173     if (isFrozen()) {
1174         return *this;
1175     }
1176     if (list[0] == UNICODESET_LOW) {
1177         ensureBufferCapacity(len-1);
1178         uprv_memcpy(buffer, list + 1, (len-1)*sizeof(UChar32));
1179         --len;
1180     } else {
1181         ensureBufferCapacity(len+1);
1182         uprv_memcpy(buffer + 1, list, len*sizeof(UChar32));
1183         buffer[0] = UNICODESET_LOW;
1184         ++len;
1185     }
1186     swapBuffers();
1187     releasePattern();
1188     return *this;
1189 }
1190 
1191 /**
1192  * Complement the specified string in this set.
1193  * The set will not contain the specified string once the call
1194  * returns.
1195  * <br><b>Warning: you cannot add an empty string ("") to a UnicodeSet.</b>
1196  * @param s the string to complement
1197  * @return this object, for chaining
1198  */
complement(const UnicodeString & s)1199 UnicodeSet& UnicodeSet::complement(const UnicodeString& s) {
1200     if (s.length() == 0 || isFrozen()) return *this;
1201     int32_t cp = getSingleCP(s);
1202     if (cp < 0) {
1203         if (strings->contains((void*) &s)) {
1204             strings->removeElement((void*) &s);
1205         } else {
1206             _add(s);
1207         }
1208         releasePattern();
1209     } else {
1210         complement((UChar32)cp, (UChar32)cp);
1211     }
1212     return *this;
1213 }
1214 
1215 /**
1216  * Adds all of the elements in the specified set to this set if
1217  * they're not already present.  This operation effectively
1218  * modifies this set so that its value is the <i>union</i> of the two
1219  * sets.  The behavior of this operation is unspecified if the specified
1220  * collection is modified while the operation is in progress.
1221  *
1222  * @param c set whose elements are to be added to this set.
1223  * @see #add(char, char)
1224  */
addAll(const UnicodeSet & c)1225 UnicodeSet& UnicodeSet::addAll(const UnicodeSet& c) {
1226     add(c.list, c.len, 0);
1227 
1228     // Add strings in order
1229     for (int32_t i=0; i<c.strings->size(); ++i) {
1230         const UnicodeString* s = (const UnicodeString*)c.strings->elementAt(i);
1231         if (!strings->contains((void*) s)) {
1232             _add(*s);
1233         }
1234     }
1235     return *this;
1236 }
1237 
1238 /**
1239  * Retains only the elements in this set that are contained in the
1240  * specified set.  In other words, removes from this set all of
1241  * its elements that are not contained in the specified set.  This
1242  * operation effectively modifies this set so that its value is
1243  * the <i>intersection</i> of the two sets.
1244  *
1245  * @param c set that defines which elements this set will retain.
1246  */
retainAll(const UnicodeSet & c)1247 UnicodeSet& UnicodeSet::retainAll(const UnicodeSet& c) {
1248     if (isFrozen()) {
1249         return *this;
1250     }
1251     retain(c.list, c.len, 0);
1252     strings->retainAll(*c.strings);
1253     return *this;
1254 }
1255 
1256 /**
1257  * Removes from this set all of its elements that are contained in the
1258  * specified set.  This operation effectively modifies this
1259  * set so that its value is the <i>asymmetric set difference</i> of
1260  * the two sets.
1261  *
1262  * @param c set that defines which elements will be removed from
1263  *          this set.
1264  */
removeAll(const UnicodeSet & c)1265 UnicodeSet& UnicodeSet::removeAll(const UnicodeSet& c) {
1266     if (isFrozen()) {
1267         return *this;
1268     }
1269     retain(c.list, c.len, 2);
1270     strings->removeAll(*c.strings);
1271     return *this;
1272 }
1273 
1274 /**
1275  * Complements in this set all elements contained in the specified
1276  * set.  Any character in the other set will be removed if it is
1277  * in this set, or will be added if it is not in this set.
1278  *
1279  * @param c set that defines which elements will be xor'ed from
1280  *          this set.
1281  */
complementAll(const UnicodeSet & c)1282 UnicodeSet& UnicodeSet::complementAll(const UnicodeSet& c) {
1283     if (isFrozen()) {
1284         return *this;
1285     }
1286     exclusiveOr(c.list, c.len, 0);
1287 
1288     for (int32_t i=0; i<c.strings->size(); ++i) {
1289         void* e = c.strings->elementAt(i);
1290         if (!strings->removeElement(e)) {
1291             _add(*(const UnicodeString*)e);
1292         }
1293     }
1294     return *this;
1295 }
1296 
1297 /**
1298  * Removes all of the elements from this set.  This set will be
1299  * empty after this call returns.
1300  */
clear(void)1301 UnicodeSet& UnicodeSet::clear(void) {
1302     if (isFrozen()) {
1303         return *this;
1304     }
1305     list[0] = UNICODESET_HIGH;
1306     len = 1;
1307     releasePattern();
1308     strings->removeAllElements();
1309     return *this;
1310 }
1311 
1312 /**
1313  * Iteration method that returns the number of ranges contained in
1314  * this set.
1315  * @see #getRangeStart
1316  * @see #getRangeEnd
1317  */
getRangeCount() const1318 int32_t UnicodeSet::getRangeCount() const {
1319     return len/2;
1320 }
1321 
1322 /**
1323  * Iteration method that returns the first character in the
1324  * specified range of this set.
1325  * @see #getRangeCount
1326  * @see #getRangeEnd
1327  */
getRangeStart(int32_t index) const1328 UChar32 UnicodeSet::getRangeStart(int32_t index) const {
1329     return list[index*2];
1330 }
1331 
1332 /**
1333  * Iteration method that returns the last character in the
1334  * specified range of this set.
1335  * @see #getRangeStart
1336  * @see #getRangeEnd
1337  */
getRangeEnd(int32_t index) const1338 UChar32 UnicodeSet::getRangeEnd(int32_t index) const {
1339     return list[index*2 + 1] - 1;
1340 }
1341 
getStringCount() const1342 int32_t UnicodeSet::getStringCount() const {
1343     return strings->size();
1344 }
1345 
getString(int32_t index) const1346 const UnicodeString* UnicodeSet::getString(int32_t index) const {
1347     return (const UnicodeString*) strings->elementAt(index);
1348 }
1349 
1350 /**
1351  * Reallocate this objects internal structures to take up the least
1352  * possible space, without changing this object's value.
1353  */
compact()1354 UnicodeSet& UnicodeSet::compact() {
1355     if (isFrozen()) {
1356         return *this;
1357     }
1358     // Delete buffer first to defragment memory less.
1359     if (buffer != NULL) {
1360         uprv_free(buffer);
1361         buffer = NULL;
1362     }
1363     if (len < capacity) {
1364         // Make the capacity equal to len or 1.
1365         // We don't want to realloc of 0 size.
1366         capacity = len + (len == 0);
1367         list = (UChar32*) uprv_realloc(list, sizeof(UChar32) * capacity);
1368     }
1369     return *this;
1370 }
1371 
serialize(uint16_t * dest,int32_t destCapacity,UErrorCode & ec) const1372 int32_t UnicodeSet::serialize(uint16_t *dest, int32_t destCapacity, UErrorCode& ec) const {
1373     int32_t bmpLength, length, destLength;
1374 
1375     if (U_FAILURE(ec)) {
1376         return 0;
1377     }
1378 
1379     if (destCapacity<0 || (destCapacity>0 && dest==NULL)) {
1380         ec=U_ILLEGAL_ARGUMENT_ERROR;
1381         return 0;
1382     }
1383 
1384     /* count necessary 16-bit units */
1385     length=this->len-1; // Subtract 1 to ignore final UNICODESET_HIGH
1386     // assert(length>=0);
1387     if (length==0) {
1388         /* empty set */
1389         if (destCapacity>0) {
1390             *dest=0;
1391         } else {
1392             ec=U_BUFFER_OVERFLOW_ERROR;
1393         }
1394         return 1;
1395     }
1396     /* now length>0 */
1397 
1398     if (this->list[length-1]<=0xffff) {
1399         /* all BMP */
1400         bmpLength=length;
1401     } else if (this->list[0]>=0x10000) {
1402         /* all supplementary */
1403         bmpLength=0;
1404         length*=2;
1405     } else {
1406         /* some BMP, some supplementary */
1407         for (bmpLength=0; bmpLength<length && this->list[bmpLength]<=0xffff; ++bmpLength) {}
1408         length=bmpLength+2*(length-bmpLength);
1409     }
1410 
1411     /* length: number of 16-bit array units */
1412     if (length>0x7fff) {
1413         /* there are only 15 bits for the length in the first serialized word */
1414         ec=U_INDEX_OUTOFBOUNDS_ERROR;
1415         return 0;
1416     }
1417 
1418     /*
1419      * total serialized length:
1420      * number of 16-bit array units (length) +
1421      * 1 length unit (always) +
1422      * 1 bmpLength unit (if there are supplementary values)
1423      */
1424     destLength=length+((length>bmpLength)?2:1);
1425     if (destLength<=destCapacity) {
1426         const UChar32 *p;
1427         int32_t i;
1428 
1429         *dest=(uint16_t)length;
1430         if (length>bmpLength) {
1431             *dest|=0x8000;
1432             *++dest=(uint16_t)bmpLength;
1433         }
1434         ++dest;
1435 
1436         /* write the BMP part of the array */
1437         p=this->list;
1438         for (i=0; i<bmpLength; ++i) {
1439             *dest++=(uint16_t)*p++;
1440         }
1441 
1442         /* write the supplementary part of the array */
1443         for (; i<length; i+=2) {
1444             *dest++=(uint16_t)(*p>>16);
1445             *dest++=(uint16_t)*p++;
1446         }
1447     } else {
1448         ec=U_BUFFER_OVERFLOW_ERROR;
1449     }
1450     return destLength;
1451 }
1452 
1453 //----------------------------------------------------------------
1454 // Implementation: Utility methods
1455 //----------------------------------------------------------------
1456 
1457 /**
1458  * Allocate our strings vector and return TRUE if successful.
1459  */
allocateStrings(UErrorCode & status)1460 UBool UnicodeSet::allocateStrings(UErrorCode &status) {
1461     if (U_FAILURE(status)) {
1462         return FALSE;
1463     }
1464     strings = new UVector(uhash_deleteUnicodeString,
1465                           uhash_compareUnicodeString, 1, status);
1466     if (U_FAILURE(status)) {
1467         delete strings;
1468         strings = NULL;
1469         return FALSE;
1470     }
1471     return TRUE;
1472 }
1473 
ensureCapacity(int32_t newLen)1474 void UnicodeSet::ensureCapacity(int32_t newLen) {
1475     if (newLen <= capacity)
1476         return;
1477     capacity = newLen + GROW_EXTRA;
1478     UChar32* temp = (UChar32*) uprv_malloc(sizeof(UChar32) * capacity);
1479     uprv_memcpy(temp, list, len*sizeof(UChar32));
1480     uprv_free(list);
1481     list = temp;
1482 }
1483 
ensureBufferCapacity(int32_t newLen)1484 void UnicodeSet::ensureBufferCapacity(int32_t newLen) {
1485     if (buffer != NULL && newLen <= bufferCapacity)
1486         return;
1487     if (buffer) {
1488         uprv_free(buffer);
1489     }
1490     bufferCapacity = newLen + GROW_EXTRA;
1491     buffer = (UChar32*) uprv_malloc(sizeof(UChar32) * bufferCapacity);
1492 }
1493 
1494 /**
1495  * Swap list and buffer.
1496  */
swapBuffers(void)1497 void UnicodeSet::swapBuffers(void) {
1498     // swap list and buffer
1499     UChar32* temp = list;
1500     list = buffer;
1501     buffer = temp;
1502 
1503     int32_t c = capacity;
1504     capacity = bufferCapacity;
1505     bufferCapacity = c;
1506 }
1507 
1508 //----------------------------------------------------------------
1509 // Implementation: Fundamental operators
1510 //----------------------------------------------------------------
1511 
max(UChar32 a,UChar32 b)1512 static inline UChar32 max(UChar32 a, UChar32 b) {
1513     return (a > b) ? a : b;
1514 }
1515 
1516 // polarity = 0, 3 is normal: x xor y
1517 // polarity = 1, 2: x xor ~y == x === y
1518 
exclusiveOr(const UChar32 * other,int32_t otherLen,int8_t polarity)1519 void UnicodeSet::exclusiveOr(const UChar32* other, int32_t otherLen, int8_t polarity) {
1520     if (isFrozen()) {
1521         return;
1522     }
1523     ensureBufferCapacity(len + otherLen);
1524     int32_t i = 0, j = 0, k = 0;
1525     UChar32 a = list[i++];
1526     UChar32 b;
1527     if (polarity == 1 || polarity == 2) {
1528         b = UNICODESET_LOW;
1529         if (other[j] == UNICODESET_LOW) { // skip base if already LOW
1530             ++j;
1531             b = other[j];
1532         }
1533     } else {
1534         b = other[j++];
1535     }
1536     // simplest of all the routines
1537     // sort the values, discarding identicals!
1538     for (;;) {
1539         if (a < b) {
1540             buffer[k++] = a;
1541             a = list[i++];
1542         } else if (b < a) {
1543             buffer[k++] = b;
1544             b = other[j++];
1545         } else if (a != UNICODESET_HIGH) { // at this point, a == b
1546             // discard both values!
1547             a = list[i++];
1548             b = other[j++];
1549         } else { // DONE!
1550             buffer[k++] = UNICODESET_HIGH;
1551             len = k;
1552             break;
1553         }
1554     }
1555     swapBuffers();
1556     releasePattern();
1557 }
1558 
1559 // polarity = 0 is normal: x union y
1560 // polarity = 2: x union ~y
1561 // polarity = 1: ~x union y
1562 // polarity = 3: ~x union ~y
1563 
add(const UChar32 * other,int32_t otherLen,int8_t polarity)1564 void UnicodeSet::add(const UChar32* other, int32_t otherLen, int8_t polarity) {
1565     if (isFrozen()) {
1566         return;
1567     }
1568     ensureBufferCapacity(len + otherLen);
1569     int32_t i = 0, j = 0, k = 0;
1570     UChar32 a = list[i++];
1571     UChar32 b = other[j++];
1572     // change from xor is that we have to check overlapping pairs
1573     // polarity bit 1 means a is second, bit 2 means b is.
1574     for (;;) {
1575         switch (polarity) {
1576           case 0: // both first; take lower if unequal
1577             if (a < b) { // take a
1578                 // Back up over overlapping ranges in buffer[]
1579                 if (k > 0 && a <= buffer[k-1]) {
1580                     // Pick latter end value in buffer[] vs. list[]
1581                     a = max(list[i], buffer[--k]);
1582                 } else {
1583                     // No overlap
1584                     buffer[k++] = a;
1585                     a = list[i];
1586                 }
1587                 i++; // Common if/else code factored out
1588                 polarity ^= 1;
1589             } else if (b < a) { // take b
1590                 if (k > 0 && b <= buffer[k-1]) {
1591                     b = max(other[j], buffer[--k]);
1592                 } else {
1593                     buffer[k++] = b;
1594                     b = other[j];
1595                 }
1596                 j++;
1597                 polarity ^= 2;
1598             } else { // a == b, take a, drop b
1599                 if (a == UNICODESET_HIGH) goto loop_end;
1600                 // This is symmetrical; it doesn't matter if
1601                 // we backtrack with a or b. - liu
1602                 if (k > 0 && a <= buffer[k-1]) {
1603                     a = max(list[i], buffer[--k]);
1604                 } else {
1605                     // No overlap
1606                     buffer[k++] = a;
1607                     a = list[i];
1608                 }
1609                 i++;
1610                 polarity ^= 1;
1611                 b = other[j++];
1612                 polarity ^= 2;
1613             }
1614             break;
1615           case 3: // both second; take higher if unequal, and drop other
1616             if (b <= a) { // take a
1617                 if (a == UNICODESET_HIGH) goto loop_end;
1618                 buffer[k++] = a;
1619             } else { // take b
1620                 if (b == UNICODESET_HIGH) goto loop_end;
1621                 buffer[k++] = b;
1622             }
1623             a = list[i++];
1624             polarity ^= 1;   // factored common code
1625             b = other[j++];
1626             polarity ^= 2;
1627             break;
1628           case 1: // a second, b first; if b < a, overlap
1629             if (a < b) { // no overlap, take a
1630                 buffer[k++] = a; a = list[i++]; polarity ^= 1;
1631             } else if (b < a) { // OVERLAP, drop b
1632                 b = other[j++];
1633                 polarity ^= 2;
1634             } else { // a == b, drop both!
1635                 if (a == UNICODESET_HIGH) goto loop_end;
1636                 a = list[i++];
1637                 polarity ^= 1;
1638                 b = other[j++];
1639                 polarity ^= 2;
1640             }
1641             break;
1642           case 2: // a first, b second; if a < b, overlap
1643             if (b < a) { // no overlap, take b
1644                 buffer[k++] = b;
1645                 b = other[j++];
1646                 polarity ^= 2;
1647             } else  if (a < b) { // OVERLAP, drop a
1648                 a = list[i++];
1649                 polarity ^= 1;
1650             } else { // a == b, drop both!
1651                 if (a == UNICODESET_HIGH) goto loop_end;
1652                 a = list[i++];
1653                 polarity ^= 1;
1654                 b = other[j++];
1655                 polarity ^= 2;
1656             }
1657             break;
1658         }
1659     }
1660  loop_end:
1661     buffer[k++] = UNICODESET_HIGH;    // terminate
1662     len = k;
1663     swapBuffers();
1664     releasePattern();
1665 }
1666 
1667 // polarity = 0 is normal: x intersect y
1668 // polarity = 2: x intersect ~y == set-minus
1669 // polarity = 1: ~x intersect y
1670 // polarity = 3: ~x intersect ~y
1671 
retain(const UChar32 * other,int32_t otherLen,int8_t polarity)1672 void UnicodeSet::retain(const UChar32* other, int32_t otherLen, int8_t polarity) {
1673     if (isFrozen()) {
1674         return;
1675     }
1676     ensureBufferCapacity(len + otherLen);
1677     int32_t i = 0, j = 0, k = 0;
1678     UChar32 a = list[i++];
1679     UChar32 b = other[j++];
1680     // change from xor is that we have to check overlapping pairs
1681     // polarity bit 1 means a is second, bit 2 means b is.
1682     for (;;) {
1683         switch (polarity) {
1684           case 0: // both first; drop the smaller
1685             if (a < b) { // drop a
1686                 a = list[i++];
1687                 polarity ^= 1;
1688             } else if (b < a) { // drop b
1689                 b = other[j++];
1690                 polarity ^= 2;
1691             } else { // a == b, take one, drop other
1692                 if (a == UNICODESET_HIGH) goto loop_end;
1693                 buffer[k++] = a;
1694                 a = list[i++];
1695                 polarity ^= 1;
1696                 b = other[j++];
1697                 polarity ^= 2;
1698             }
1699             break;
1700           case 3: // both second; take lower if unequal
1701             if (a < b) { // take a
1702                 buffer[k++] = a;
1703                 a = list[i++];
1704                 polarity ^= 1;
1705             } else if (b < a) { // take b
1706                 buffer[k++] = b;
1707                 b = other[j++];
1708                 polarity ^= 2;
1709             } else { // a == b, take one, drop other
1710                 if (a == UNICODESET_HIGH) goto loop_end;
1711                 buffer[k++] = a;
1712                 a = list[i++];
1713                 polarity ^= 1;
1714                 b = other[j++];
1715                 polarity ^= 2;
1716             }
1717             break;
1718           case 1: // a second, b first;
1719             if (a < b) { // NO OVERLAP, drop a
1720                 a = list[i++];
1721                 polarity ^= 1;
1722             } else if (b < a) { // OVERLAP, take b
1723                 buffer[k++] = b;
1724                 b = other[j++];
1725                 polarity ^= 2;
1726             } else { // a == b, drop both!
1727                 if (a == UNICODESET_HIGH) goto loop_end;
1728                 a = list[i++];
1729                 polarity ^= 1;
1730                 b = other[j++];
1731                 polarity ^= 2;
1732             }
1733             break;
1734           case 2: // a first, b second; if a < b, overlap
1735             if (b < a) { // no overlap, drop b
1736                 b = other[j++];
1737                 polarity ^= 2;
1738             } else  if (a < b) { // OVERLAP, take a
1739                 buffer[k++] = a;
1740                 a = list[i++];
1741                 polarity ^= 1;
1742             } else { // a == b, drop both!
1743                 if (a == UNICODESET_HIGH) goto loop_end;
1744                 a = list[i++];
1745                 polarity ^= 1;
1746                 b = other[j++];
1747                 polarity ^= 2;
1748             }
1749             break;
1750         }
1751     }
1752  loop_end:
1753     buffer[k++] = UNICODESET_HIGH;    // terminate
1754     len = k;
1755     swapBuffers();
1756     releasePattern();
1757 }
1758 
1759 /**
1760  * Append the <code>toPattern()</code> representation of a
1761  * string to the given <code>StringBuffer</code>.
1762  */
_appendToPat(UnicodeString & buf,const UnicodeString & s,UBool escapeUnprintable)1763 void UnicodeSet::_appendToPat(UnicodeString& buf, const UnicodeString& s, UBool
1764 escapeUnprintable) {
1765     UChar32 cp;
1766     for (int32_t i = 0; i < s.length(); i += UTF_CHAR_LENGTH(cp)) {
1767         _appendToPat(buf, cp = s.char32At(i), escapeUnprintable);
1768     }
1769 }
1770 
1771 /**
1772  * Append the <code>toPattern()</code> representation of a
1773  * character to the given <code>StringBuffer</code>.
1774  */
_appendToPat(UnicodeString & buf,UChar32 c,UBool escapeUnprintable)1775 void UnicodeSet::_appendToPat(UnicodeString& buf, UChar32 c, UBool
1776 escapeUnprintable) {
1777     if (escapeUnprintable && ICU_Utility::isUnprintable(c)) {
1778         // Use hex escape notation (\uxxxx or \Uxxxxxxxx) for anything
1779         // unprintable
1780         if (ICU_Utility::escapeUnprintable(buf, c)) {
1781             return;
1782         }
1783     }
1784     // Okay to let ':' pass through
1785     switch (c) {
1786     case SET_OPEN:
1787     case SET_CLOSE:
1788     case HYPHEN:
1789     case COMPLEMENT:
1790     case INTERSECTION:
1791     case BACKSLASH:
1792     case OPEN_BRACE:
1793     case CLOSE_BRACE:
1794     case COLON:
1795     case SymbolTable::SYMBOL_REF:
1796         buf.append(BACKSLASH);
1797         break;
1798     default:
1799         // Escape whitespace
1800         if (uprv_isRuleWhiteSpace(c)) {
1801             buf.append(BACKSLASH);
1802         }
1803         break;
1804     }
1805     buf.append(c);
1806 }
1807 
1808 /**
1809  * Append a string representation of this set to result.  This will be
1810  * a cleaned version of the string passed to applyPattern(), if there
1811  * is one.  Otherwise it will be generated.
1812  */
_toPattern(UnicodeString & result,UBool escapeUnprintable) const1813 UnicodeString& UnicodeSet::_toPattern(UnicodeString& result,
1814                                       UBool escapeUnprintable) const
1815 {
1816     if (pat != NULL) {
1817         int32_t i;
1818         int32_t backslashCount = 0;
1819         for (i=0; i<patLen; ) {
1820             UChar32 c;
1821             U16_NEXT(pat, i, patLen, c);
1822             if (escapeUnprintable && ICU_Utility::isUnprintable(c)) {
1823                 // If the unprintable character is preceded by an odd
1824                 // number of backslashes, then it has been escaped.
1825                 // Before unescaping it, we delete the final
1826                 // backslash.
1827                 if ((backslashCount % 2) == 1) {
1828                     result.truncate(result.length() - 1);
1829                 }
1830                 ICU_Utility::escapeUnprintable(result, c);
1831                 backslashCount = 0;
1832             } else {
1833                 result.append(c);
1834                 if (c == BACKSLASH) {
1835                     ++backslashCount;
1836                 } else {
1837                     backslashCount = 0;
1838                 }
1839             }
1840         }
1841         return result;
1842     }
1843 
1844     return _generatePattern(result, escapeUnprintable);
1845 }
1846 
1847 /**
1848  * Returns a string representation of this set.  If the result of
1849  * calling this function is passed to a UnicodeSet constructor, it
1850  * will produce another set that is equal to this one.
1851  */
toPattern(UnicodeString & result,UBool escapeUnprintable) const1852 UnicodeString& UnicodeSet::toPattern(UnicodeString& result,
1853                                      UBool escapeUnprintable) const
1854 {
1855     result.truncate(0);
1856     return _toPattern(result, escapeUnprintable);
1857 }
1858 
1859 /**
1860  * Generate and append a string representation of this set to result.
1861  * This does not use this.pat, the cleaned up copy of the string
1862  * passed to applyPattern().
1863  */
_generatePattern(UnicodeString & result,UBool escapeUnprintable) const1864 UnicodeString& UnicodeSet::_generatePattern(UnicodeString& result,
1865                                             UBool escapeUnprintable) const
1866 {
1867     result.append(SET_OPEN);
1868 
1869 //  // Check against the predefined categories.  We implicitly build
1870 //  // up ALL category sets the first time toPattern() is called.
1871 //  for (int8_t cat=0; cat<Unicode::GENERAL_TYPES_COUNT; ++cat) {
1872 //      if (*this == getCategorySet(cat)) {
1873 //          result.append(COLON);
1874 //          result.append(CATEGORY_NAMES, cat*2, 2);
1875 //          return result.append(CATEGORY_CLOSE);
1876 //      }
1877 //  }
1878 
1879     int32_t count = getRangeCount();
1880 
1881     // If the set contains at least 2 intervals and includes both
1882     // MIN_VALUE and MAX_VALUE, then the inverse representation will
1883     // be more economical.
1884     if (count > 1 &&
1885         getRangeStart(0) == MIN_VALUE &&
1886         getRangeEnd(count-1) == MAX_VALUE) {
1887 
1888         // Emit the inverse
1889         result.append(COMPLEMENT);
1890 
1891         for (int32_t i = 1; i < count; ++i) {
1892             UChar32 start = getRangeEnd(i-1)+1;
1893             UChar32 end = getRangeStart(i)-1;
1894             _appendToPat(result, start, escapeUnprintable);
1895             if (start != end) {
1896                 if ((start+1) != end) {
1897                     result.append(HYPHEN);
1898                 }
1899                 _appendToPat(result, end, escapeUnprintable);
1900             }
1901         }
1902     }
1903 
1904     // Default; emit the ranges as pairs
1905     else {
1906         for (int32_t i = 0; i < count; ++i) {
1907             UChar32 start = getRangeStart(i);
1908             UChar32 end = getRangeEnd(i);
1909             _appendToPat(result, start, escapeUnprintable);
1910             if (start != end) {
1911                 if ((start+1) != end) {
1912                     result.append(HYPHEN);
1913                 }
1914                 _appendToPat(result, end, escapeUnprintable);
1915             }
1916         }
1917     }
1918 
1919     for (int32_t i = 0; i<strings->size(); ++i) {
1920         result.append(OPEN_BRACE);
1921         _appendToPat(result,
1922                      *(const UnicodeString*) strings->elementAt(i),
1923                      escapeUnprintable);
1924         result.append(CLOSE_BRACE);
1925     }
1926     return result.append(SET_CLOSE);
1927 }
1928 
1929 /**
1930 * Release existing cached pattern
1931 */
releasePattern()1932 void UnicodeSet::releasePattern() {
1933     if (pat) {
1934         uprv_free(pat);
1935         pat = NULL;
1936         patLen = 0;
1937     }
1938 }
1939 
1940 /**
1941 * Set the new pattern to cache.
1942 */
setPattern(const UnicodeString & newPat)1943 void UnicodeSet::setPattern(const UnicodeString& newPat) {
1944     releasePattern();
1945     int32_t newPatLen = newPat.length();
1946     pat = (UChar *)uprv_malloc((newPatLen + 1) * sizeof(UChar));
1947     if (pat) {
1948         patLen = newPatLen;
1949         newPat.extractBetween(0, patLen, pat);
1950         pat[patLen] = 0;
1951     }
1952     // else we don't care if malloc failed. This was just a nice cache.
1953     // We can regenerate an equivalent pattern later when requested.
1954 }
1955 
freeze()1956 UnicodeFunctor *UnicodeSet::freeze() {
1957     if(!isFrozen()) {
1958         // Do most of what compact() does before freezing because
1959         // compact() will not work when the set is frozen.
1960         // Small modification: Don't shrink if the savings would be tiny (<=GROW_EXTRA).
1961 
1962         // Delete buffer first to defragment memory less.
1963         if (buffer != NULL) {
1964             uprv_free(buffer);
1965             buffer = NULL;
1966         }
1967         if (capacity > (len + GROW_EXTRA)) {
1968             // Make the capacity equal to len or 1.
1969             // We don't want to realloc of 0 size.
1970             capacity = len + (len == 0);
1971             list = (UChar32*) uprv_realloc(list, sizeof(UChar32) * capacity);
1972         }
1973 
1974         // Optimize contains() and span() and similar functions.
1975         if (!strings->isEmpty()) {
1976             stringSpan = new UnicodeSetStringSpan(*this, *strings, UnicodeSetStringSpan::ALL);
1977             if (stringSpan != NULL && !stringSpan->needsStringSpanUTF16()) {
1978                 // All strings are irrelevant for span() etc. because
1979                 // all of each string's code points are contained in this set.
1980                 // Do not check needsStringSpanUTF8() because UTF-8 has at most as
1981                 // many relevant strings as UTF-16.
1982                 // (Thus needsStringSpanUTF8() implies needsStringSpanUTF16().)
1983                 delete stringSpan;
1984                 stringSpan = NULL;
1985             }
1986         }
1987         if (stringSpan == NULL) {
1988             // No span-relevant strings: Optimize for code point spans.
1989             bmpSet=new BMPSet(list, len);
1990         }
1991     }
1992     return this;
1993 }
1994 
span(const UChar * s,int32_t length,USetSpanCondition spanCondition) const1995 int32_t UnicodeSet::span(const UChar *s, int32_t length, USetSpanCondition spanCondition) const {
1996     if(length>0 && bmpSet!=NULL) {
1997         return (int32_t)(bmpSet->span(s, s+length, spanCondition)-s);
1998     }
1999     if(length<0) {
2000         length=u_strlen(s);
2001     }
2002     if(length==0) {
2003         return 0;
2004     }
2005     if(stringSpan!=NULL) {
2006         return stringSpan->span(s, length, spanCondition);
2007     } else if(!strings->isEmpty()) {
2008         uint32_t which= spanCondition==USET_SPAN_NOT_CONTAINED ?
2009                             UnicodeSetStringSpan::FWD_UTF16_NOT_CONTAINED :
2010                             UnicodeSetStringSpan::FWD_UTF16_CONTAINED;
2011         UnicodeSetStringSpan strSpan(*this, *strings, which);
2012         if(strSpan.needsStringSpanUTF16()) {
2013             return strSpan.span(s, length, spanCondition);
2014         }
2015     }
2016 
2017     if(spanCondition!=USET_SPAN_NOT_CONTAINED) {
2018         spanCondition=USET_SPAN_CONTAINED;  // Pin to 0/1 values.
2019     }
2020 
2021     UChar32 c;
2022     int32_t start=0, prev=0;
2023     do {
2024         U16_NEXT(s, start, length, c);
2025         if(spanCondition!=contains(c)) {
2026             break;
2027         }
2028     } while((prev=start)<length);
2029     return prev;
2030 }
2031 
spanBack(const UChar * s,int32_t length,USetSpanCondition spanCondition) const2032 int32_t UnicodeSet::spanBack(const UChar *s, int32_t length, USetSpanCondition spanCondition) const {
2033     if(length>0 && bmpSet!=NULL) {
2034         return (int32_t)(bmpSet->spanBack(s, s+length, spanCondition)-s);
2035     }
2036     if(length<0) {
2037         length=u_strlen(s);
2038     }
2039     if(length==0) {
2040         return 0;
2041     }
2042     if(stringSpan!=NULL) {
2043         return stringSpan->spanBack(s, length, spanCondition);
2044     } else if(!strings->isEmpty()) {
2045         uint32_t which= spanCondition==USET_SPAN_NOT_CONTAINED ?
2046                             UnicodeSetStringSpan::BACK_UTF16_NOT_CONTAINED :
2047                             UnicodeSetStringSpan::BACK_UTF16_CONTAINED;
2048         UnicodeSetStringSpan strSpan(*this, *strings, which);
2049         if(strSpan.needsStringSpanUTF16()) {
2050             return strSpan.spanBack(s, length, spanCondition);
2051         }
2052     }
2053 
2054     if(spanCondition!=USET_SPAN_NOT_CONTAINED) {
2055         spanCondition=USET_SPAN_CONTAINED;  // Pin to 0/1 values.
2056     }
2057 
2058     UChar32 c;
2059     int32_t prev=length;
2060     do {
2061         U16_PREV(s, 0, length, c);
2062         if(spanCondition!=contains(c)) {
2063             break;
2064         }
2065     } while((prev=length)>0);
2066     return prev;
2067 }
2068 
spanUTF8(const char * s,int32_t length,USetSpanCondition spanCondition) const2069 int32_t UnicodeSet::spanUTF8(const char *s, int32_t length, USetSpanCondition spanCondition) const {
2070     if(length>0 && bmpSet!=NULL) {
2071         const uint8_t *s0=(const uint8_t *)s;
2072         return (int32_t)(bmpSet->spanUTF8(s0, length, spanCondition)-s0);
2073     }
2074     if(length<0) {
2075         length=uprv_strlen(s);
2076     }
2077     if(length==0) {
2078         return 0;
2079     }
2080     if(stringSpan!=NULL) {
2081         return stringSpan->spanUTF8((const uint8_t *)s, length, spanCondition);
2082     } else if(!strings->isEmpty()) {
2083         uint32_t which= spanCondition==USET_SPAN_NOT_CONTAINED ?
2084                             UnicodeSetStringSpan::FWD_UTF8_NOT_CONTAINED :
2085                             UnicodeSetStringSpan::FWD_UTF8_CONTAINED;
2086         UnicodeSetStringSpan strSpan(*this, *strings, which);
2087         if(strSpan.needsStringSpanUTF8()) {
2088             return strSpan.spanUTF8((const uint8_t *)s, length, spanCondition);
2089         }
2090     }
2091 
2092     if(spanCondition!=USET_SPAN_NOT_CONTAINED) {
2093         spanCondition=USET_SPAN_CONTAINED;  // Pin to 0/1 values.
2094     }
2095 
2096     UChar32 c;
2097     int32_t start=0, prev=0;
2098     do {
2099         U8_NEXT(s, start, length, c);
2100         if(c<0) {
2101             c=0xfffd;
2102         }
2103         if(spanCondition!=contains(c)) {
2104             break;
2105         }
2106     } while((prev=start)<length);
2107     return prev;
2108 }
2109 
spanBackUTF8(const char * s,int32_t length,USetSpanCondition spanCondition) const2110 int32_t UnicodeSet::spanBackUTF8(const char *s, int32_t length, USetSpanCondition spanCondition) const {
2111     if(length>0 && bmpSet!=NULL) {
2112         const uint8_t *s0=(const uint8_t *)s;
2113         return bmpSet->spanBackUTF8(s0, length, spanCondition);
2114     }
2115     if(length<0) {
2116         length=uprv_strlen(s);
2117     }
2118     if(length==0) {
2119         return 0;
2120     }
2121     if(stringSpan!=NULL) {
2122         return stringSpan->spanBackUTF8((const uint8_t *)s, length, spanCondition);
2123     } else if(!strings->isEmpty()) {
2124         uint32_t which= spanCondition==USET_SPAN_NOT_CONTAINED ?
2125                             UnicodeSetStringSpan::BACK_UTF8_NOT_CONTAINED :
2126                             UnicodeSetStringSpan::BACK_UTF8_CONTAINED;
2127         UnicodeSetStringSpan strSpan(*this, *strings, which);
2128         if(strSpan.needsStringSpanUTF8()) {
2129             return strSpan.spanBackUTF8((const uint8_t *)s, length, spanCondition);
2130         }
2131     }
2132 
2133     if(spanCondition!=USET_SPAN_NOT_CONTAINED) {
2134         spanCondition=USET_SPAN_CONTAINED;  // Pin to 0/1 values.
2135     }
2136 
2137     UChar32 c;
2138     int32_t prev=length;
2139     do {
2140         U8_PREV(s, 0, length, c);
2141         if(c<0) {
2142             c=0xfffd;
2143         }
2144         if(spanCondition!=contains(c)) {
2145             break;
2146         }
2147     } while((prev=length)>0);
2148     return prev;
2149 }
2150 
2151 U_NAMESPACE_END
2152