• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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