LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - uitercollationiterator.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 257 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 25 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13