1/*
2**********************************************************************
3* Copyright (c) 2002-2006, International Business Machines
4* Corporation and others.  All Rights Reserved.
5**********************************************************************
6*/
7#include "unicode/usetiter.h"
8#include "unicode/uniset.h"
9#include "unicode/unistr.h"
10#include "uvector.h"
11
12U_NAMESPACE_BEGIN
13
14UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeSetIterator)
15
16/**
17 * Create an iterator
18 * @param set set to iterate over
19 */
20UnicodeSetIterator::UnicodeSetIterator(const UnicodeSet& uSet) {
21    cpString  = NULL;
22    reset(uSet);
23}
24
25/**
26 * Create an iterator. Convenience for when the contents are to be set later.
27 */
28UnicodeSetIterator::UnicodeSetIterator() {
29    this->set = NULL;
30    cpString  = NULL;
31    reset();
32}
33
34UnicodeSetIterator::~UnicodeSetIterator() {
35    delete cpString;
36}
37
38/**
39 * Returns the next element in the set.
40 * @return true if there was another element in the set.
41 * if so, if codepoint == IS_STRING, the value is a string in the string field
42 * else the value is a single code point in the codepoint field.
43 * <br>You are guaranteed that the codepoints are in sorted order, and the strings are in sorted order,
44 * and that all code points are returned before any strings are returned.
45 * <br>Note also that the codepointEnd is undefined after calling this method.
46 */
47UBool UnicodeSetIterator::next() {
48    if (nextElement <= endElement) {
49        codepoint = codepointEnd = nextElement++;
50        string = NULL;
51        return TRUE;
52    }
53    if (range < endRange) {
54        loadRange(++range);
55        codepoint = codepointEnd = nextElement++;
56        string = NULL;
57        return TRUE;
58    }
59
60    if (nextString >= stringCount) return FALSE;
61    codepoint = (UChar32)IS_STRING; // signal that value is actually a string
62    string = (const UnicodeString*) set->strings->elementAt(nextString++);
63    return TRUE;
64}
65
66/**
67 * @return true if there was another element in the set.
68 * if so, if codepoint == IS_STRING, the value is a string in the string field
69 * else the value is a range of codepoints in the <codepoint, codepointEnd> fields.
70 * <br>Note that the codepoints are in sorted order, and the strings are in sorted order,
71 * and that all code points are returned before any strings are returned.
72 * <br>You are guaranteed that the ranges are in sorted order, and the strings are in sorted order,
73 * and that all ranges are returned before any strings are returned.
74 * <br>You are also guaranteed that ranges are disjoint and non-contiguous.
75 * <br>Note also that the codepointEnd is undefined after calling this method.
76 */
77UBool UnicodeSetIterator::nextRange() {
78    string = NULL;
79    if (nextElement <= endElement) {
80        codepointEnd = endElement;
81        codepoint = nextElement;
82        nextElement = endElement+1;
83        return TRUE;
84    }
85    if (range < endRange) {
86        loadRange(++range);
87        codepointEnd = endElement;
88        codepoint = nextElement;
89        nextElement = endElement+1;
90        return TRUE;
91    }
92
93    if (nextString >= stringCount) return FALSE;
94    codepoint = (UChar32)IS_STRING; // signal that value is actually a string
95    string = (const UnicodeString*) set->strings->elementAt(nextString++);
96    return TRUE;
97}
98
99/**
100 *@param set the set to iterate over. This allows reuse of the iterator.
101 */
102void UnicodeSetIterator::reset(const UnicodeSet& uSet) {
103    this->set = &uSet;
104    reset();
105}
106
107/**
108 * Resets to the start, to allow the iteration to start over again.
109 */
110void UnicodeSetIterator::reset() {
111    if (set == NULL) {
112        // Set up indices to empty iteration
113        endRange = -1;
114        stringCount = 0;
115    } else {
116        endRange = set->getRangeCount() - 1;
117        stringCount = set->strings->size();
118    }
119    range = 0;
120    endElement = -1;
121    nextElement = 0;
122    if (endRange >= 0) {
123        loadRange(range);
124    }
125    nextString = 0;
126    string = NULL;
127}
128
129void UnicodeSetIterator::loadRange(int32_t iRange) {
130    nextElement = set->getRangeStart(iRange);
131    endElement = set->getRangeEnd(iRange);
132}
133
134
135const UnicodeString& UnicodeSetIterator::getString()  {
136    if (string==NULL && codepoint!=(UChar32)IS_STRING) {
137       if (cpString == NULL) {
138          cpString = new UnicodeString();
139       }
140       if (cpString != NULL) {
141          cpString->setTo((UChar32)codepoint);
142       }
143       string = cpString;
144    }
145    return *string;
146}
147
148U_NAMESPACE_END
149
150//eof
151