1fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/*
2fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*******************************************************************************
3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (C) 2012-2014, International Business Machines
4fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Corporation and others.  All Rights Reserved.
5fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*******************************************************************************
6fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* uitercollationiterator.cpp
7fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*
8fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* created on: 2012sep23 (from utf16collationiterator.cpp)
9fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* created by: Markus W. Scherer
10fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*/
11fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
12fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/utypes.h"
13fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
14fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_COLLATION
15fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
16fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/uiter.h"
17fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "charstr.h"
18fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "cmemory.h"
19fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collation.h"
20fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdata.h"
21fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationfcd.h"
22fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationiterator.h"
23fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "normalizer2impl.h"
24fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "uassert.h"
25fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "uitercollationiterator.h"
26fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
27fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_BEGIN
28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUIterCollationIterator::~UIterCollationIterator() {}
30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
32fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUIterCollationIterator::resetToOffset(int32_t newOffset) {
33fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    reset();
34fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    iter.move(&iter, newOffset, UITER_START);
35fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
36fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
37fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusint32_t
38fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUIterCollationIterator::getOffset() const {
39fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return iter.getIndex(&iter, UITER_CURRENT);
40fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
41fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
42fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusuint32_t
43fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUIterCollationIterator::handleNextCE32(UChar32 &c, UErrorCode & /*errorCode*/) {
44fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    c = iter.next(&iter);
45fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(c < 0) {
46fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return Collation::FALLBACK_CE32;
47fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
48fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return UTRIE2_GET32_FROM_U16_SINGLE_LEAD(trie, c);
49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
51fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUChar
52fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUIterCollationIterator::handleGetTrailSurrogate() {
53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UChar32 trail = iter.next(&iter);
54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(!U16_IS_TRAIL(trail) && trail >= 0) { iter.previous(&iter); }
55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return (UChar)trail;
56fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUChar32
59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUIterCollationIterator::nextCodePoint(UErrorCode & /*errorCode*/) {
60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return uiter_next32(&iter);
61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
62fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
63fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUChar32
64fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUIterCollationIterator::previousCodePoint(UErrorCode & /*errorCode*/) {
65fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return uiter_previous32(&iter);
66fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
67fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
68fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
69fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUIterCollationIterator::forwardNumCodePoints(int32_t num, UErrorCode & /*errorCode*/) {
70fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    while(num > 0 && (uiter_next32(&iter)) >= 0) {
71fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        --num;
72fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
73fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
74fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
75fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
76fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUIterCollationIterator::backwardNumCodePoints(int32_t num, UErrorCode & /*errorCode*/) {
77fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    while(num > 0 && (uiter_previous32(&iter)) >= 0) {
78fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        --num;
79fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
80fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// FCDUIterCollationIterator ----------------------------------------------- ***
83fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
84fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::~FCDUIterCollationIterator() {}
85fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
86fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
87fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::resetToOffset(int32_t newOffset) {
88fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UIterCollationIterator::resetToOffset(newOffset);
89fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    start = newOffset;
90fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    state = ITER_CHECK_FWD;
91fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
92fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
93fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusint32_t
94fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::getOffset() const {
95fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(state <= ITER_CHECK_BWD) {
96fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return iter.getIndex(&iter, UITER_CURRENT);
97fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else if(state == ITER_IN_FCD_SEGMENT) {
98fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return pos;
99fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else if(pos == 0) {
100fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return start;
101fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
102fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return limit;
103fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
104fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
105fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
106fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusuint32_t
107fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::handleNextCE32(UChar32 &c, UErrorCode &errorCode) {
108fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    for(;;) {
109fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(state == ITER_CHECK_FWD) {
110fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            c = iter.next(&iter);
111fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(c < 0) {
112fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                return Collation::FALLBACK_CE32;
113fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
114fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(CollationFCD::hasTccc(c)) {
115fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if(CollationFCD::maybeTibetanCompositeVowel(c) ||
116fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        CollationFCD::hasLccc(iter.current(&iter))) {
117fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    iter.previous(&iter);
118fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if(!nextSegment(errorCode)) {
119fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        c = U_SENTINEL;
120fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return Collation::FALLBACK_CE32;
121fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    continue;
123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
125fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
126fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else if(state == ITER_IN_FCD_SEGMENT && pos != limit) {
127fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            c = iter.next(&iter);
128fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            ++pos;
129fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            U_ASSERT(c >= 0);
130fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
131fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else if(state >= IN_NORM_ITER_AT_LIMIT && pos != normalized.length()) {
132fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            c = normalized[pos++];
133fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
134fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else {
135fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            switchToForward();
136fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
137fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
138fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return UTRIE2_GET32_FROM_U16_SINGLE_LEAD(trie, c);
139fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
140fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
141fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUChar
142fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::handleGetTrailSurrogate() {
143fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(state <= ITER_IN_FCD_SEGMENT) {
144fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UChar32 trail = iter.next(&iter);
145fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(U16_IS_TRAIL(trail)) {
146fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(state == ITER_IN_FCD_SEGMENT) { ++pos; }
147fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else if(trail >= 0) {
148fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            iter.previous(&iter);
149fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
150fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return (UChar)trail;
151fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
152fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        U_ASSERT(pos < normalized.length());
153fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UChar trail;
154fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(U16_IS_TRAIL(trail = normalized[pos])) { ++pos; }
155fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return trail;
156fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
157fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
158fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
159fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUChar32
160fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::nextCodePoint(UErrorCode &errorCode) {
161fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UChar32 c;
162fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    for(;;) {
163fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(state == ITER_CHECK_FWD) {
164fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            c = iter.next(&iter);
165fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(c < 0) {
166fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                return c;
167fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
168fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(CollationFCD::hasTccc(c)) {
169fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if(CollationFCD::maybeTibetanCompositeVowel(c) ||
170fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        CollationFCD::hasLccc(iter.current(&iter))) {
171fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    iter.previous(&iter);
172fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if(!nextSegment(errorCode)) {
173fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return U_SENTINEL;
174fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
175fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    continue;
176fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
177fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
178fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(U16_IS_LEAD(c)) {
179fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                UChar32 trail = iter.next(&iter);
180fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if(U16_IS_TRAIL(trail)) {
181fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    return U16_GET_SUPPLEMENTARY(c, trail);
182fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if(trail >= 0) {
183fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    iter.previous(&iter);
184fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
185fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
186fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return c;
187fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else if(state == ITER_IN_FCD_SEGMENT && pos != limit) {
188fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            c = uiter_next32(&iter);
189fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            pos += U16_LENGTH(c);
190fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            U_ASSERT(c >= 0);
191fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return c;
192fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else if(state >= IN_NORM_ITER_AT_LIMIT && pos != normalized.length()) {
193fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            c = normalized.char32At(pos);
194fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            pos += U16_LENGTH(c);
195fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return c;
196fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else {
197fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            switchToForward();
198fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
199fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
200fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
201fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
202fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUChar32
203fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::previousCodePoint(UErrorCode &errorCode) {
204fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UChar32 c;
205fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    for(;;) {
206fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(state == ITER_CHECK_BWD) {
207fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            c = iter.previous(&iter);
208fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(c < 0) {
209fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                start = pos = 0;
210fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                state = ITER_IN_FCD_SEGMENT;
211fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                return U_SENTINEL;
212fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
213fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(CollationFCD::hasLccc(c)) {
214fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                UChar32 prev = U_SENTINEL;
215fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if(CollationFCD::maybeTibetanCompositeVowel(c) ||
216fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        CollationFCD::hasTccc(prev = iter.previous(&iter))) {
217fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    iter.next(&iter);
218fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if(prev >= 0) {
219fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        iter.next(&iter);
220fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
221fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if(!previousSegment(errorCode)) {
222fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return U_SENTINEL;
223fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
224fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    continue;
225fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
226fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // hasLccc(trail)=true for all trail surrogates
227fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if(U16_IS_TRAIL(c)) {
228fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if(prev < 0) {
229fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        prev = iter.previous(&iter);
230fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
231fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if(U16_IS_LEAD(prev)) {
232fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return U16_GET_SUPPLEMENTARY(prev, c);
233fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
234fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
235fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if(prev >= 0) {
236fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    iter.next(&iter);
237fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
238fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
239fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return c;
240fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else if(state == ITER_IN_FCD_SEGMENT && pos != start) {
241fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            c = uiter_previous32(&iter);
242fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            pos -= U16_LENGTH(c);
243fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            U_ASSERT(c >= 0);
244fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return c;
245fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else if(state >= IN_NORM_ITER_AT_LIMIT && pos != 0) {
246fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            c = normalized.char32At(pos - 1);
247fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            pos -= U16_LENGTH(c);
248fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return c;
249fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else {
250fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            switchToBackward();
251fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
252fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
253fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
254fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
255fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
256fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::forwardNumCodePoints(int32_t num, UErrorCode &errorCode) {
257fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // Specify the class to avoid a virtual-function indirection.
258fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // In Java, we would declare this class final.
259fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    while(num > 0 && FCDUIterCollationIterator::nextCodePoint(errorCode) >= 0) {
260fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        --num;
261fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
262fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
263fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
264fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
265fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::backwardNumCodePoints(int32_t num, UErrorCode &errorCode) {
266fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // Specify the class to avoid a virtual-function indirection.
267fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // In Java, we would declare this class final.
268fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    while(num > 0 && FCDUIterCollationIterator::previousCodePoint(errorCode) >= 0) {
269fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        --num;
270fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
271fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
272fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
273fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
274fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::switchToForward() {
275fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    U_ASSERT(state == ITER_CHECK_BWD ||
276fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius             (state == ITER_IN_FCD_SEGMENT && pos == limit) ||
277fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius             (state >= IN_NORM_ITER_AT_LIMIT && pos == normalized.length()));
278fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(state == ITER_CHECK_BWD) {
279fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Turn around from backward checking.
280fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        start = pos = iter.getIndex(&iter, UITER_CURRENT);
281fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(pos == limit) {
282fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            state = ITER_CHECK_FWD;  // Check forward.
283fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else {  // pos < limit
284fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            state = ITER_IN_FCD_SEGMENT;  // Stay in FCD segment.
285fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
286fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
287fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Reached the end of the FCD segment.
288fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(state == ITER_IN_FCD_SEGMENT) {
289fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // The input text segment is FCD, extend it forward.
290fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else {
291fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // The input text segment needed to be normalized.
292fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Switch to checking forward from it.
293fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(state == IN_NORM_ITER_AT_START) {
294fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                iter.move(&iter, limit - start, UITER_CURRENT);
295fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
296fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            start = limit;
297fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
298fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        state = ITER_CHECK_FWD;
299fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
300fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
301fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
302fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUBool
303fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::nextSegment(UErrorCode &errorCode) {
304fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(errorCode)) { return FALSE; }
305fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    U_ASSERT(state == ITER_CHECK_FWD);
306fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // The input text [start..(iter index)[ passes the FCD check.
307fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    pos = iter.getIndex(&iter, UITER_CURRENT);
308fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // Collect the characters being checked, in case they need to be normalized.
309fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UnicodeString s;
310fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    uint8_t prevCC = 0;
311fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    for(;;) {
312fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Fetch the next character and its fcd16 value.
313fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UChar32 c = uiter_next32(&iter);
314fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(c < 0) { break; }
315fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        uint16_t fcd16 = nfcImpl.getFCD16(c);
316fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        uint8_t leadCC = (uint8_t)(fcd16 >> 8);
317fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(leadCC == 0 && !s.isEmpty()) {
318fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // FCD boundary before this character.
319fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            uiter_previous32(&iter);
320fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
321fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
322fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        s.append(c);
323fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(leadCC != 0 && (prevCC > leadCC || CollationFCD::isFCD16OfTibetanCompositeVowel(fcd16))) {
324fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Fails FCD check. Find the next FCD boundary and normalize.
325fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            for(;;) {
326fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                c = uiter_next32(&iter);
327fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if(c < 0) { break; }
328fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if(nfcImpl.getFCD16(c) <= 0xff) {
329fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    uiter_previous32(&iter);
330fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    break;
331fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
332fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                s.append(c);
333fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
334fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(!normalize(s, errorCode)) { return FALSE; }
335fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            start = pos;
336fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            limit = pos + s.length();
337fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            state = IN_NORM_ITER_AT_LIMIT;
338fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            pos = 0;
339fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return TRUE;
340fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
341fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        prevCC = (uint8_t)fcd16;
342fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(prevCC == 0) {
343fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // FCD boundary after the last character.
344fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
345fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
346fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
347fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    limit = pos + s.length();
348fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    U_ASSERT(pos != limit);
349fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    iter.move(&iter, -s.length(), UITER_CURRENT);
350fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    state = ITER_IN_FCD_SEGMENT;
351fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return TRUE;
352fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
353fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
354fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
355fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::switchToBackward() {
356fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    U_ASSERT(state == ITER_CHECK_FWD ||
357fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius             (state == ITER_IN_FCD_SEGMENT && pos == start) ||
358fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius             (state >= IN_NORM_ITER_AT_LIMIT && pos == 0));
359fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(state == ITER_CHECK_FWD) {
360fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Turn around from forward checking.
361fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        limit = pos = iter.getIndex(&iter, UITER_CURRENT);
362fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(pos == start) {
363fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            state = ITER_CHECK_BWD;  // Check backward.
364fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else {  // pos > start
365fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            state = ITER_IN_FCD_SEGMENT;  // Stay in FCD segment.
366fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
367fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
368fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Reached the start of the FCD segment.
369fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(state == ITER_IN_FCD_SEGMENT) {
370fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // The input text segment is FCD, extend it backward.
371fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else {
372fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // The input text segment needed to be normalized.
373fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Switch to checking backward from it.
374fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(state == IN_NORM_ITER_AT_LIMIT) {
375fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                iter.move(&iter, start - limit, UITER_CURRENT);
376fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
377fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            limit = start;
378fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
379fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        state = ITER_CHECK_BWD;
380fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
381fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
382fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
383fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUBool
384fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::previousSegment(UErrorCode &errorCode) {
385fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(errorCode)) { return FALSE; }
386fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    U_ASSERT(state == ITER_CHECK_BWD);
387fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // The input text [(iter index)..limit[ passes the FCD check.
388fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    pos = iter.getIndex(&iter, UITER_CURRENT);
389fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // Collect the characters being checked, in case they need to be normalized.
390fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UnicodeString s;
391fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    uint8_t nextCC = 0;
392fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    for(;;) {
393fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Fetch the previous character and its fcd16 value.
394fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UChar32 c = uiter_previous32(&iter);
395fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(c < 0) { break; }
396fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        uint16_t fcd16 = nfcImpl.getFCD16(c);
397fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        uint8_t trailCC = (uint8_t)fcd16;
398fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(trailCC == 0 && !s.isEmpty()) {
399fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // FCD boundary after this character.
400fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            uiter_next32(&iter);
401fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
402fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
403fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        s.append(c);
404fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(trailCC != 0 && ((nextCC != 0 && trailCC > nextCC) ||
405fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            CollationFCD::isFCD16OfTibetanCompositeVowel(fcd16))) {
406fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Fails FCD check. Find the previous FCD boundary and normalize.
407fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            while(fcd16 > 0xff) {
408fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                c = uiter_previous32(&iter);
409fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if(c < 0) { break; }
410fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                fcd16 = nfcImpl.getFCD16(c);
411fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if(fcd16 == 0) {
412fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    (void)uiter_next32(&iter);
413fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    break;
414fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
415fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                s.append(c);
416fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
417fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            s.reverse();
418fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(!normalize(s, errorCode)) { return FALSE; }
419fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            limit = pos;
420fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            start = pos - s.length();
421fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            state = IN_NORM_ITER_AT_START;
422fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            pos = normalized.length();
423fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return TRUE;
424fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
425fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        nextCC = (uint8_t)(fcd16 >> 8);
426fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(nextCC == 0) {
427fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // FCD boundary before the following character.
428fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
429fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
430fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
431fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    start = pos - s.length();
432fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    U_ASSERT(pos != start);
433fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    iter.move(&iter, s.length(), UITER_CURRENT);
434fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    state = ITER_IN_FCD_SEGMENT;
435fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return TRUE;
436fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
437fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
438fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUBool
439fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFCDUIterCollationIterator::normalize(const UnicodeString &s, UErrorCode &errorCode) {
440fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // NFD without argument checking.
441fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    U_ASSERT(U_SUCCESS(errorCode));
442fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    nfcImpl.decompose(s, normalized, errorCode);
443fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return U_SUCCESS(errorCode);
444fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
445fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
446fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_END
447fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
448fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif  // !UCONFIG_NO_COLLATION
449