| 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 |