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