Home | History | Annotate | Download | only in util
      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