1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * Copyright (C) 1996-2012, International Business Machines Corporation and * 7 * others. All Rights Reserved. * 8 ******************************************************************************* 9 */ 10 package android.icu.dev.util; 11 12 import java.util.Iterator; 13 import java.util.Set; 14 15 import android.icu.text.UTF16; 16 import android.icu.testsharding.MainTestShard; 17 18 /** 19 * UnicodeSetIterator iterates over the contents of a UnicodeSet. It 20 * iterates over either code points or code point ranges. After all 21 * code points or ranges have been returned, it returns the 22 * multicharacter strings of the UnicodSet, if any. 23 * 24 * <p>To iterate over code points, use a loop like this: 25 * <pre> 26 * UnicodeSetIterator it = new UnicodeSetIterator(set); 27 * while (set.next()) { 28 * if (set.codepoint != UnicodeSetIterator.IS_STRING) { 29 * processCodepoint(set.codepoint); 30 * } else { 31 * processString(set.string); 32 * } 33 * } 34 * </pre> 35 * 36 * <p>To iterate over code point ranges, use a loop like this: 37 * <pre> 38 * UnicodeSetIterator it = new UnicodeSetIterator(set); 39 * while (set.nextRange()) { 40 * if (set.codepoint != UnicodeSetIterator.IS_STRING) { 41 * processCodepointRange(set.codepoint, set.codepointEnd); 42 * } else { 43 * processString(set.string); 44 * } 45 * } 46 * </pre> 47 * @author M. Davis 48 * 49 * @internal CLDR 50 */ 51 @MainTestShard 52 public class UnicodeMapIterator<T> { 53 54 /** 55 * Value of <tt>codepoint</tt> if the iterator points to a string. 56 * If <tt>codepoint == IS_STRING</tt>, then examine 57 * <tt>string</tt> for the current iteration result. 58 */ 59 public static int IS_STRING = -1; 60 61 /** 62 * Current code point, or the special value <tt>IS_STRING</tt>, if 63 * the iterator points to a string. 64 */ 65 public int codepoint; 66 67 /** 68 * When iterating over ranges using <tt>nextRange()</tt>, 69 * <tt>codepointEnd</tt> contains the inclusive end of the 70 * iteration range, if <tt>codepoint != IS_STRING</tt>. If 71 * iterating over code points using <tt>next()</tt>, or if 72 * <tt>codepoint == IS_STRING</tt>, then the value of 73 * <tt>codepointEnd</tt> is undefined. 74 */ 75 public int codepointEnd; 76 77 /** 78 * If <tt>codepoint == IS_STRING</tt>, then <tt>string</tt> points 79 * to the current string. If <tt>codepoint != IS_STRING</tt>, the 80 * value of <tt>string</tt> is undefined. 81 */ 82 public String string; 83 84 /** 85 * The value associated with this element or range. 86 */ 87 public T value; 88 89 /** 90 * Create an iterator over the given set. 91 * @param set set to iterate over 92 */ 93 public UnicodeMapIterator(UnicodeMap set) { 94 reset(set); 95 } 96 97 /** 98 * Create an iterator over nothing. <tt>next()</tt> and 99 * <tt>nextRange()</tt> return false. This is a convenience 100 * constructor allowing the target to be set later. 101 */ 102 public UnicodeMapIterator() { 103 reset(new UnicodeMap()); 104 } 105 106 /** 107 * Returns the next element in the set, either a single code point 108 * or a string. If there are no more elements in the set, return 109 * false. If <tt>codepoint == IS_STRING</tt>, the value is a 110 * string in the <tt>string</tt> field. Otherwise the value is a 111 * single code point in the <tt>codepoint</tt> field. 112 * 113 * <p>The order of iteration is all code points in sorted order, 114 * followed by all strings sorted order. <tt>codepointEnd</tt> is 115 * undefined after calling this method. <tt>string</tt> is 116 * undefined unless <tt>codepoint == IS_STRING</tt>. Do not mix 117 * calls to <tt>next()</tt> and <tt>nextRange()</tt> without 118 * calling <tt>reset()</tt> between them. The results of doing so 119 * are undefined. 120 * 121 * @return true if there was another element in the set and this 122 * object contains the element. 123 */ 124 public boolean next() { 125 if (nextElement <= endElement) { 126 codepoint = codepointEnd = nextElement++; 127 return true; 128 } 129 while (range < endRange) { 130 if (loadRange(++range) == null) { 131 continue; 132 } 133 codepoint = codepointEnd = nextElement++; 134 return true; 135 } 136 137 // stringIterator == null iff there are no string elements remaining 138 139 if (stringIterator == null) return false; 140 codepoint = IS_STRING; // signal that value is actually a string 141 string = (String)stringIterator.next(); 142 if (!stringIterator.hasNext()) stringIterator = null; 143 return true; 144 } 145 146 /** 147 * Returns the next element in the set, either a code point range 148 * or a string. If there are no more elements in the set, return 149 * false. If <tt>codepoint == IS_STRING</tt>, the value is a 150 * string in the <tt>string</tt> field. Otherwise the value is a 151 * range of one or more code points from <tt>codepoint</tt> to 152 * <tt>codepointeEnd</tt> inclusive. 153 * 154 * <p>The order of iteration is all code points ranges in sorted 155 * order, followed by all strings sorted order. Ranges are 156 * disjoint and non-contiguous. <tt>string</tt> is undefined 157 * unless <tt>codepoint == IS_STRING</tt>. Do not mix calls to 158 * <tt>next()</tt> and <tt>nextRange()</tt> without calling 159 * <tt>reset()</tt> between them. The results of doing so are 160 * undefined. 161 * 162 * @return true if there was another element in the set and this 163 * object contains the element. 164 */ 165 public boolean nextRange() { 166 if (nextElement <= endElement) { 167 codepointEnd = endElement; 168 codepoint = nextElement; 169 nextElement = endElement+1; 170 return true; 171 } 172 while (range < endRange) { 173 if (loadRange(++range) == null) { 174 continue; 175 } 176 codepointEnd = endElement; 177 codepoint = nextElement; 178 nextElement = endElement+1; 179 return true; 180 } 181 182 // stringIterator == null iff there are no string elements remaining 183 184 if (stringIterator == null) return false; 185 codepoint = IS_STRING; // signal that value is actually a string 186 string = (String)stringIterator.next(); 187 if (!stringIterator.hasNext()) stringIterator = null; 188 return true; 189 } 190 191 /** 192 * Sets this iterator to visit the elements of the given set and 193 * resets it to the start of that set. The iterator is valid only 194 * so long as <tt>set</tt> is valid. 195 * @param set the set to iterate over. 196 */ 197 public void reset(UnicodeMap set) { 198 this.map = set; 199 reset(); 200 } 201 202 /** 203 * Resets this iterator to the start of the set. 204 * @return 205 */ 206 public UnicodeMapIterator<T> reset() { 207 endRange = map.getRangeCount() - 1; 208 // both next*() methods will test: if (nextElement <= endElement) 209 // we set them to fail this test, which will cause them to load the first range 210 nextElement = 0; 211 endElement = -1; 212 range = -1; 213 214 stringIterator = null; 215 Set<String> strings = map.getNonRangeStrings(); 216 if (strings != null) { 217 stringIterator = strings.iterator(); 218 if (!stringIterator.hasNext()) stringIterator = null; 219 } 220 value = null; 221 return this; 222 } 223 224 /** 225 * Gets the current string from the iterator. Only use after calling next(), not nextRange(). 226 */ 227 public String getString() { 228 if (codepoint != IS_STRING) { 229 return UTF16.valueOf(codepoint); 230 } 231 return string; 232 } 233 234 // ======================= PRIVATES =========================== 235 236 private UnicodeMap<T> map; 237 private int endRange = 0; 238 private int range = 0; 239 private Iterator<String> stringIterator = null; 240 protected int endElement; 241 protected int nextElement; 242 243 /* 244 * Invariant: stringIterator is null when there are no (more) strings remaining 245 */ 246 247 protected T loadRange(int range) { 248 nextElement = map.getRangeStart(range); 249 endElement = map.getRangeEnd(range); 250 value = map.getRangeValue(range); 251 return value; 252 } 253 } 254