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-2011, International Business Machines Corporation and * 7 * others. All Rights Reserved. * 8 ****************************************************************************** 9 */ 10 11 package ohos.global.icu.lang; 12 13 import ohos.global.icu.impl.UCharacterName; 14 import ohos.global.icu.impl.UCharacterNameChoice; 15 import ohos.global.icu.util.ValueIterator; 16 17 /** 18 * <p>Class enabling iteration of the codepoints and their names.</p> 19 * <p>Result of each iteration contains a valid codepoint that has valid 20 * name.</p> 21 * <p>See UCharacter.getNameIterator() for an example of use.</p> 22 * @author synwee 23 */ 24 class UCharacterNameIterator implements ValueIterator 25 { 26 // public methods ---------------------------------------------------- 27 28 /** 29 * <p>Gets the next result for this iteration and returns 30 * true if we are not at the end of the iteration, false otherwise.</p> 31 * <p>If the return boolean is a false, the contents of elements will not 32 * be updated.</p> 33 * @param element for storing the result codepoint and name 34 * @return true if we are not at the end of the iteration, false otherwise. 35 * @see ohos.global.icu.util.ValueIterator.Element 36 */ 37 @Override next(ValueIterator.Element element)38 public boolean next(ValueIterator.Element element) 39 { 40 if (m_current_ >= m_limit_) { 41 return false; 42 } 43 44 if (m_choice_ == UCharacterNameChoice.UNICODE_CHAR_NAME || 45 m_choice_ == UCharacterNameChoice.EXTENDED_CHAR_NAME 46 ) { 47 int length = m_name_.getAlgorithmLength(); 48 if (m_algorithmIndex_ < length) { 49 while (m_algorithmIndex_ < length) { 50 // find the algorithm range that could contain m_current_ 51 if (m_algorithmIndex_ < 0 || 52 m_name_.getAlgorithmEnd(m_algorithmIndex_) < 53 m_current_) { 54 m_algorithmIndex_ ++; 55 } 56 else { 57 break; 58 } 59 } 60 61 if (m_algorithmIndex_ < length) { 62 // interleave the data-driven ones with the algorithmic ones 63 // iterate over all algorithmic ranges; assume that they are 64 // in ascending order 65 int start = m_name_.getAlgorithmStart(m_algorithmIndex_); 66 if (m_current_ < start) { 67 // this should get rid of those codepoints that are not 68 // in the algorithmic range 69 int end = start; 70 if (m_limit_ <= start) { 71 end = m_limit_; 72 } 73 if (!iterateGroup(element, end)) { 74 m_current_ ++; 75 return true; 76 } 77 } 78 /* 79 // "if (m_current_ >= m_limit_)" would not return true 80 // because it can never be reached due to: 81 // 1) It has already been checked earlier 82 // 2) When m_current_ is updated earlier, it returns true 83 // 3) No updates on m_limit_*/ 84 if (m_current_ >= m_limit_) { 85 // after iterateGroup fails, current codepoint may be 86 // greater than limit 87 return false; 88 } 89 90 element.integer = m_current_; 91 element.value = m_name_.getAlgorithmName(m_algorithmIndex_, 92 m_current_); 93 // reset the group index if we are in the algorithmic names 94 m_groupIndex_ = -1; 95 m_current_ ++; 96 return true; 97 } 98 } 99 } 100 // enumerate the character names after the last algorithmic range 101 if (!iterateGroup(element, m_limit_)) { 102 m_current_ ++; 103 return true; 104 } 105 else if (m_choice_ == UCharacterNameChoice.EXTENDED_CHAR_NAME) { 106 if (!iterateExtended(element, m_limit_)) { 107 m_current_ ++; 108 return true; 109 } 110 } 111 112 return false; 113 } 114 115 /** 116 * <p>Resets the iterator to start iterating from the integer index 117 * UCharacter.MIN_VALUE or X if a setRange(X, Y) has been called previously. 118 * </p> 119 */ 120 @Override reset()121 public void reset() 122 { 123 m_current_ = m_start_; 124 m_groupIndex_ = -1; 125 m_algorithmIndex_ = -1; 126 } 127 128 /** 129 * <p>Restricts the range of integers to iterate and resets the iteration 130 * to begin at the index argument start.</p> 131 * <p>If setRange(start, end) is not performed before next(element) is 132 * called, the iteration will start from the integer index 133 * UCharacter.MIN_VALUE and end at UCharacter.MAX_VALUE.</p> 134 * <p> 135 * If this range is set outside the range of UCharacter.MIN_VALUE and 136 * UCharacter.MAX_VALUE, next(element) will always return false. 137 * </p> 138 * @param start first integer in range to iterate 139 * @param limit 1 integer after the last integer in range 140 * @exception IllegalArgumentException thrown when attempting to set an 141 * illegal range. E.g limit <= start 142 */ 143 @Override setRange(int start, int limit)144 public void setRange(int start, int limit) 145 { 146 if (start >= limit) { 147 throw new IllegalArgumentException( 148 "start or limit has to be valid Unicode codepoints and start < limit"); 149 } 150 if (start < UCharacter.MIN_VALUE) { 151 m_start_ = UCharacter.MIN_VALUE; 152 } 153 else { 154 m_start_ = start; 155 } 156 157 if (limit > UCharacter.MAX_VALUE + 1) { 158 m_limit_ = UCharacter.MAX_VALUE + 1; 159 } 160 else { 161 m_limit_ = limit; 162 } 163 m_current_ = m_start_; 164 } 165 166 // protected constructor --------------------------------------------- 167 168 /** 169 * Constructor 170 * @param name name data 171 * @param choice name choice from the class 172 * ohos.global.icu.lang.UCharacterNameChoice 173 */ UCharacterNameIterator(UCharacterName name, int choice)174 protected UCharacterNameIterator(UCharacterName name, int choice) 175 { 176 if(name==null){ 177 throw new IllegalArgumentException("UCharacterName name argument cannot be null. Missing unames.icu?"); 178 } 179 m_name_ = name; 180 // no explicit choice in UCharacter so no checks on choice 181 m_choice_ = choice; 182 m_start_ = UCharacter.MIN_VALUE; 183 m_limit_ = UCharacter.MAX_VALUE + 1; 184 m_current_ = m_start_; 185 } 186 187 // private data members --------------------------------------------- 188 189 /** 190 * Name data 191 */ 192 private UCharacterName m_name_; 193 /** 194 * Name choice 195 */ 196 private int m_choice_; 197 /** 198 * Start iteration range 199 */ 200 private int m_start_; 201 /** 202 * End + 1 iteration range 203 */ 204 private int m_limit_; 205 /** 206 * Current codepoint 207 */ 208 private int m_current_; 209 /** 210 * Group index 211 */ 212 private int m_groupIndex_ = -1; 213 /** 214 * Algorithm index 215 */ 216 private int m_algorithmIndex_ = -1; 217 /** 218 * Group use 219 */ 220 private static char GROUP_OFFSETS_[] = 221 new char[UCharacterName.LINES_PER_GROUP_ + 1]; 222 private static char GROUP_LENGTHS_[] = 223 new char[UCharacterName.LINES_PER_GROUP_ + 1]; 224 225 // private methods -------------------------------------------------- 226 227 /** 228 * Group name iteration, iterate all the names in the current 32-group and 229 * returns the first codepoint that has a valid name. 230 * @param result stores the result codepoint and name 231 * @param limit last codepoint + 1 in range to search 232 * @return false if a codepoint with a name is found in group and we can 233 * bail from further iteration, true to continue on with the 234 * iteration 235 */ iterateSingleGroup(ValueIterator.Element result, int limit)236 private boolean iterateSingleGroup(ValueIterator.Element result, int limit) 237 { 238 synchronized(GROUP_OFFSETS_) { 239 synchronized(GROUP_LENGTHS_) { 240 int index = m_name_.getGroupLengths(m_groupIndex_, GROUP_OFFSETS_, 241 GROUP_LENGTHS_); 242 while (m_current_ < limit) { 243 int offset = UCharacterName.getGroupOffset(m_current_); 244 String name = m_name_.getGroupName( 245 index + GROUP_OFFSETS_[offset], 246 GROUP_LENGTHS_[offset], m_choice_); 247 if ((name == null || name.length() == 0) && 248 m_choice_ == UCharacterNameChoice.EXTENDED_CHAR_NAME) { 249 name = m_name_.getExtendedName(m_current_); 250 } 251 if (name != null && name.length() > 0) { 252 result.integer = m_current_; 253 result.value = name; 254 return false; 255 } 256 ++ m_current_; 257 } 258 } 259 } 260 return true; 261 } 262 263 /** 264 * Group name iteration, iterate all the names in the current 32-group and 265 * returns the first codepoint that has a valid name. 266 * @param result stores the result codepoint and name 267 * @param limit last codepoint + 1 in range to search 268 * @return false if a codepoint with a name is found in group and we can 269 * bail from further iteration, true to continue on with the 270 * iteration 271 */ iterateGroup(ValueIterator.Element result, int limit)272 private boolean iterateGroup(ValueIterator.Element result, int limit) 273 { 274 if (m_groupIndex_ < 0) { 275 m_groupIndex_ = m_name_.getGroup(m_current_); 276 } 277 278 while (m_groupIndex_ < m_name_.m_groupcount_ && 279 m_current_ < limit) { 280 // iterate till the last group or the last codepoint 281 int startMSB = UCharacterName.getCodepointMSB(m_current_); 282 int gMSB = m_name_.getGroupMSB(m_groupIndex_); // can be -1 283 if (startMSB == gMSB) { 284 if (startMSB == UCharacterName.getCodepointMSB(limit - 1)) { 285 // if start and limit - 1 are in the same group, then enumerate 286 // only in that one 287 return iterateSingleGroup(result, limit); 288 } 289 // enumerate characters in the partial start group 290 // if (m_name_.getGroupOffset(m_current_) != 0) { 291 if (!iterateSingleGroup(result, 292 UCharacterName.getGroupLimit(gMSB))) { 293 return false; 294 } 295 ++ m_groupIndex_; // continue with the next group 296 } 297 else if (startMSB > gMSB) { 298 // make sure that we start enumerating with the first group 299 // after start 300 m_groupIndex_ ++; 301 } 302 else { 303 int gMIN = UCharacterName.getGroupMin(gMSB); 304 if (gMIN > limit) { 305 gMIN = limit; 306 } 307 if (m_choice_ == UCharacterNameChoice.EXTENDED_CHAR_NAME) { 308 if (!iterateExtended(result, gMIN)) { 309 return false; 310 } 311 } 312 m_current_ = gMIN; 313 } 314 } 315 316 return true; 317 } 318 319 /** 320 * Iterate extended names. 321 * @param result stores the result codepoint and name 322 * @param limit last codepoint + 1 in range to search 323 * @return false if a codepoint with a name is found and we can 324 * bail from further iteration, true to continue on with the 325 * iteration (this will always be false for valid codepoints) 326 */ iterateExtended(ValueIterator.Element result, int limit)327 private boolean iterateExtended(ValueIterator.Element result, 328 int limit) 329 { 330 while (m_current_ < limit) { 331 String name = m_name_.getExtendedOr10Name(m_current_); 332 if (name != null && name.length() > 0) { 333 result.integer = m_current_; 334 result.value = name; 335 return false; 336 } 337 ++ m_current_; 338 } 339 return true; 340 } 341 } 342