X-Git-Url: http://gitweb.fperrin.net/?a=blobdiff_plain;f=jars%2Ficu4j-4_2_1-src%2Fsrc%2Fcom%2Fibm%2Ficu%2Fdev%2Ftest%2Futil%2FCollectionUtilities.java;h=e58fcfa8324145d809e597bf6e0092709fb7d4fb;hb=127973afabe0c34015667c599d68bf9453d85652;hp=5b4e765c5e2f5e276a2b94dfdf21bc436ea4e4eb;hpb=92dfc8b7d39cbc2e55f3c547c0c265bc7ae3af86;p=Dictionary.git diff --git a/jars/icu4j-4_2_1-src/src/com/ibm/icu/dev/test/util/CollectionUtilities.java b/jars/icu4j-4_2_1-src/src/com/ibm/icu/dev/test/util/CollectionUtilities.java old mode 100755 new mode 100644 index 5b4e765..e58fcfa --- a/jars/icu4j-4_2_1-src/src/com/ibm/icu/dev/test/util/CollectionUtilities.java +++ b/jars/icu4j-4_2_1-src/src/com/ibm/icu/dev/test/util/CollectionUtilities.java @@ -1,498 +1,498 @@ -//##header -/* - ******************************************************************************* - * Copyright (C) 1996-2009, International Business Machines Corporation and * - * others. All Rights Reserved. * - ******************************************************************************* - */ -package com.ibm.icu.dev.test.util; - -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.SortedSet; - -//#if defined(FOUNDATION10) || defined(J2SE13) -//#else -import java.util.regex.Matcher; -//#endif - -import com.ibm.icu.text.Transliterator; -import com.ibm.icu.text.UTF16; -import com.ibm.icu.text.UnicodeSet; -import com.ibm.icu.text.UnicodeSetIterator; - -/** - * Utilities that ought to be on collections, but aren't - */ -public final class CollectionUtilities { - - public static String join(Object[] array, String separator) { - StringBuffer result = new StringBuffer(); - for (int i = 0; i < array.length; ++i) { - if (i != 0) result.append(separator); - result.append(array[i]); - } - return result.toString(); - } - - public static String join(Collection collection, String separator) { - StringBuffer result = new StringBuffer(); - boolean first = true; - for (Iterator it = collection.iterator(); it.hasNext();) { - if (first) first = false; - else result.append(separator); - result.append(it.next()); - } - return result.toString(); - } - - /** - * Utility like Arrays.asList() - */ - public static Map asMap(Object[][] source, Map target, boolean reverse) { - int from = 0, to = 1; - if (reverse) { - from = 1; to = 0; - } - for (int i = 0; i < source.length; ++i) { - target.put(source[i][from], source[i][to]); - } - return target; - } - - public static Collection addAll(Iterator source, Collection target) { - while (source.hasNext()) { - target.add(source.next()); - } - return target; // for chaining - } - - public static int size(Iterator source) { - int result = 0; - while (source.hasNext()) { - source.next(); - ++result; - } - return result; - } - - - public static Map asMap(Object[][] source) { - return asMap(source, new HashMap(), false); - } - - /** - * Utility that ought to be on Map - */ - public static Map removeAll(Map m, Collection itemsToRemove) { - for (Iterator it = itemsToRemove.iterator(); it.hasNext();) { - Object item = it.next(); - m.remove(item); - } - return m; - } - - public Object getFirst(Collection c) { - Iterator it = c.iterator(); - if (!it.hasNext()) return null; - return it.next(); - } - - public static Object getBest(Collection c, Comparator comp, int direction) { - Iterator it = c.iterator(); - if (!it.hasNext()) return null; - Object bestSoFar = it.next(); - if (direction < 0) { - while (it.hasNext()) { - Object item = it.next(); - int compValue = comp.compare(item, bestSoFar); - if (compValue < 0) { - bestSoFar = item; - } - } - } else { - while (it.hasNext()) { - Object item = it.next(); - int compValue = comp.compare(item, bestSoFar); - if (compValue > 0) { - bestSoFar = item; - } - } - } - return bestSoFar; - } - - public interface ObjectMatcher { - /** - * Must handle null, never throw exception - */ - boolean matches(Object o); - } - - public static class InverseMatcher implements ObjectMatcher { - ObjectMatcher other; - public ObjectMatcher set(ObjectMatcher toInverse) { - other = toInverse; - return this; - } - public boolean matches(Object value) { - return !other.matches(value); - } - } - - public static Collection removeAll(Collection c, ObjectMatcher f) { - for (Iterator it = c.iterator(); it.hasNext();) { - Object item = it.next(); - if (f.matches(item)) it.remove(); - } - return c; - } - - public static Collection retainAll(Collection c, ObjectMatcher f) { - for (Iterator it = c.iterator(); it.hasNext();) { - Object item = it.next(); - if (!f.matches(item)) it.remove(); - } - return c; - } - - public static boolean containsSome(Collection a, Collection b) { - // fast paths - if (a.size() == 0 || b.size() == 0) return false; - if (a == b) return true; // must test after size test. - - if (a instanceof SortedSet && b instanceof SortedSet) { - SortedSet aa = (SortedSet) a; - SortedSet bb = (SortedSet) b; - aa.containsAll(null); - Comparator bbc = bb.comparator(); - Comparator aac = aa.comparator(); - if (bbc == null) { - if (aac == null) { - Iterator ai = aa.iterator(); - Iterator bi = bb.iterator(); - Comparable ao = (Comparable) ai.next(); // these are ok, since the sizes are != 0 - Comparable bo = (Comparable) bi.next(); - while (true) { - int rel = ao.compareTo(bo); - if (rel < 0) { - if (!ai.hasNext()) return false; - ao = (Comparable) ai.next(); - } else if (rel > 0) { - if (!bi.hasNext()) return false; - bo = (Comparable) bi.next(); - } else { - return true; - } - } - } - } else if (bbc.equals(a)) { - Iterator ai = aa.iterator(); - Iterator bi = bb.iterator(); - Object ao = ai.next(); // these are ok, since the sizes are != 0 - Object bo = bi.next(); - while (true) { - int rel = aac.compare(ao, bo); - if (rel < 0) { - if (!ai.hasNext()) return false; - ao = ai.next(); - } else if (rel > 0) { - if (!bi.hasNext()) return false; - bo = bi.next(); - } else { - return true; - } - } - } - } - for (Iterator it = a.iterator(); it.hasNext();) { - if (b.contains(it.next())) return true; - } - return false; - } - - public static boolean containsAll(Collection a, Collection b) { - // fast paths - if (a == b) return true; - if (b.size() == 0) return true; - if (a.size() == 0) return false; - - if (a instanceof SortedSet && b instanceof SortedSet) { - SortedSet aa = (SortedSet) a; - SortedSet bb = (SortedSet) b; - Comparator bbc = bb.comparator(); - Comparator aac = aa.comparator(); - if (bbc == null) { - if (aac == null) { - Iterator ai = aa.iterator(); - Iterator bi = bb.iterator(); - Comparable ao = (Comparable) ai.next(); // these are ok, since the sizes are != 0 - Comparable bo = (Comparable) bi.next(); - while (true) { - int rel = ao.compareTo(bo); - if (rel == 0) { - if (!bi.hasNext()) return true; - if (!ai.hasNext()) return false; - bo = (Comparable) bi.next(); - ao = (Comparable) ai.next(); - } else if (rel < 0) { - if (!ai.hasNext()) return false; - ao = (Comparable) ai.next(); - } else { - return false; - } - } - } - } else if (bbc.equals(a)) { - Iterator ai = aa.iterator(); - Iterator bi = bb.iterator(); - Object ao = ai.next(); // these are ok, since the sizes are != 0 - Object bo = bi.next(); - while (true) { - int rel = aac.compare(ao, bo); - if (rel == 0) { - if (!bi.hasNext()) return true; - if (!ai.hasNext()) return false; - bo = bi.next(); - ao = ai.next(); - } else if (rel < 0) { - if (!ai.hasNext()) return false; - ao = ai.next(); - } else { - return false; - } - } - } - } - return a.containsAll(b); - } - - public static boolean containsNone(Collection a, Collection b) { - return !containsSome(a, b); - } - - /** - * Used for results of getContainmentRelation - */ - public static final int - ALL_EMPTY = 0, - NOT_A_SUPERSET_B = 1, - NOT_A_DISJOINT_B = 2, - NOT_A_SUBSET_B = 4, - NOT_A_EQUALS_B = NOT_A_SUBSET_B | NOT_A_SUPERSET_B, - A_PROPER_SUBSET_OF_B = NOT_A_DISJOINT_B | NOT_A_SUPERSET_B, - A_PROPER_SUPERSET_B = NOT_A_SUBSET_B | NOT_A_DISJOINT_B, - A_PROPER_OVERLAPS_B = NOT_A_SUBSET_B | NOT_A_DISJOINT_B | NOT_A_SUPERSET_B; - - /** - * Assesses all the possible containment relations between collections A and B with one call.
- * Returns an int with bits set, according to a "Venn Diagram" view of A vs B.
- * NOT_A_SUPERSET_B: a - b != {}
- * NOT_A_DISJOINT_B: a * b != {} // * is intersects
- * NOT_A_SUBSET_B: b - a != {}
- * Thus the bits can be used to get the following relations:
- * for A_SUPERSET_B, use (x & CollectionUtilities.NOT_A_SUPERSET_B) == 0
- * for A_SUBSET_B, use (x & CollectionUtilities.NOT_A_SUBSET_B) == 0
- * for A_EQUALS_B, use (x & CollectionUtilities.NOT_A_EQUALS_B) == 0
- * for A_DISJOINT_B, use (x & CollectionUtilities.NOT_A_DISJOINT_B) == 0
- * for A_OVERLAPS_B, use (x & CollectionUtilities.NOT_A_DISJOINT_B) != 0
- */ - public static int getContainmentRelation(Collection a, Collection b) { - if (a.size() == 0) { - return (b.size() == 0) ? ALL_EMPTY : NOT_A_SUPERSET_B; - } else if (b.size() == 0) { - return NOT_A_SUBSET_B; - } - int result = 0; - // WARNING: one might think that the following can be short-circuited, by looking at - // the sizes of a and b. However, this would fail in general, where a different comparator is being - // used in the two collections. Unfortunately, there is no failsafe way to test for that. - for (Iterator it = a.iterator(); result != 6 && it.hasNext();) { - result |= (b.contains(it.next())) ? NOT_A_DISJOINT_B : NOT_A_SUBSET_B; - } - for (Iterator it = b.iterator(); (result & 3) != 3 && it.hasNext();) { - result |= (a.contains(it.next())) ? NOT_A_DISJOINT_B : NOT_A_SUPERSET_B; - } - return result; - } - - public static String remove(String source, UnicodeSet removals) { - StringBuffer result = new StringBuffer(); - int cp; - for (int i = 0; i < source.length(); i += UTF16.getCharCount(cp)) { - cp = UTF16.charAt(source, i); - if (!removals.contains(cp)) UTF16.append(result, cp); - } - return result.toString(); - } - -//#if defined(FOUNDATION10) || defined(J2SE13) -//#else - /** - * Does one string contain another, starting at a specific offset? - * @param text - * @param offset - * @param other - * @return - */ - public static int matchesAt(CharSequence text, int offset, CharSequence other) { - int len = other.length(); - int i = 0; - int j = offset; - for (; i < len; ++i, ++j) { - char pc = other.charAt(i); - char tc = text.charAt(j); - if (pc != tc) return -1; - } - return i; - } - - /** - * Returns the ending offset found by matching characters with testSet, until a position is found that doen't match - * @param string - * @param offset - * @param testSet - * @return - */ - public int span(CharSequence string, int offset, UnicodeSet testSet) { - while (true) { - int newOffset = testSet.matchesAt(string, offset); - if (newOffset < 0) return offset; - } - } - - /** - * Returns the ending offset found by matching characters with testSet, until a position is found that does match - * @param string - * @param offset - * @param testSet - * @return - */ - public int spanNot(CharSequence string, int offset, UnicodeSet testSet) { - while (true) { - int newOffset = testSet.matchesAt(string, offset); - if (newOffset >= 0) return offset; - ++offset; // try next character position - // we don't have to worry about surrogates for this. - } - } -//#endif - - public static String prettyPrint(UnicodeSet uset, boolean compressRanges, UnicodeSet toQuote, Transliterator quoter, - Comparator ordering, Comparator spaceComparator) { - PrettyPrinter pp = new PrettyPrinter().setCompressRanges(compressRanges); - if (toQuote != null) pp.setToQuote(toQuote); - if (ordering != null) pp.setOrdering(ordering); - if (spaceComparator != null) pp.setSpaceComparator(spaceComparator); - return pp.toPattern(uset); - } - - public static class MultiComparator implements Comparator { - private Comparator[] comparators; - - public MultiComparator (Comparator[] comparators) { - this.comparators = comparators; - } - - /* Lexigraphic compare. Returns the first difference - * @return zero if equal. Otherwise +/- (i+1) - * where i is the index of the first comparator finding a difference - * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) - */ - public int compare(Object arg0, Object arg1) { - for (int i = 0; i < comparators.length; ++i) { - int result = comparators[i].compare(arg0, arg1); - if (result == 0) continue; - if (result > 0) return i+1; - return -(i+1); - } - return 0; - } - } - - /** - * Modifies Unicode set to flatten the strings. Eg [abc{da}] => [abcd] - * Returns the set for chaining. - * @param exemplar1 - * @return - */ - public static UnicodeSet flatten(UnicodeSet exemplar1) { - UnicodeSet result = new UnicodeSet(); - boolean gotString = false; - for (UnicodeSetIterator it = new UnicodeSetIterator(exemplar1); it.nextRange();) { - if (it.codepoint == UnicodeSetIterator.IS_STRING) { - result.addAll(it.string); - gotString = true; - } else { - result.add(it.codepoint, it.codepointEnd); - } - } - if (gotString) exemplar1.set(result); - return exemplar1; - } - - /** - * For producing filtered iterators - */ - public static abstract class FilteredIterator implements Iterator { - private Iterator baseIterator; - private static final Object EMPTY = new Object(); - private static final Object DONE = new Object(); - private Object nextObject = EMPTY; - public FilteredIterator set(Iterator baseIterator) { - this.baseIterator = baseIterator; - return this; - } - public void remove() { - throw new UnsupportedOperationException("Doesn't support removal"); - } - public Object next() { - Object result = nextObject; - nextObject = EMPTY; - return result; - } - public boolean hasNext() { - if (nextObject == DONE) return false; - if (nextObject != EMPTY) return true; - while (baseIterator.hasNext()) { - nextObject = baseIterator.next(); - if (isIncluded(nextObject)) { - return true; - } - } - nextObject = DONE; - return false; - } - abstract public boolean isIncluded(Object item); - } - - public static class PrefixIterator extends FilteredIterator { - private String prefix; - public PrefixIterator set(Iterator baseIterator, String prefix) { - super.set(baseIterator); - this.prefix = prefix; - return this; - } - public boolean isIncluded(Object item) { - return ((String)item).startsWith(prefix); - } - } - -//#if defined(FOUNDATION10) || defined(J2SE13) -//#else - public static class RegexIterator extends FilteredIterator { - private Matcher matcher; - public RegexIterator set(Iterator baseIterator, Matcher matcher) { - super.set(baseIterator); - this.matcher = matcher; - return this; - } - public boolean isIncluded(Object item) { - return matcher.reset((String)item).matches(); - } - } -//#endif -} +//##header J2SE15 +/* + ******************************************************************************* + * Copyright (C) 1996-2009, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ +package com.ibm.icu.dev.test.util; + +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.SortedSet; + +//#if defined(FOUNDATION10) || defined(J2SE13) +//#else +import java.util.regex.Matcher; +//#endif + +import com.ibm.icu.text.Transliterator; +import com.ibm.icu.text.UTF16; +import com.ibm.icu.text.UnicodeSet; +import com.ibm.icu.text.UnicodeSetIterator; + +/** + * Utilities that ought to be on collections, but aren't + */ +public final class CollectionUtilities { + + public static String join(Object[] array, String separator) { + StringBuffer result = new StringBuffer(); + for (int i = 0; i < array.length; ++i) { + if (i != 0) result.append(separator); + result.append(array[i]); + } + return result.toString(); + } + + public static String join(Collection collection, String separator) { + StringBuffer result = new StringBuffer(); + boolean first = true; + for (Iterator it = collection.iterator(); it.hasNext();) { + if (first) first = false; + else result.append(separator); + result.append(it.next()); + } + return result.toString(); + } + + /** + * Utility like Arrays.asList() + */ + public static Map asMap(Object[][] source, Map target, boolean reverse) { + int from = 0, to = 1; + if (reverse) { + from = 1; to = 0; + } + for (int i = 0; i < source.length; ++i) { + target.put(source[i][from], source[i][to]); + } + return target; + } + + public static Collection addAll(Iterator source, Collection target) { + while (source.hasNext()) { + target.add(source.next()); + } + return target; // for chaining + } + + public static int size(Iterator source) { + int result = 0; + while (source.hasNext()) { + source.next(); + ++result; + } + return result; + } + + + public static Map asMap(Object[][] source) { + return asMap(source, new HashMap(), false); + } + + /** + * Utility that ought to be on Map + */ + public static Map removeAll(Map m, Collection itemsToRemove) { + for (Iterator it = itemsToRemove.iterator(); it.hasNext();) { + Object item = it.next(); + m.remove(item); + } + return m; + } + + public Object getFirst(Collection c) { + Iterator it = c.iterator(); + if (!it.hasNext()) return null; + return it.next(); + } + + public static Object getBest(Collection c, Comparator comp, int direction) { + Iterator it = c.iterator(); + if (!it.hasNext()) return null; + Object bestSoFar = it.next(); + if (direction < 0) { + while (it.hasNext()) { + Object item = it.next(); + int compValue = comp.compare(item, bestSoFar); + if (compValue < 0) { + bestSoFar = item; + } + } + } else { + while (it.hasNext()) { + Object item = it.next(); + int compValue = comp.compare(item, bestSoFar); + if (compValue > 0) { + bestSoFar = item; + } + } + } + return bestSoFar; + } + + public interface ObjectMatcher { + /** + * Must handle null, never throw exception + */ + boolean matches(Object o); + } + + public static class InverseMatcher implements ObjectMatcher { + ObjectMatcher other; + public ObjectMatcher set(ObjectMatcher toInverse) { + other = toInverse; + return this; + } + public boolean matches(Object value) { + return !other.matches(value); + } + } + + public static Collection removeAll(Collection c, ObjectMatcher f) { + for (Iterator it = c.iterator(); it.hasNext();) { + Object item = it.next(); + if (f.matches(item)) it.remove(); + } + return c; + } + + public static Collection retainAll(Collection c, ObjectMatcher f) { + for (Iterator it = c.iterator(); it.hasNext();) { + Object item = it.next(); + if (!f.matches(item)) it.remove(); + } + return c; + } + + public static boolean containsSome(Collection a, Collection b) { + // fast paths + if (a.size() == 0 || b.size() == 0) return false; + if (a == b) return true; // must test after size test. + + if (a instanceof SortedSet && b instanceof SortedSet) { + SortedSet aa = (SortedSet) a; + SortedSet bb = (SortedSet) b; + aa.containsAll(null); + Comparator bbc = bb.comparator(); + Comparator aac = aa.comparator(); + if (bbc == null) { + if (aac == null) { + Iterator ai = aa.iterator(); + Iterator bi = bb.iterator(); + Comparable ao = (Comparable) ai.next(); // these are ok, since the sizes are != 0 + Comparable bo = (Comparable) bi.next(); + while (true) { + int rel = ao.compareTo(bo); + if (rel < 0) { + if (!ai.hasNext()) return false; + ao = (Comparable) ai.next(); + } else if (rel > 0) { + if (!bi.hasNext()) return false; + bo = (Comparable) bi.next(); + } else { + return true; + } + } + } + } else if (bbc.equals(a)) { + Iterator ai = aa.iterator(); + Iterator bi = bb.iterator(); + Object ao = ai.next(); // these are ok, since the sizes are != 0 + Object bo = bi.next(); + while (true) { + int rel = aac.compare(ao, bo); + if (rel < 0) { + if (!ai.hasNext()) return false; + ao = ai.next(); + } else if (rel > 0) { + if (!bi.hasNext()) return false; + bo = bi.next(); + } else { + return true; + } + } + } + } + for (Iterator it = a.iterator(); it.hasNext();) { + if (b.contains(it.next())) return true; + } + return false; + } + + public static boolean containsAll(Collection a, Collection b) { + // fast paths + if (a == b) return true; + if (b.size() == 0) return true; + if (a.size() == 0) return false; + + if (a instanceof SortedSet && b instanceof SortedSet) { + SortedSet aa = (SortedSet) a; + SortedSet bb = (SortedSet) b; + Comparator bbc = bb.comparator(); + Comparator aac = aa.comparator(); + if (bbc == null) { + if (aac == null) { + Iterator ai = aa.iterator(); + Iterator bi = bb.iterator(); + Comparable ao = (Comparable) ai.next(); // these are ok, since the sizes are != 0 + Comparable bo = (Comparable) bi.next(); + while (true) { + int rel = ao.compareTo(bo); + if (rel == 0) { + if (!bi.hasNext()) return true; + if (!ai.hasNext()) return false; + bo = (Comparable) bi.next(); + ao = (Comparable) ai.next(); + } else if (rel < 0) { + if (!ai.hasNext()) return false; + ao = (Comparable) ai.next(); + } else { + return false; + } + } + } + } else if (bbc.equals(a)) { + Iterator ai = aa.iterator(); + Iterator bi = bb.iterator(); + Object ao = ai.next(); // these are ok, since the sizes are != 0 + Object bo = bi.next(); + while (true) { + int rel = aac.compare(ao, bo); + if (rel == 0) { + if (!bi.hasNext()) return true; + if (!ai.hasNext()) return false; + bo = bi.next(); + ao = ai.next(); + } else if (rel < 0) { + if (!ai.hasNext()) return false; + ao = ai.next(); + } else { + return false; + } + } + } + } + return a.containsAll(b); + } + + public static boolean containsNone(Collection a, Collection b) { + return !containsSome(a, b); + } + + /** + * Used for results of getContainmentRelation + */ + public static final int + ALL_EMPTY = 0, + NOT_A_SUPERSET_B = 1, + NOT_A_DISJOINT_B = 2, + NOT_A_SUBSET_B = 4, + NOT_A_EQUALS_B = NOT_A_SUBSET_B | NOT_A_SUPERSET_B, + A_PROPER_SUBSET_OF_B = NOT_A_DISJOINT_B | NOT_A_SUPERSET_B, + A_PROPER_SUPERSET_B = NOT_A_SUBSET_B | NOT_A_DISJOINT_B, + A_PROPER_OVERLAPS_B = NOT_A_SUBSET_B | NOT_A_DISJOINT_B | NOT_A_SUPERSET_B; + + /** + * Assesses all the possible containment relations between collections A and B with one call.
+ * Returns an int with bits set, according to a "Venn Diagram" view of A vs B.
+ * NOT_A_SUPERSET_B: a - b != {}
+ * NOT_A_DISJOINT_B: a * b != {} // * is intersects
+ * NOT_A_SUBSET_B: b - a != {}
+ * Thus the bits can be used to get the following relations:
+ * for A_SUPERSET_B, use (x & CollectionUtilities.NOT_A_SUPERSET_B) == 0
+ * for A_SUBSET_B, use (x & CollectionUtilities.NOT_A_SUBSET_B) == 0
+ * for A_EQUALS_B, use (x & CollectionUtilities.NOT_A_EQUALS_B) == 0
+ * for A_DISJOINT_B, use (x & CollectionUtilities.NOT_A_DISJOINT_B) == 0
+ * for A_OVERLAPS_B, use (x & CollectionUtilities.NOT_A_DISJOINT_B) != 0
+ */ + public static int getContainmentRelation(Collection a, Collection b) { + if (a.size() == 0) { + return (b.size() == 0) ? ALL_EMPTY : NOT_A_SUPERSET_B; + } else if (b.size() == 0) { + return NOT_A_SUBSET_B; + } + int result = 0; + // WARNING: one might think that the following can be short-circuited, by looking at + // the sizes of a and b. However, this would fail in general, where a different comparator is being + // used in the two collections. Unfortunately, there is no failsafe way to test for that. + for (Iterator it = a.iterator(); result != 6 && it.hasNext();) { + result |= (b.contains(it.next())) ? NOT_A_DISJOINT_B : NOT_A_SUBSET_B; + } + for (Iterator it = b.iterator(); (result & 3) != 3 && it.hasNext();) { + result |= (a.contains(it.next())) ? NOT_A_DISJOINT_B : NOT_A_SUPERSET_B; + } + return result; + } + + public static String remove(String source, UnicodeSet removals) { + StringBuffer result = new StringBuffer(); + int cp; + for (int i = 0; i < source.length(); i += UTF16.getCharCount(cp)) { + cp = UTF16.charAt(source, i); + if (!removals.contains(cp)) UTF16.append(result, cp); + } + return result.toString(); + } + +//#if defined(FOUNDATION10) || defined(J2SE13) +//#else + /** + * Does one string contain another, starting at a specific offset? + * @param text + * @param offset + * @param other + * @return + */ + public static int matchesAt(CharSequence text, int offset, CharSequence other) { + int len = other.length(); + int i = 0; + int j = offset; + for (; i < len; ++i, ++j) { + char pc = other.charAt(i); + char tc = text.charAt(j); + if (pc != tc) return -1; + } + return i; + } + + /** + * Returns the ending offset found by matching characters with testSet, until a position is found that doen't match + * @param string + * @param offset + * @param testSet + * @return + */ + public int span(CharSequence string, int offset, UnicodeSet testSet) { + while (true) { + int newOffset = testSet.matchesAt(string, offset); + if (newOffset < 0) return offset; + } + } + + /** + * Returns the ending offset found by matching characters with testSet, until a position is found that does match + * @param string + * @param offset + * @param testSet + * @return + */ + public int spanNot(CharSequence string, int offset, UnicodeSet testSet) { + while (true) { + int newOffset = testSet.matchesAt(string, offset); + if (newOffset >= 0) return offset; + ++offset; // try next character position + // we don't have to worry about surrogates for this. + } + } +//#endif + + public static String prettyPrint(UnicodeSet uset, boolean compressRanges, UnicodeSet toQuote, Transliterator quoter, + Comparator ordering, Comparator spaceComparator) { + PrettyPrinter pp = new PrettyPrinter().setCompressRanges(compressRanges); + if (toQuote != null) pp.setToQuote(toQuote); + if (ordering != null) pp.setOrdering(ordering); + if (spaceComparator != null) pp.setSpaceComparator(spaceComparator); + return pp.toPattern(uset); + } + + public static class MultiComparator implements Comparator { + private Comparator[] comparators; + + public MultiComparator (Comparator[] comparators) { + this.comparators = comparators; + } + + /* Lexigraphic compare. Returns the first difference + * @return zero if equal. Otherwise +/- (i+1) + * where i is the index of the first comparator finding a difference + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + public int compare(Object arg0, Object arg1) { + for (int i = 0; i < comparators.length; ++i) { + int result = comparators[i].compare(arg0, arg1); + if (result == 0) continue; + if (result > 0) return i+1; + return -(i+1); + } + return 0; + } + } + + /** + * Modifies Unicode set to flatten the strings. Eg [abc{da}] => [abcd] + * Returns the set for chaining. + * @param exemplar1 + * @return + */ + public static UnicodeSet flatten(UnicodeSet exemplar1) { + UnicodeSet result = new UnicodeSet(); + boolean gotString = false; + for (UnicodeSetIterator it = new UnicodeSetIterator(exemplar1); it.nextRange();) { + if (it.codepoint == UnicodeSetIterator.IS_STRING) { + result.addAll(it.string); + gotString = true; + } else { + result.add(it.codepoint, it.codepointEnd); + } + } + if (gotString) exemplar1.set(result); + return exemplar1; + } + + /** + * For producing filtered iterators + */ + public static abstract class FilteredIterator implements Iterator { + private Iterator baseIterator; + private static final Object EMPTY = new Object(); + private static final Object DONE = new Object(); + private Object nextObject = EMPTY; + public FilteredIterator set(Iterator baseIterator) { + this.baseIterator = baseIterator; + return this; + } + public void remove() { + throw new UnsupportedOperationException("Doesn't support removal"); + } + public Object next() { + Object result = nextObject; + nextObject = EMPTY; + return result; + } + public boolean hasNext() { + if (nextObject == DONE) return false; + if (nextObject != EMPTY) return true; + while (baseIterator.hasNext()) { + nextObject = baseIterator.next(); + if (isIncluded(nextObject)) { + return true; + } + } + nextObject = DONE; + return false; + } + abstract public boolean isIncluded(Object item); + } + + public static class PrefixIterator extends FilteredIterator { + private String prefix; + public PrefixIterator set(Iterator baseIterator, String prefix) { + super.set(baseIterator); + this.prefix = prefix; + return this; + } + public boolean isIncluded(Object item) { + return ((String)item).startsWith(prefix); + } + } + +//#if defined(FOUNDATION10) || defined(J2SE13) +//#else + public static class RegexIterator extends FilteredIterator { + private Matcher matcher; + public RegexIterator set(Iterator baseIterator, Matcher matcher) { + super.set(baseIterator); + this.matcher = matcher; + return this; + } + public boolean isIncluded(Object item) { + return matcher.reset((String)item).matches(); + } + } +//#endif +}