| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2 ******************************************************************************* |  | 
| 3 * |  | 
| 4 *   Copyright (C) 2003-2011, International Business Machines |  | 
| 5 *   Corporation and others.  All Rights Reserved. |  | 
| 6 * |  | 
| 7 ******************************************************************************* |  | 
| 8 *   file name:  unorm_it.c |  | 
| 9 *   encoding:   US-ASCII |  | 
| 10 *   tab size:   8 (not used) |  | 
| 11 *   indentation:4 |  | 
| 12 * |  | 
| 13 *   created on: 2003jan21 |  | 
| 14 *   created by: Markus W. Scherer |  | 
| 15 */ |  | 
| 16 |  | 
| 17 #include "unicode/utypes.h" |  | 
| 18 |  | 
| 19 #if !UCONFIG_NO_COLLATION && !UCONFIG_NO_NORMALIZATION |  | 
| 20 |  | 
| 21 #include "unicode/uiter.h" |  | 
| 22 #include "unicode/unorm.h" |  | 
| 23 #include "unicode/utf.h" |  | 
| 24 #include "unorm_it.h" |  | 
| 25 #include "cmemory.h" |  | 
| 26 |  | 
| 27 /* UNormIterator ------------------------------------------------------------ */ |  | 
| 28 |  | 
| 29 enum { |  | 
| 30     INITIAL_CAPACITY=100 |  | 
| 31 }; |  | 
| 32 |  | 
| 33 struct UNormIterator { |  | 
| 34     UCharIterator api; |  | 
| 35     UCharIterator *iter; |  | 
| 36 |  | 
| 37     /* |  | 
| 38      * chars and states either use the static buffers |  | 
| 39      * or are allocated in the same memory block |  | 
| 40      * |  | 
| 41      * They are parallel arrays with states[] holding the getState() values |  | 
| 42      * from normalization boundaries, and UITER_NO_STATE in between. |  | 
| 43      */ |  | 
| 44     UChar *chars; |  | 
| 45     uint32_t *states; |  | 
| 46 |  | 
| 47     /* |  | 
| 48      * api.start: first valid character & state in the arrays |  | 
| 49      * api.index: current position |  | 
| 50      * api.limit: one past the last valid character in chars[], but states[limit
     ] is valid |  | 
| 51      * capacity: length of allocated arrays |  | 
| 52      */ |  | 
| 53     int32_t capacity; |  | 
| 54 |  | 
| 55     /* the current iter->getState(), saved to avoid unnecessary setState() calls
     ; may not correspond to api->index! */ |  | 
| 56     uint32_t state; |  | 
| 57 |  | 
| 58     /* there are UChars available before start or after limit? */ |  | 
| 59     UBool hasPrevious, hasNext, isStackAllocated; |  | 
| 60 |  | 
| 61     UNormalizationMode mode; |  | 
| 62 |  | 
| 63     UChar charsBuffer[INITIAL_CAPACITY]; |  | 
| 64     uint32_t statesBuffer[INITIAL_CAPACITY+1]; /* one more than charsBuffer[]! *
     / |  | 
| 65 }; |  | 
| 66 |  | 
| 67 static void |  | 
| 68 initIndexes(UNormIterator *uni, UCharIterator *iter) { |  | 
| 69     /* do not pass api so that the compiler knows it's an alias pointer to uni i
     tself */ |  | 
| 70     UCharIterator *api=&uni->api; |  | 
| 71 |  | 
| 72     if(!iter->hasPrevious(iter)) { |  | 
| 73         /* set indexes to the beginning of the arrays */ |  | 
| 74         api->start=api->index=api->limit=0; |  | 
| 75         uni->hasPrevious=FALSE; |  | 
| 76         uni->hasNext=iter->hasNext(iter); |  | 
| 77     } else if(!iter->hasNext(iter)) { |  | 
| 78         /* set indexes to the end of the arrays */ |  | 
| 79         api->start=api->index=api->limit=uni->capacity; |  | 
| 80         uni->hasNext=FALSE; |  | 
| 81         uni->hasPrevious=iter->hasPrevious(iter); |  | 
| 82     } else { |  | 
| 83         /* set indexes into the middle of the arrays */ |  | 
| 84         api->start=api->index=api->limit=uni->capacity/2; |  | 
| 85         uni->hasPrevious=uni->hasNext=TRUE; |  | 
| 86     } |  | 
| 87 } |  | 
| 88 |  | 
| 89 static UBool |  | 
| 90 reallocArrays(UNormIterator *uni, int32_t capacity, UBool addAtStart) { |  | 
| 91     /* do not pass api so that the compiler knows it's an alias pointer to uni i
     tself */ |  | 
| 92     UCharIterator *api=&uni->api; |  | 
| 93 |  | 
| 94     uint32_t *states; |  | 
| 95     UChar *chars; |  | 
| 96     int32_t start, limit; |  | 
| 97 |  | 
| 98     states=(uint32_t *)uprv_malloc((capacity+1)*4+capacity*2); |  | 
| 99     if(states==NULL) { |  | 
| 100         return FALSE; |  | 
| 101     } |  | 
| 102 |  | 
| 103     chars=(UChar *)(states+(capacity+1)); |  | 
| 104     uni->capacity=capacity; |  | 
| 105 |  | 
| 106     start=api->start; |  | 
| 107     limit=api->limit; |  | 
| 108 |  | 
| 109     if(addAtStart) { |  | 
| 110         /* copy old contents to the end of the new arrays */ |  | 
| 111         int32_t delta; |  | 
| 112 |  | 
| 113         delta=capacity-uni->capacity; |  | 
| 114         uprv_memcpy(states+delta+start, uni->states+start, (limit-start+1)*4); |  | 
| 115         uprv_memcpy(chars+delta+start, uni->chars+start, (limit-start)*4); |  | 
| 116 |  | 
| 117         api->start=start+delta; |  | 
| 118         api->index+=delta; |  | 
| 119         api->limit=limit+delta; |  | 
| 120     } else { |  | 
| 121         /* copy old contents to the beginning of the new arrays */ |  | 
| 122         uprv_memcpy(states+start, uni->states+start, (limit-start+1)*4); |  | 
| 123         uprv_memcpy(chars+start, uni->chars+start, (limit-start)*4); |  | 
| 124     } |  | 
| 125 |  | 
| 126     uni->chars=chars; |  | 
| 127     uni->states=states; |  | 
| 128 |  | 
| 129     return TRUE; |  | 
| 130 } |  | 
| 131 |  | 
| 132 static void |  | 
| 133 moveContentsTowardStart(UCharIterator *api, UChar chars[], uint32_t states[], in
     t32_t delta) { |  | 
| 134     /* move array contents up to make room */ |  | 
| 135     int32_t srcIndex, destIndex, limit; |  | 
| 136 |  | 
| 137     limit=api->limit; |  | 
| 138     srcIndex=delta; |  | 
| 139     if(srcIndex>api->start) { |  | 
| 140         /* look for a position in the arrays with a known state */ |  | 
| 141         while(srcIndex<limit && states[srcIndex]==UITER_NO_STATE) { |  | 
| 142             ++srcIndex; |  | 
| 143         } |  | 
| 144     } |  | 
| 145 |  | 
| 146     /* now actually move the array contents */ |  | 
| 147     api->start=destIndex=0; |  | 
| 148     while(srcIndex<limit) { |  | 
| 149         chars[destIndex]=chars[srcIndex]; |  | 
| 150         states[destIndex++]=states[srcIndex++]; |  | 
| 151     } |  | 
| 152 |  | 
| 153     /* copy states[limit] as well! */ |  | 
| 154     states[destIndex]=states[srcIndex]; |  | 
| 155 |  | 
| 156     api->limit=destIndex; |  | 
| 157 } |  | 
| 158 |  | 
| 159 static void |  | 
| 160 moveContentsTowardEnd(UCharIterator *api, UChar chars[], uint32_t states[], int3
     2_t delta) { |  | 
| 161     /* move array contents up to make room */ |  | 
| 162     int32_t srcIndex, destIndex, start; |  | 
| 163 |  | 
| 164     start=api->start; |  | 
| 165     destIndex=((UNormIterator *)api)->capacity; |  | 
| 166     srcIndex=destIndex-delta; |  | 
| 167     if(srcIndex<api->limit) { |  | 
| 168         /* look for a position in the arrays with a known state */ |  | 
| 169         while(srcIndex>start && states[srcIndex]==UITER_NO_STATE) { |  | 
| 170             --srcIndex; |  | 
| 171         } |  | 
| 172     } |  | 
| 173 |  | 
| 174     /* now actually move the array contents */ |  | 
| 175     api->limit=destIndex; |  | 
| 176 |  | 
| 177     /* copy states[limit] as well! */ |  | 
| 178     states[destIndex]=states[srcIndex]; |  | 
| 179 |  | 
| 180     while(srcIndex>start) { |  | 
| 181         chars[--destIndex]=chars[--srcIndex]; |  | 
| 182         states[destIndex]=states[srcIndex]; |  | 
| 183     } |  | 
| 184 |  | 
| 185     api->start=destIndex; |  | 
| 186 } |  | 
| 187 |  | 
| 188 /* normalize forward from the limit, assume hasNext is true */ |  | 
| 189 static UBool |  | 
| 190 readNext(UNormIterator *uni, UCharIterator *iter) { |  | 
| 191     /* do not pass api so that the compiler knows it's an alias pointer to uni i
     tself */ |  | 
| 192     UCharIterator *api=&uni->api; |  | 
| 193 |  | 
| 194     /* make capacity/4 room at the end of the arrays */ |  | 
| 195     int32_t limit, capacity, room; |  | 
| 196     UErrorCode errorCode; |  | 
| 197 |  | 
| 198     limit=api->limit; |  | 
| 199     capacity=uni->capacity; |  | 
| 200     room=capacity/4; |  | 
| 201     if(room>(capacity-limit)) { |  | 
| 202         /* move array contents to make room */ |  | 
| 203         moveContentsTowardStart(api, uni->chars, uni->states, room); |  | 
| 204         api->index=limit=api->limit; |  | 
| 205         uni->hasPrevious=TRUE; |  | 
| 206     } |  | 
| 207 |  | 
| 208     /* normalize starting from the limit position */ |  | 
| 209     errorCode=U_ZERO_ERROR; |  | 
| 210     if(uni->state!=uni->states[limit]) { |  | 
| 211         uiter_setState(iter, uni->states[limit], &errorCode); |  | 
| 212         if(U_FAILURE(errorCode)) { |  | 
| 213             uni->state=UITER_NO_STATE; |  | 
| 214             uni->hasNext=FALSE; |  | 
| 215             return FALSE; |  | 
| 216         } |  | 
| 217     } |  | 
| 218 |  | 
| 219     room=unorm_next(iter, uni->chars+limit, capacity-limit, uni->mode, 0, TRUE, 
     NULL, &errorCode); |  | 
| 220     if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |  | 
| 221         if(room<=capacity) { |  | 
| 222             /* empty and re-use the arrays */ |  | 
| 223             uni->states[0]=uni->states[limit]; |  | 
| 224             api->start=api->index=api->limit=limit=0; |  | 
| 225             uni->hasPrevious=TRUE; |  | 
| 226         } else { |  | 
| 227             capacity+=room+100; |  | 
| 228             if(!reallocArrays(uni, capacity, FALSE)) { |  | 
| 229                 uni->state=UITER_NO_STATE; |  | 
| 230                 uni->hasNext=FALSE; |  | 
| 231                 return FALSE; |  | 
| 232             } |  | 
| 233             limit=api->limit; |  | 
| 234         } |  | 
| 235 |  | 
| 236         errorCode=U_ZERO_ERROR; |  | 
| 237         uiter_setState(iter, uni->states[limit], &errorCode); |  | 
| 238         room=unorm_next(iter, uni->chars+limit, capacity-limit, uni->mode, 0, TR
     UE, NULL, &errorCode); |  | 
| 239     } |  | 
| 240     if(U_FAILURE(errorCode) || room==0) { |  | 
| 241         uni->state=UITER_NO_STATE; |  | 
| 242         uni->hasNext=FALSE; |  | 
| 243         return FALSE; |  | 
| 244     } |  | 
| 245 |  | 
| 246     /* room>0 */ |  | 
| 247     ++limit; /* leave the known states[limit] alone */ |  | 
| 248     for(--room; room>0; --room) { |  | 
| 249         /* set unknown states for all but the normalization boundaries */ |  | 
| 250         uni->states[limit++]=UITER_NO_STATE; |  | 
| 251     } |  | 
| 252     uni->states[limit]=uni->state=uiter_getState(iter); |  | 
| 253     uni->hasNext=iter->hasNext(iter); |  | 
| 254     api->limit=limit; |  | 
| 255     return TRUE; |  | 
| 256 } |  | 
| 257 |  | 
| 258 /* normalize backward from the start, assume hasPrevious is true */ |  | 
| 259 static UBool |  | 
| 260 readPrevious(UNormIterator *uni, UCharIterator *iter) { |  | 
| 261     /* do not pass api so that the compiler knows it's an alias pointer to uni i
     tself */ |  | 
| 262     UCharIterator *api=&uni->api; |  | 
| 263 |  | 
| 264     /* make capacity/4 room at the start of the arrays */ |  | 
| 265     int32_t start, capacity, room; |  | 
| 266     UErrorCode errorCode; |  | 
| 267 |  | 
| 268     start=api->start; |  | 
| 269     capacity=uni->capacity; |  | 
| 270     room=capacity/4; |  | 
| 271     if(room>start) { |  | 
| 272         /* move array contents to make room */ |  | 
| 273         moveContentsTowardEnd(api, uni->chars, uni->states, room); |  | 
| 274         api->index=start=api->start; |  | 
| 275         uni->hasNext=TRUE; |  | 
| 276     } |  | 
| 277 |  | 
| 278     /* normalize ending at the start position */ |  | 
| 279     errorCode=U_ZERO_ERROR; |  | 
| 280     if(uni->state!=uni->states[start]) { |  | 
| 281         uiter_setState(iter, uni->states[start], &errorCode); |  | 
| 282         if(U_FAILURE(errorCode)) { |  | 
| 283             uni->state=UITER_NO_STATE; |  | 
| 284             uni->hasPrevious=FALSE; |  | 
| 285             return FALSE; |  | 
| 286         } |  | 
| 287     } |  | 
| 288 |  | 
| 289     room=unorm_previous(iter, uni->chars, start, uni->mode, 0, TRUE, NULL, &erro
     rCode); |  | 
| 290     if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |  | 
| 291         if(room<=capacity) { |  | 
| 292             /* empty and re-use the arrays */ |  | 
| 293             uni->states[capacity]=uni->states[start]; |  | 
| 294             api->start=api->index=api->limit=start=capacity; |  | 
| 295             uni->hasNext=TRUE; |  | 
| 296         } else { |  | 
| 297             capacity+=room+100; |  | 
| 298             if(!reallocArrays(uni, capacity, TRUE)) { |  | 
| 299                 uni->state=UITER_NO_STATE; |  | 
| 300                 uni->hasPrevious=FALSE; |  | 
| 301                 return FALSE; |  | 
| 302             } |  | 
| 303             start=api->start; |  | 
| 304         } |  | 
| 305 |  | 
| 306         errorCode=U_ZERO_ERROR; |  | 
| 307         uiter_setState(iter, uni->states[start], &errorCode); |  | 
| 308         room=unorm_previous(iter, uni->chars, start, uni->mode, 0, TRUE, NULL, &
     errorCode); |  | 
| 309     } |  | 
| 310     if(U_FAILURE(errorCode) || room==0) { |  | 
| 311         uni->state=UITER_NO_STATE; |  | 
| 312         uni->hasPrevious=FALSE; |  | 
| 313         return FALSE; |  | 
| 314     } |  | 
| 315 |  | 
| 316     /* room>0 */ |  | 
| 317     do { |  | 
| 318         /* copy the UChars from chars[0..room[ to chars[(start-room)..start[ */ |  | 
| 319         uni->chars[--start]=uni->chars[--room]; |  | 
| 320         /* set unknown states for all but the normalization boundaries */ |  | 
| 321         uni->states[start]=UITER_NO_STATE; |  | 
| 322     } while(room>0); |  | 
| 323     uni->states[start]=uni->state=uiter_getState(iter); |  | 
| 324     uni->hasPrevious=iter->hasPrevious(iter); |  | 
| 325     api->start=start; |  | 
| 326     return TRUE; |  | 
| 327 } |  | 
| 328 |  | 
| 329 /* Iterator runtime API functions ------------------------------------------- */ |  | 
| 330 |  | 
| 331 static int32_t U_CALLCONV |  | 
| 332 unormIteratorGetIndex(UCharIterator *api, UCharIteratorOrigin origin) { |  | 
| 333     switch(origin) { |  | 
| 334     case UITER_ZERO: |  | 
| 335     case UITER_START: |  | 
| 336         return 0; |  | 
| 337     case UITER_CURRENT: |  | 
| 338     case UITER_LIMIT: |  | 
| 339     case UITER_LENGTH: |  | 
| 340         return UITER_UNKNOWN_INDEX; |  | 
| 341     default: |  | 
| 342         /* not a valid origin */ |  | 
| 343         /* Should never get here! */ |  | 
| 344         return -1; |  | 
| 345     } |  | 
| 346 } |  | 
| 347 |  | 
| 348 static int32_t U_CALLCONV |  | 
| 349 unormIteratorMove(UCharIterator *api, int32_t delta, UCharIteratorOrigin origin)
      { |  | 
| 350     UNormIterator *uni=(UNormIterator *)api; |  | 
| 351     UCharIterator *iter=uni->iter; |  | 
| 352     int32_t pos; |  | 
| 353 |  | 
| 354     switch(origin) { |  | 
| 355     case UITER_ZERO: |  | 
| 356     case UITER_START: |  | 
| 357         /* restart from the beginning */ |  | 
| 358         if(uni->hasPrevious) { |  | 
| 359             iter->move(iter, 0, UITER_START); |  | 
| 360             api->start=api->index=api->limit=0; |  | 
| 361             uni->states[api->limit]=uni->state=uiter_getState(iter); |  | 
| 362             uni->hasPrevious=FALSE; |  | 
| 363             uni->hasNext=iter->hasNext(iter); |  | 
| 364         } else { |  | 
| 365             /* we already have the beginning of the normalized text */ |  | 
| 366             api->index=api->start; |  | 
| 367         } |  | 
| 368         break; |  | 
| 369     case UITER_CURRENT: |  | 
| 370         break; |  | 
| 371     case UITER_LIMIT: |  | 
| 372     case UITER_LENGTH: |  | 
| 373         /* restart from the end */ |  | 
| 374         if(uni->hasNext) { |  | 
| 375             iter->move(iter, 0, UITER_LIMIT); |  | 
| 376             api->start=api->index=api->limit=uni->capacity; |  | 
| 377             uni->states[api->limit]=uni->state=uiter_getState(iter); |  | 
| 378             uni->hasPrevious=iter->hasPrevious(iter); |  | 
| 379             uni->hasNext=FALSE; |  | 
| 380         } else { |  | 
| 381             /* we already have the end of the normalized text */ |  | 
| 382             api->index=api->limit; |  | 
| 383         } |  | 
| 384         break; |  | 
| 385     default: |  | 
| 386         return -1;  /* Error */ |  | 
| 387     } |  | 
| 388 |  | 
| 389     /* move relative to the current position by delta normalized UChars */ |  | 
| 390     if(delta==0) { |  | 
| 391         /* nothing to do */ |  | 
| 392     } else if(delta>0) { |  | 
| 393         /* go forward until the requested position is in the buffer */ |  | 
| 394         for(;;) { |  | 
| 395             pos=api->index+delta;   /* requested position */ |  | 
| 396             delta=pos-api->limit;   /* remainder beyond buffered text */ |  | 
| 397             if(delta<=0) { |  | 
| 398                 api->index=pos;     /* position reached */ |  | 
| 399                 break; |  | 
| 400             } |  | 
| 401 |  | 
| 402             /* go to end of buffer and normalize further */ |  | 
| 403             api->index=api->limit; |  | 
| 404             if(!uni->hasNext || !readNext(uni, iter)) { |  | 
| 405                 break;              /* reached end of text */ |  | 
| 406             } |  | 
| 407         } |  | 
| 408     } else /* delta<0 */ { |  | 
| 409         /* go backward until the requested position is in the buffer */ |  | 
| 410         for(;;) { |  | 
| 411             pos=api->index+delta;   /* requested position */ |  | 
| 412             delta=pos-api->start;   /* remainder beyond buffered text */ |  | 
| 413             if(delta>=0) { |  | 
| 414                 api->index=pos;     /* position reached */ |  | 
| 415                 break; |  | 
| 416             } |  | 
| 417 |  | 
| 418             /* go to start of buffer and normalize further */ |  | 
| 419             api->index=api->start; |  | 
| 420             if(!uni->hasPrevious || !readPrevious(uni, iter)) { |  | 
| 421                 break;              /* reached start of text */ |  | 
| 422             } |  | 
| 423         } |  | 
| 424     } |  | 
| 425 |  | 
| 426     if(api->index==api->start && !uni->hasPrevious) { |  | 
| 427         return 0; |  | 
| 428     } else { |  | 
| 429         return UITER_UNKNOWN_INDEX; |  | 
| 430     } |  | 
| 431 } |  | 
| 432 |  | 
| 433 static UBool U_CALLCONV |  | 
| 434 unormIteratorHasNext(UCharIterator *api) { |  | 
| 435     return api->index<api->limit || ((UNormIterator *)api)->hasNext; |  | 
| 436 } |  | 
| 437 |  | 
| 438 static UBool U_CALLCONV |  | 
| 439 unormIteratorHasPrevious(UCharIterator *api) { |  | 
| 440     return api->index>api->start || ((UNormIterator *)api)->hasPrevious; |  | 
| 441 } |  | 
| 442 |  | 
| 443 static UChar32 U_CALLCONV |  | 
| 444 unormIteratorCurrent(UCharIterator *api) { |  | 
| 445     UNormIterator *uni=(UNormIterator *)api; |  | 
| 446 |  | 
| 447     if( api->index<api->limit || |  | 
| 448         (uni->hasNext && readNext(uni, uni->iter)) |  | 
| 449     ) { |  | 
| 450         return uni->chars[api->index]; |  | 
| 451     } else { |  | 
| 452         return U_SENTINEL; |  | 
| 453     } |  | 
| 454 } |  | 
| 455 |  | 
| 456 static UChar32 U_CALLCONV |  | 
| 457 unormIteratorNext(UCharIterator *api) { |  | 
| 458     UNormIterator *uni=(UNormIterator *)api; |  | 
| 459 |  | 
| 460     if( api->index<api->limit || |  | 
| 461         (uni->hasNext && readNext(uni, uni->iter)) |  | 
| 462     ) { |  | 
| 463         return uni->chars[api->index++]; |  | 
| 464     } else { |  | 
| 465         return U_SENTINEL; |  | 
| 466     } |  | 
| 467 } |  | 
| 468 |  | 
| 469 static UChar32 U_CALLCONV |  | 
| 470 unormIteratorPrevious(UCharIterator *api) { |  | 
| 471     UNormIterator *uni=(UNormIterator *)api; |  | 
| 472 |  | 
| 473     if( api->index>api->start || |  | 
| 474         (uni->hasPrevious && readPrevious(uni, uni->iter)) |  | 
| 475     ) { |  | 
| 476         return uni->chars[--api->index]; |  | 
| 477     } else { |  | 
| 478         return U_SENTINEL; |  | 
| 479     } |  | 
| 480 } |  | 
| 481 |  | 
| 482 static uint32_t U_CALLCONV |  | 
| 483 unormIteratorGetState(const UCharIterator *api) { |  | 
| 484     /* not uni->state because that may not be at api->index */ |  | 
| 485     return ((UNormIterator *)api)->states[api->index]; |  | 
| 486 } |  | 
| 487 |  | 
| 488 static void U_CALLCONV |  | 
| 489 unormIteratorSetState(UCharIterator *api, uint32_t state, UErrorCode *pErrorCode
     ) { |  | 
| 490     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { |  | 
| 491         /* do nothing */ |  | 
| 492     } else if(api==NULL) { |  | 
| 493         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |  | 
| 494     } else if(state==UITER_NO_STATE) { |  | 
| 495         *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; |  | 
| 496     } else { |  | 
| 497         UNormIterator *uni=(UNormIterator *)api; |  | 
| 498         UCharIterator *iter=((UNormIterator *)api)->iter; |  | 
| 499         if(state!=uni->state) { |  | 
| 500             uni->state=state; |  | 
| 501             uiter_setState(iter, state, pErrorCode); |  | 
| 502         } |  | 
| 503 |  | 
| 504         /* |  | 
| 505          * Try shortcuts: If the requested state is in the array contents |  | 
| 506          * then just set the index there. |  | 
| 507          * |  | 
| 508          * We assume that the state is unique per position! |  | 
| 509          */ |  | 
| 510         if(state==uni->states[api->index]) { |  | 
| 511             return; |  | 
| 512         } else if(state==uni->states[api->limit]) { |  | 
| 513             api->index=api->limit; |  | 
| 514             return; |  | 
| 515         } else { |  | 
| 516             /* search for the index with this state */ |  | 
| 517             int32_t i; |  | 
| 518 |  | 
| 519             for(i=api->start; i<api->limit; ++i) { |  | 
| 520                 if(state==uni->states[i]) { |  | 
| 521                     api->index=i; |  | 
| 522                     return; |  | 
| 523                 } |  | 
| 524             } |  | 
| 525         } |  | 
| 526 |  | 
| 527         /* there is no array index for this state, reset for fresh contents */ |  | 
| 528         initIndexes((UNormIterator *)api, iter); |  | 
| 529         uni->states[api->limit]=state; |  | 
| 530     } |  | 
| 531 } |  | 
| 532 |  | 
| 533 static const UCharIterator unormIterator={ |  | 
| 534     NULL, 0, 0, 0, 0, 0, |  | 
| 535     unormIteratorGetIndex, |  | 
| 536     unormIteratorMove, |  | 
| 537     unormIteratorHasNext, |  | 
| 538     unormIteratorHasPrevious, |  | 
| 539     unormIteratorCurrent, |  | 
| 540     unormIteratorNext, |  | 
| 541     unormIteratorPrevious, |  | 
| 542     NULL, |  | 
| 543     unormIteratorGetState, |  | 
| 544     unormIteratorSetState |  | 
| 545 }; |  | 
| 546 |  | 
| 547 /* Setup functions ---------------------------------------------------------- */ |  | 
| 548 |  | 
| 549 U_CAPI UNormIterator * U_EXPORT2 |  | 
| 550 unorm_openIter(void *stackMem, int32_t stackMemSize, UErrorCode *pErrorCode) { |  | 
| 551     UNormIterator *uni; |  | 
| 552 |  | 
| 553     /* argument checking */ |  | 
| 554     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { |  | 
| 555         return NULL; |  | 
| 556     } |  | 
| 557 |  | 
| 558     /* allocate */ |  | 
| 559     uni=NULL; |  | 
| 560     if(stackMem!=NULL && stackMemSize>=sizeof(UNormIterator)) { |  | 
| 561         if(U_ALIGNMENT_OFFSET(stackMem)==0) { |  | 
| 562             /* already aligned */ |  | 
| 563             uni=(UNormIterator *)stackMem; |  | 
| 564         } else { |  | 
| 565             int32_t align=(int32_t)U_ALIGNMENT_OFFSET_UP(stackMem); |  | 
| 566             if((stackMemSize-=align)>=(int32_t)sizeof(UNormIterator)) { |  | 
| 567                 /* needs alignment */ |  | 
| 568                 uni=(UNormIterator *)((char *)stackMem+align); |  | 
| 569             } |  | 
| 570         } |  | 
| 571         /* else does not fit */ |  | 
| 572     } |  | 
| 573 |  | 
| 574     if(uni!=NULL) { |  | 
| 575         uni->isStackAllocated=TRUE; |  | 
| 576     } else { |  | 
| 577         uni=(UNormIterator *)uprv_malloc(sizeof(UNormIterator)); |  | 
| 578         if(uni==NULL) { |  | 
| 579             *pErrorCode=U_MEMORY_ALLOCATION_ERROR; |  | 
| 580             return NULL; |  | 
| 581         } |  | 
| 582         uni->isStackAllocated=FALSE; |  | 
| 583     } |  | 
| 584 |  | 
| 585     /* |  | 
| 586      * initialize |  | 
| 587      * do not memset because that would unnecessarily initialize the arrays |  | 
| 588      */ |  | 
| 589     uni->iter=NULL; |  | 
| 590     uni->chars=uni->charsBuffer; |  | 
| 591     uni->states=uni->statesBuffer; |  | 
| 592     uni->capacity=INITIAL_CAPACITY; |  | 
| 593     uni->state=UITER_NO_STATE; |  | 
| 594     uni->hasPrevious=uni->hasNext=FALSE; |  | 
| 595     uni->mode=UNORM_NONE; |  | 
| 596 |  | 
| 597     /* set a no-op iterator into the api */ |  | 
| 598     uiter_setString(&uni->api, NULL, 0); |  | 
| 599     return uni; |  | 
| 600 } |  | 
| 601 |  | 
| 602 U_CAPI void U_EXPORT2 |  | 
| 603 unorm_closeIter(UNormIterator *uni) { |  | 
| 604     if(uni!=NULL) { |  | 
| 605         if(uni->states!=uni->statesBuffer) { |  | 
| 606             /* chars and states are allocated in the same memory block */ |  | 
| 607             uprv_free(uni->states); |  | 
| 608         } |  | 
| 609         if(!uni->isStackAllocated) { |  | 
| 610             uprv_free(uni); |  | 
| 611         } |  | 
| 612     } |  | 
| 613 } |  | 
| 614 |  | 
| 615 U_CAPI UCharIterator * U_EXPORT2 |  | 
| 616 unorm_setIter(UNormIterator *uni, UCharIterator *iter, UNormalizationMode mode, 
     UErrorCode *pErrorCode) { |  | 
| 617     /* argument checking */ |  | 
| 618     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { |  | 
| 619         return NULL; |  | 
| 620     } |  | 
| 621     if(uni==NULL) { |  | 
| 622         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |  | 
| 623         return NULL; |  | 
| 624     } |  | 
| 625     if( iter==NULL || iter->getState==NULL || iter->setState==NULL || |  | 
| 626         mode<UNORM_NONE || UNORM_MODE_COUNT<=mode |  | 
| 627     ) { |  | 
| 628         /* set a no-op iterator into the api */ |  | 
| 629         uiter_setString(&uni->api, NULL, 0); |  | 
| 630         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |  | 
| 631         return NULL; |  | 
| 632     } |  | 
| 633 |  | 
| 634     /* set the iterator and initialize */ |  | 
| 635     uprv_memcpy(&uni->api, &unormIterator, sizeof(unormIterator)); |  | 
| 636 |  | 
| 637     uni->iter=iter; |  | 
| 638     uni->mode=mode; |  | 
| 639 |  | 
| 640     initIndexes(uni, iter); |  | 
| 641     uni->states[uni->api.limit]=uni->state=uiter_getState(iter); |  | 
| 642 |  | 
| 643     return &uni->api; |  | 
| 644 } |  | 
| 645 |  | 
| 646 #endif /* uconfig.h switches */ |  | 
| OLD | NEW | 
|---|