intl/icu/source/common/uiter.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 *******************************************************************************
michael@0 3 *
michael@0 4 * Copyright (C) 2002-2012, International Business Machines
michael@0 5 * Corporation and others. All Rights Reserved.
michael@0 6 *
michael@0 7 *******************************************************************************
michael@0 8 * file name: uiter.cpp
michael@0 9 * encoding: US-ASCII
michael@0 10 * tab size: 8 (not used)
michael@0 11 * indentation:4
michael@0 12 *
michael@0 13 * created on: 2002jan18
michael@0 14 * created by: Markus W. Scherer
michael@0 15 */
michael@0 16
michael@0 17 #include "unicode/utypes.h"
michael@0 18 #include "unicode/ustring.h"
michael@0 19 #include "unicode/chariter.h"
michael@0 20 #include "unicode/rep.h"
michael@0 21 #include "unicode/uiter.h"
michael@0 22 #include "unicode/utf.h"
michael@0 23 #include "unicode/utf8.h"
michael@0 24 #include "unicode/utf16.h"
michael@0 25 #include "cstring.h"
michael@0 26
michael@0 27 U_NAMESPACE_USE
michael@0 28
michael@0 29 #define IS_EVEN(n) (((n)&1)==0)
michael@0 30 #define IS_POINTER_EVEN(p) IS_EVEN((size_t)p)
michael@0 31
michael@0 32 U_CDECL_BEGIN
michael@0 33
michael@0 34 /* No-Op UCharIterator implementation for illegal input --------------------- */
michael@0 35
michael@0 36 static int32_t U_CALLCONV
michael@0 37 noopGetIndex(UCharIterator * /*iter*/, UCharIteratorOrigin /*origin*/) {
michael@0 38 return 0;
michael@0 39 }
michael@0 40
michael@0 41 static int32_t U_CALLCONV
michael@0 42 noopMove(UCharIterator * /*iter*/, int32_t /*delta*/, UCharIteratorOrigin /*origin*/) {
michael@0 43 return 0;
michael@0 44 }
michael@0 45
michael@0 46 static UBool U_CALLCONV
michael@0 47 noopHasNext(UCharIterator * /*iter*/) {
michael@0 48 return FALSE;
michael@0 49 }
michael@0 50
michael@0 51 static UChar32 U_CALLCONV
michael@0 52 noopCurrent(UCharIterator * /*iter*/) {
michael@0 53 return U_SENTINEL;
michael@0 54 }
michael@0 55
michael@0 56 static uint32_t U_CALLCONV
michael@0 57 noopGetState(const UCharIterator * /*iter*/) {
michael@0 58 return UITER_NO_STATE;
michael@0 59 }
michael@0 60
michael@0 61 static void U_CALLCONV
michael@0 62 noopSetState(UCharIterator * /*iter*/, uint32_t /*state*/, UErrorCode *pErrorCode) {
michael@0 63 *pErrorCode=U_UNSUPPORTED_ERROR;
michael@0 64 }
michael@0 65
michael@0 66 static const UCharIterator noopIterator={
michael@0 67 0, 0, 0, 0, 0, 0,
michael@0 68 noopGetIndex,
michael@0 69 noopMove,
michael@0 70 noopHasNext,
michael@0 71 noopHasNext,
michael@0 72 noopCurrent,
michael@0 73 noopCurrent,
michael@0 74 noopCurrent,
michael@0 75 NULL,
michael@0 76 noopGetState,
michael@0 77 noopSetState
michael@0 78 };
michael@0 79
michael@0 80 /* UCharIterator implementation for simple strings -------------------------- */
michael@0 81
michael@0 82 /*
michael@0 83 * This is an implementation of a code unit (UChar) iterator
michael@0 84 * for UChar * strings.
michael@0 85 *
michael@0 86 * The UCharIterator.context field holds a pointer to the string.
michael@0 87 */
michael@0 88
michael@0 89 static int32_t U_CALLCONV
michael@0 90 stringIteratorGetIndex(UCharIterator *iter, UCharIteratorOrigin origin) {
michael@0 91 switch(origin) {
michael@0 92 case UITER_ZERO:
michael@0 93 return 0;
michael@0 94 case UITER_START:
michael@0 95 return iter->start;
michael@0 96 case UITER_CURRENT:
michael@0 97 return iter->index;
michael@0 98 case UITER_LIMIT:
michael@0 99 return iter->limit;
michael@0 100 case UITER_LENGTH:
michael@0 101 return iter->length;
michael@0 102 default:
michael@0 103 /* not a valid origin */
michael@0 104 /* Should never get here! */
michael@0 105 return -1;
michael@0 106 }
michael@0 107 }
michael@0 108
michael@0 109 static int32_t U_CALLCONV
michael@0 110 stringIteratorMove(UCharIterator *iter, int32_t delta, UCharIteratorOrigin origin) {
michael@0 111 int32_t pos;
michael@0 112
michael@0 113 switch(origin) {
michael@0 114 case UITER_ZERO:
michael@0 115 pos=delta;
michael@0 116 break;
michael@0 117 case UITER_START:
michael@0 118 pos=iter->start+delta;
michael@0 119 break;
michael@0 120 case UITER_CURRENT:
michael@0 121 pos=iter->index+delta;
michael@0 122 break;
michael@0 123 case UITER_LIMIT:
michael@0 124 pos=iter->limit+delta;
michael@0 125 break;
michael@0 126 case UITER_LENGTH:
michael@0 127 pos=iter->length+delta;
michael@0 128 break;
michael@0 129 default:
michael@0 130 return -1; /* Error */
michael@0 131 }
michael@0 132
michael@0 133 if(pos<iter->start) {
michael@0 134 pos=iter->start;
michael@0 135 } else if(pos>iter->limit) {
michael@0 136 pos=iter->limit;
michael@0 137 }
michael@0 138
michael@0 139 return iter->index=pos;
michael@0 140 }
michael@0 141
michael@0 142 static UBool U_CALLCONV
michael@0 143 stringIteratorHasNext(UCharIterator *iter) {
michael@0 144 return iter->index<iter->limit;
michael@0 145 }
michael@0 146
michael@0 147 static UBool U_CALLCONV
michael@0 148 stringIteratorHasPrevious(UCharIterator *iter) {
michael@0 149 return iter->index>iter->start;
michael@0 150 }
michael@0 151
michael@0 152 static UChar32 U_CALLCONV
michael@0 153 stringIteratorCurrent(UCharIterator *iter) {
michael@0 154 if(iter->index<iter->limit) {
michael@0 155 return ((const UChar *)(iter->context))[iter->index];
michael@0 156 } else {
michael@0 157 return U_SENTINEL;
michael@0 158 }
michael@0 159 }
michael@0 160
michael@0 161 static UChar32 U_CALLCONV
michael@0 162 stringIteratorNext(UCharIterator *iter) {
michael@0 163 if(iter->index<iter->limit) {
michael@0 164 return ((const UChar *)(iter->context))[iter->index++];
michael@0 165 } else {
michael@0 166 return U_SENTINEL;
michael@0 167 }
michael@0 168 }
michael@0 169
michael@0 170 static UChar32 U_CALLCONV
michael@0 171 stringIteratorPrevious(UCharIterator *iter) {
michael@0 172 if(iter->index>iter->start) {
michael@0 173 return ((const UChar *)(iter->context))[--iter->index];
michael@0 174 } else {
michael@0 175 return U_SENTINEL;
michael@0 176 }
michael@0 177 }
michael@0 178
michael@0 179 static uint32_t U_CALLCONV
michael@0 180 stringIteratorGetState(const UCharIterator *iter) {
michael@0 181 return (uint32_t)iter->index;
michael@0 182 }
michael@0 183
michael@0 184 static void U_CALLCONV
michael@0 185 stringIteratorSetState(UCharIterator *iter, uint32_t state, UErrorCode *pErrorCode) {
michael@0 186 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
michael@0 187 /* do nothing */
michael@0 188 } else if(iter==NULL) {
michael@0 189 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 190 } else if((int32_t)state<iter->start || iter->limit<(int32_t)state) {
michael@0 191 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
michael@0 192 } else {
michael@0 193 iter->index=(int32_t)state;
michael@0 194 }
michael@0 195 }
michael@0 196
michael@0 197 static const UCharIterator stringIterator={
michael@0 198 0, 0, 0, 0, 0, 0,
michael@0 199 stringIteratorGetIndex,
michael@0 200 stringIteratorMove,
michael@0 201 stringIteratorHasNext,
michael@0 202 stringIteratorHasPrevious,
michael@0 203 stringIteratorCurrent,
michael@0 204 stringIteratorNext,
michael@0 205 stringIteratorPrevious,
michael@0 206 NULL,
michael@0 207 stringIteratorGetState,
michael@0 208 stringIteratorSetState
michael@0 209 };
michael@0 210
michael@0 211 U_CAPI void U_EXPORT2
michael@0 212 uiter_setString(UCharIterator *iter, const UChar *s, int32_t length) {
michael@0 213 if(iter!=0) {
michael@0 214 if(s!=0 && length>=-1) {
michael@0 215 *iter=stringIterator;
michael@0 216 iter->context=s;
michael@0 217 if(length>=0) {
michael@0 218 iter->length=length;
michael@0 219 } else {
michael@0 220 iter->length=u_strlen(s);
michael@0 221 }
michael@0 222 iter->limit=iter->length;
michael@0 223 } else {
michael@0 224 *iter=noopIterator;
michael@0 225 }
michael@0 226 }
michael@0 227 }
michael@0 228
michael@0 229 /* UCharIterator implementation for UTF-16BE strings ------------------------ */
michael@0 230
michael@0 231 /*
michael@0 232 * This is an implementation of a code unit (UChar) iterator
michael@0 233 * for UTF-16BE strings, i.e., strings in byte-vectors where
michael@0 234 * each UChar is stored as a big-endian pair of bytes.
michael@0 235 *
michael@0 236 * The UCharIterator.context field holds a pointer to the string.
michael@0 237 * Everything works just like with a normal UChar iterator (uiter_setString),
michael@0 238 * except that UChars are assembled from byte pairs.
michael@0 239 */
michael@0 240
michael@0 241 /* internal helper function */
michael@0 242 static inline UChar32
michael@0 243 utf16BEIteratorGet(UCharIterator *iter, int32_t index) {
michael@0 244 const uint8_t *p=(const uint8_t *)iter->context;
michael@0 245 return ((UChar)p[2*index]<<8)|(UChar)p[2*index+1];
michael@0 246 }
michael@0 247
michael@0 248 static UChar32 U_CALLCONV
michael@0 249 utf16BEIteratorCurrent(UCharIterator *iter) {
michael@0 250 int32_t index;
michael@0 251
michael@0 252 if((index=iter->index)<iter->limit) {
michael@0 253 return utf16BEIteratorGet(iter, index);
michael@0 254 } else {
michael@0 255 return U_SENTINEL;
michael@0 256 }
michael@0 257 }
michael@0 258
michael@0 259 static UChar32 U_CALLCONV
michael@0 260 utf16BEIteratorNext(UCharIterator *iter) {
michael@0 261 int32_t index;
michael@0 262
michael@0 263 if((index=iter->index)<iter->limit) {
michael@0 264 iter->index=index+1;
michael@0 265 return utf16BEIteratorGet(iter, index);
michael@0 266 } else {
michael@0 267 return U_SENTINEL;
michael@0 268 }
michael@0 269 }
michael@0 270
michael@0 271 static UChar32 U_CALLCONV
michael@0 272 utf16BEIteratorPrevious(UCharIterator *iter) {
michael@0 273 int32_t index;
michael@0 274
michael@0 275 if((index=iter->index)>iter->start) {
michael@0 276 iter->index=--index;
michael@0 277 return utf16BEIteratorGet(iter, index);
michael@0 278 } else {
michael@0 279 return U_SENTINEL;
michael@0 280 }
michael@0 281 }
michael@0 282
michael@0 283 static const UCharIterator utf16BEIterator={
michael@0 284 0, 0, 0, 0, 0, 0,
michael@0 285 stringIteratorGetIndex,
michael@0 286 stringIteratorMove,
michael@0 287 stringIteratorHasNext,
michael@0 288 stringIteratorHasPrevious,
michael@0 289 utf16BEIteratorCurrent,
michael@0 290 utf16BEIteratorNext,
michael@0 291 utf16BEIteratorPrevious,
michael@0 292 NULL,
michael@0 293 stringIteratorGetState,
michael@0 294 stringIteratorSetState
michael@0 295 };
michael@0 296
michael@0 297 /*
michael@0 298 * Count the number of UChars in a UTF-16BE string before a terminating UChar NUL,
michael@0 299 * i.e., before a pair of 0 bytes where the first 0 byte is at an even
michael@0 300 * offset from s.
michael@0 301 */
michael@0 302 static int32_t
michael@0 303 utf16BE_strlen(const char *s) {
michael@0 304 if(IS_POINTER_EVEN(s)) {
michael@0 305 /*
michael@0 306 * even-aligned, call u_strlen(s)
michael@0 307 * we are probably on a little-endian machine, but searching for UChar NUL
michael@0 308 * does not care about endianness
michael@0 309 */
michael@0 310 return u_strlen((const UChar *)s);
michael@0 311 } else {
michael@0 312 /* odd-aligned, search for pair of 0 bytes */
michael@0 313 const char *p=s;
michael@0 314
michael@0 315 while(!(*p==0 && p[1]==0)) {
michael@0 316 p+=2;
michael@0 317 }
michael@0 318 return (int32_t)((p-s)/2);
michael@0 319 }
michael@0 320 }
michael@0 321
michael@0 322 U_CAPI void U_EXPORT2
michael@0 323 uiter_setUTF16BE(UCharIterator *iter, const char *s, int32_t length) {
michael@0 324 if(iter!=NULL) {
michael@0 325 /* allow only even-length strings (the input length counts bytes) */
michael@0 326 if(s!=NULL && (length==-1 || (length>=0 && IS_EVEN(length)))) {
michael@0 327 /* length/=2, except that >>=1 also works for -1 (-1/2==0, -1>>1==-1) */
michael@0 328 length>>=1;
michael@0 329
michael@0 330 if(U_IS_BIG_ENDIAN && IS_POINTER_EVEN(s)) {
michael@0 331 /* big-endian machine and 2-aligned UTF-16BE string: use normal UChar iterator */
michael@0 332 uiter_setString(iter, (const UChar *)s, length);
michael@0 333 return;
michael@0 334 }
michael@0 335
michael@0 336 *iter=utf16BEIterator;
michael@0 337 iter->context=s;
michael@0 338 if(length>=0) {
michael@0 339 iter->length=length;
michael@0 340 } else {
michael@0 341 iter->length=utf16BE_strlen(s);
michael@0 342 }
michael@0 343 iter->limit=iter->length;
michael@0 344 } else {
michael@0 345 *iter=noopIterator;
michael@0 346 }
michael@0 347 }
michael@0 348 }
michael@0 349
michael@0 350 /* UCharIterator wrapper around CharacterIterator --------------------------- */
michael@0 351
michael@0 352 /*
michael@0 353 * This is wrapper code around a C++ CharacterIterator to
michael@0 354 * look like a C UCharIterator.
michael@0 355 *
michael@0 356 * The UCharIterator.context field holds a pointer to the CharacterIterator.
michael@0 357 */
michael@0 358
michael@0 359 static int32_t U_CALLCONV
michael@0 360 characterIteratorGetIndex(UCharIterator *iter, UCharIteratorOrigin origin) {
michael@0 361 switch(origin) {
michael@0 362 case UITER_ZERO:
michael@0 363 return 0;
michael@0 364 case UITER_START:
michael@0 365 return ((CharacterIterator *)(iter->context))->startIndex();
michael@0 366 case UITER_CURRENT:
michael@0 367 return ((CharacterIterator *)(iter->context))->getIndex();
michael@0 368 case UITER_LIMIT:
michael@0 369 return ((CharacterIterator *)(iter->context))->endIndex();
michael@0 370 case UITER_LENGTH:
michael@0 371 return ((CharacterIterator *)(iter->context))->getLength();
michael@0 372 default:
michael@0 373 /* not a valid origin */
michael@0 374 /* Should never get here! */
michael@0 375 return -1;
michael@0 376 }
michael@0 377 }
michael@0 378
michael@0 379 static int32_t U_CALLCONV
michael@0 380 characterIteratorMove(UCharIterator *iter, int32_t delta, UCharIteratorOrigin origin) {
michael@0 381 switch(origin) {
michael@0 382 case UITER_ZERO:
michael@0 383 ((CharacterIterator *)(iter->context))->setIndex(delta);
michael@0 384 return ((CharacterIterator *)(iter->context))->getIndex();
michael@0 385 case UITER_START:
michael@0 386 case UITER_CURRENT:
michael@0 387 case UITER_LIMIT:
michael@0 388 return ((CharacterIterator *)(iter->context))->move(delta, (CharacterIterator::EOrigin)origin);
michael@0 389 case UITER_LENGTH:
michael@0 390 ((CharacterIterator *)(iter->context))->setIndex(((CharacterIterator *)(iter->context))->getLength()+delta);
michael@0 391 return ((CharacterIterator *)(iter->context))->getIndex();
michael@0 392 default:
michael@0 393 /* not a valid origin */
michael@0 394 /* Should never get here! */
michael@0 395 return -1;
michael@0 396 }
michael@0 397 }
michael@0 398
michael@0 399 static UBool U_CALLCONV
michael@0 400 characterIteratorHasNext(UCharIterator *iter) {
michael@0 401 return ((CharacterIterator *)(iter->context))->hasNext();
michael@0 402 }
michael@0 403
michael@0 404 static UBool U_CALLCONV
michael@0 405 characterIteratorHasPrevious(UCharIterator *iter) {
michael@0 406 return ((CharacterIterator *)(iter->context))->hasPrevious();
michael@0 407 }
michael@0 408
michael@0 409 static UChar32 U_CALLCONV
michael@0 410 characterIteratorCurrent(UCharIterator *iter) {
michael@0 411 UChar32 c;
michael@0 412
michael@0 413 c=((CharacterIterator *)(iter->context))->current();
michael@0 414 if(c!=0xffff || ((CharacterIterator *)(iter->context))->hasNext()) {
michael@0 415 return c;
michael@0 416 } else {
michael@0 417 return U_SENTINEL;
michael@0 418 }
michael@0 419 }
michael@0 420
michael@0 421 static UChar32 U_CALLCONV
michael@0 422 characterIteratorNext(UCharIterator *iter) {
michael@0 423 if(((CharacterIterator *)(iter->context))->hasNext()) {
michael@0 424 return ((CharacterIterator *)(iter->context))->nextPostInc();
michael@0 425 } else {
michael@0 426 return U_SENTINEL;
michael@0 427 }
michael@0 428 }
michael@0 429
michael@0 430 static UChar32 U_CALLCONV
michael@0 431 characterIteratorPrevious(UCharIterator *iter) {
michael@0 432 if(((CharacterIterator *)(iter->context))->hasPrevious()) {
michael@0 433 return ((CharacterIterator *)(iter->context))->previous();
michael@0 434 } else {
michael@0 435 return U_SENTINEL;
michael@0 436 }
michael@0 437 }
michael@0 438
michael@0 439 static uint32_t U_CALLCONV
michael@0 440 characterIteratorGetState(const UCharIterator *iter) {
michael@0 441 return ((CharacterIterator *)(iter->context))->getIndex();
michael@0 442 }
michael@0 443
michael@0 444 static void U_CALLCONV
michael@0 445 characterIteratorSetState(UCharIterator *iter, uint32_t state, UErrorCode *pErrorCode) {
michael@0 446 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
michael@0 447 /* do nothing */
michael@0 448 } else if(iter==NULL || iter->context==NULL) {
michael@0 449 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 450 } else if((int32_t)state<((CharacterIterator *)(iter->context))->startIndex() || ((CharacterIterator *)(iter->context))->endIndex()<(int32_t)state) {
michael@0 451 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
michael@0 452 } else {
michael@0 453 ((CharacterIterator *)(iter->context))->setIndex((int32_t)state);
michael@0 454 }
michael@0 455 }
michael@0 456
michael@0 457 static const UCharIterator characterIteratorWrapper={
michael@0 458 0, 0, 0, 0, 0, 0,
michael@0 459 characterIteratorGetIndex,
michael@0 460 characterIteratorMove,
michael@0 461 characterIteratorHasNext,
michael@0 462 characterIteratorHasPrevious,
michael@0 463 characterIteratorCurrent,
michael@0 464 characterIteratorNext,
michael@0 465 characterIteratorPrevious,
michael@0 466 NULL,
michael@0 467 characterIteratorGetState,
michael@0 468 characterIteratorSetState
michael@0 469 };
michael@0 470
michael@0 471 U_CAPI void U_EXPORT2
michael@0 472 uiter_setCharacterIterator(UCharIterator *iter, CharacterIterator *charIter) {
michael@0 473 if(iter!=0) {
michael@0 474 if(charIter!=0) {
michael@0 475 *iter=characterIteratorWrapper;
michael@0 476 iter->context=charIter;
michael@0 477 } else {
michael@0 478 *iter=noopIterator;
michael@0 479 }
michael@0 480 }
michael@0 481 }
michael@0 482
michael@0 483 /* UCharIterator wrapper around Replaceable --------------------------------- */
michael@0 484
michael@0 485 /*
michael@0 486 * This is an implementation of a code unit (UChar) iterator
michael@0 487 * based on a Replaceable object.
michael@0 488 *
michael@0 489 * The UCharIterator.context field holds a pointer to the Replaceable.
michael@0 490 * UCharIterator.length and UCharIterator.index hold Replaceable.length()
michael@0 491 * and the iteration index.
michael@0 492 */
michael@0 493
michael@0 494 static UChar32 U_CALLCONV
michael@0 495 replaceableIteratorCurrent(UCharIterator *iter) {
michael@0 496 if(iter->index<iter->limit) {
michael@0 497 return ((Replaceable *)(iter->context))->charAt(iter->index);
michael@0 498 } else {
michael@0 499 return U_SENTINEL;
michael@0 500 }
michael@0 501 }
michael@0 502
michael@0 503 static UChar32 U_CALLCONV
michael@0 504 replaceableIteratorNext(UCharIterator *iter) {
michael@0 505 if(iter->index<iter->limit) {
michael@0 506 return ((Replaceable *)(iter->context))->charAt(iter->index++);
michael@0 507 } else {
michael@0 508 return U_SENTINEL;
michael@0 509 }
michael@0 510 }
michael@0 511
michael@0 512 static UChar32 U_CALLCONV
michael@0 513 replaceableIteratorPrevious(UCharIterator *iter) {
michael@0 514 if(iter->index>iter->start) {
michael@0 515 return ((Replaceable *)(iter->context))->charAt(--iter->index);
michael@0 516 } else {
michael@0 517 return U_SENTINEL;
michael@0 518 }
michael@0 519 }
michael@0 520
michael@0 521 static const UCharIterator replaceableIterator={
michael@0 522 0, 0, 0, 0, 0, 0,
michael@0 523 stringIteratorGetIndex,
michael@0 524 stringIteratorMove,
michael@0 525 stringIteratorHasNext,
michael@0 526 stringIteratorHasPrevious,
michael@0 527 replaceableIteratorCurrent,
michael@0 528 replaceableIteratorNext,
michael@0 529 replaceableIteratorPrevious,
michael@0 530 NULL,
michael@0 531 stringIteratorGetState,
michael@0 532 stringIteratorSetState
michael@0 533 };
michael@0 534
michael@0 535 U_CAPI void U_EXPORT2
michael@0 536 uiter_setReplaceable(UCharIterator *iter, const Replaceable *rep) {
michael@0 537 if(iter!=0) {
michael@0 538 if(rep!=0) {
michael@0 539 *iter=replaceableIterator;
michael@0 540 iter->context=rep;
michael@0 541 iter->limit=iter->length=rep->length();
michael@0 542 } else {
michael@0 543 *iter=noopIterator;
michael@0 544 }
michael@0 545 }
michael@0 546 }
michael@0 547
michael@0 548 /* UCharIterator implementation for UTF-8 strings --------------------------- */
michael@0 549
michael@0 550 /*
michael@0 551 * Possible, probably necessary only for an implementation for arbitrary
michael@0 552 * converters:
michael@0 553 * Maintain a buffer (ring buffer?) for a piece of converted 16-bit text.
michael@0 554 * This would require to turn reservedFn into a close function and
michael@0 555 * to introduce a uiter_close(iter).
michael@0 556 */
michael@0 557
michael@0 558 #define UITER_CNV_CAPACITY 16
michael@0 559
michael@0 560 /*
michael@0 561 * Minimal implementation:
michael@0 562 * Maintain a single-UChar buffer for an additional surrogate.
michael@0 563 * The caller must not modify start and limit because they are used internally.
michael@0 564 *
michael@0 565 * Use UCharIterator fields as follows:
michael@0 566 * context pointer to UTF-8 string
michael@0 567 * length UTF-16 length of the string; -1 until lazy evaluation
michael@0 568 * start current UTF-8 index
michael@0 569 * index current UTF-16 index; may be -1="unknown" after setState()
michael@0 570 * limit UTF-8 length of the string
michael@0 571 * reservedField supplementary code point
michael@0 572 *
michael@0 573 * Since UCharIterator delivers 16-bit code units, the iteration can be
michael@0 574 * currently in the middle of the byte sequence for a supplementary code point.
michael@0 575 * In this case, reservedField will contain that code point and start will
michael@0 576 * point to after the corresponding byte sequence. The UTF-16 index will be
michael@0 577 * one less than what it would otherwise be corresponding to the UTF-8 index.
michael@0 578 * Otherwise, reservedField will be 0.
michael@0 579 */
michael@0 580
michael@0 581 /*
michael@0 582 * Possible optimization for NUL-terminated UTF-8 and UTF-16 strings:
michael@0 583 * Add implementations that do not call strlen() for iteration but check for NUL.
michael@0 584 */
michael@0 585
michael@0 586 static int32_t U_CALLCONV
michael@0 587 utf8IteratorGetIndex(UCharIterator *iter, UCharIteratorOrigin origin) {
michael@0 588 switch(origin) {
michael@0 589 case UITER_ZERO:
michael@0 590 case UITER_START:
michael@0 591 return 0;
michael@0 592 case UITER_CURRENT:
michael@0 593 if(iter->index<0) {
michael@0 594 /* the current UTF-16 index is unknown after setState(), count from the beginning */
michael@0 595 const uint8_t *s;
michael@0 596 UChar32 c;
michael@0 597 int32_t i, limit, index;
michael@0 598
michael@0 599 s=(const uint8_t *)iter->context;
michael@0 600 i=index=0;
michael@0 601 limit=iter->start; /* count up to the UTF-8 index */
michael@0 602 while(i<limit) {
michael@0 603 U8_NEXT_OR_FFFD(s, i, limit, c);
michael@0 604 index+=U16_LENGTH(c);
michael@0 605 }
michael@0 606
michael@0 607 iter->start=i; /* just in case setState() did not get us to a code point boundary */
michael@0 608 if(i==iter->limit) {
michael@0 609 iter->length=index; /* in case it was <0 or wrong */
michael@0 610 }
michael@0 611 if(iter->reservedField!=0) {
michael@0 612 --index; /* we are in the middle of a supplementary code point */
michael@0 613 }
michael@0 614 iter->index=index;
michael@0 615 }
michael@0 616 return iter->index;
michael@0 617 case UITER_LIMIT:
michael@0 618 case UITER_LENGTH:
michael@0 619 if(iter->length<0) {
michael@0 620 const uint8_t *s;
michael@0 621 UChar32 c;
michael@0 622 int32_t i, limit, length;
michael@0 623
michael@0 624 s=(const uint8_t *)iter->context;
michael@0 625 if(iter->index<0) {
michael@0 626 /*
michael@0 627 * the current UTF-16 index is unknown after setState(),
michael@0 628 * we must first count from the beginning to here
michael@0 629 */
michael@0 630 i=length=0;
michael@0 631 limit=iter->start;
michael@0 632
michael@0 633 /* count from the beginning to the current index */
michael@0 634 while(i<limit) {
michael@0 635 U8_NEXT_OR_FFFD(s, i, limit, c);
michael@0 636 length+=U16_LENGTH(c);
michael@0 637 }
michael@0 638
michael@0 639 /* assume i==limit==iter->start, set the UTF-16 index */
michael@0 640 iter->start=i; /* just in case setState() did not get us to a code point boundary */
michael@0 641 iter->index= iter->reservedField!=0 ? length-1 : length;
michael@0 642 } else {
michael@0 643 i=iter->start;
michael@0 644 length=iter->index;
michael@0 645 if(iter->reservedField!=0) {
michael@0 646 ++length;
michael@0 647 }
michael@0 648 }
michael@0 649
michael@0 650 /* count from the current index to the end */
michael@0 651 limit=iter->limit;
michael@0 652 while(i<limit) {
michael@0 653 U8_NEXT_OR_FFFD(s, i, limit, c);
michael@0 654 length+=U16_LENGTH(c);
michael@0 655 }
michael@0 656 iter->length=length;
michael@0 657 }
michael@0 658 return iter->length;
michael@0 659 default:
michael@0 660 /* not a valid origin */
michael@0 661 /* Should never get here! */
michael@0 662 return -1;
michael@0 663 }
michael@0 664 }
michael@0 665
michael@0 666 static int32_t U_CALLCONV
michael@0 667 utf8IteratorMove(UCharIterator *iter, int32_t delta, UCharIteratorOrigin origin) {
michael@0 668 const uint8_t *s;
michael@0 669 UChar32 c;
michael@0 670 int32_t pos; /* requested UTF-16 index */
michael@0 671 int32_t i; /* UTF-8 index */
michael@0 672 UBool havePos;
michael@0 673
michael@0 674 /* calculate the requested UTF-16 index */
michael@0 675 switch(origin) {
michael@0 676 case UITER_ZERO:
michael@0 677 case UITER_START:
michael@0 678 pos=delta;
michael@0 679 havePos=TRUE;
michael@0 680 /* iter->index<0 (unknown) is possible */
michael@0 681 break;
michael@0 682 case UITER_CURRENT:
michael@0 683 if(iter->index>=0) {
michael@0 684 pos=iter->index+delta;
michael@0 685 havePos=TRUE;
michael@0 686 } else {
michael@0 687 /* the current UTF-16 index is unknown after setState(), use only delta */
michael@0 688 pos=0;
michael@0 689 havePos=FALSE;
michael@0 690 }
michael@0 691 break;
michael@0 692 case UITER_LIMIT:
michael@0 693 case UITER_LENGTH:
michael@0 694 if(iter->length>=0) {
michael@0 695 pos=iter->length+delta;
michael@0 696 havePos=TRUE;
michael@0 697 } else {
michael@0 698 /* pin to the end, avoid counting the length */
michael@0 699 iter->index=-1;
michael@0 700 iter->start=iter->limit;
michael@0 701 iter->reservedField=0;
michael@0 702 if(delta>=0) {
michael@0 703 return UITER_UNKNOWN_INDEX;
michael@0 704 } else {
michael@0 705 /* the current UTF-16 index is unknown, use only delta */
michael@0 706 pos=0;
michael@0 707 havePos=FALSE;
michael@0 708 }
michael@0 709 }
michael@0 710 break;
michael@0 711 default:
michael@0 712 return -1; /* Error */
michael@0 713 }
michael@0 714
michael@0 715 if(havePos) {
michael@0 716 /* shortcuts: pinning to the edges of the string */
michael@0 717 if(pos<=0) {
michael@0 718 iter->index=iter->start=iter->reservedField=0;
michael@0 719 return 0;
michael@0 720 } else if(iter->length>=0 && pos>=iter->length) {
michael@0 721 iter->index=iter->length;
michael@0 722 iter->start=iter->limit;
michael@0 723 iter->reservedField=0;
michael@0 724 return iter->index;
michael@0 725 }
michael@0 726
michael@0 727 /* minimize the number of U8_NEXT/PREV operations */
michael@0 728 if(iter->index<0 || pos<iter->index/2) {
michael@0 729 /* go forward from the start instead of backward from the current index */
michael@0 730 iter->index=iter->start=iter->reservedField=0;
michael@0 731 } else if(iter->length>=0 && (iter->length-pos)<(pos-iter->index)) {
michael@0 732 /*
michael@0 733 * if we have the UTF-16 index and length and the new position is
michael@0 734 * closer to the end than the current index,
michael@0 735 * then go backward from the end instead of forward from the current index
michael@0 736 */
michael@0 737 iter->index=iter->length;
michael@0 738 iter->start=iter->limit;
michael@0 739 iter->reservedField=0;
michael@0 740 }
michael@0 741
michael@0 742 delta=pos-iter->index;
michael@0 743 if(delta==0) {
michael@0 744 return iter->index; /* nothing to do */
michael@0 745 }
michael@0 746 } else {
michael@0 747 /* move relative to unknown UTF-16 index */
michael@0 748 if(delta==0) {
michael@0 749 return UITER_UNKNOWN_INDEX; /* nothing to do */
michael@0 750 } else if(-delta>=iter->start) {
michael@0 751 /* moving backwards by more UChars than there are UTF-8 bytes, pin to 0 */
michael@0 752 iter->index=iter->start=iter->reservedField=0;
michael@0 753 return 0;
michael@0 754 } else if(delta>=(iter->limit-iter->start)) {
michael@0 755 /* moving forward by more UChars than the remaining UTF-8 bytes, pin to the end */
michael@0 756 iter->index=iter->length; /* may or may not be <0 (unknown) */
michael@0 757 iter->start=iter->limit;
michael@0 758 iter->reservedField=0;
michael@0 759 return iter->index>=0 ? iter->index : (int32_t)UITER_UNKNOWN_INDEX;
michael@0 760 }
michael@0 761 }
michael@0 762
michael@0 763 /* delta!=0 */
michael@0 764
michael@0 765 /* move towards the requested position, pin to the edges of the string */
michael@0 766 s=(const uint8_t *)iter->context;
michael@0 767 pos=iter->index; /* could be <0 (unknown) */
michael@0 768 i=iter->start;
michael@0 769 if(delta>0) {
michael@0 770 /* go forward */
michael@0 771 int32_t limit=iter->limit;
michael@0 772 if(iter->reservedField!=0) {
michael@0 773 iter->reservedField=0;
michael@0 774 ++pos;
michael@0 775 --delta;
michael@0 776 }
michael@0 777 while(delta>0 && i<limit) {
michael@0 778 U8_NEXT_OR_FFFD(s, i, limit, c);
michael@0 779 if(c<=0xffff) {
michael@0 780 ++pos;
michael@0 781 --delta;
michael@0 782 } else if(delta>=2) {
michael@0 783 pos+=2;
michael@0 784 delta-=2;
michael@0 785 } else /* delta==1 */ {
michael@0 786 /* stop in the middle of a supplementary code point */
michael@0 787 iter->reservedField=c;
michael@0 788 ++pos;
michael@0 789 break; /* delta=0; */
michael@0 790 }
michael@0 791 }
michael@0 792 if(i==limit) {
michael@0 793 if(iter->length<0 && iter->index>=0) {
michael@0 794 iter->length= iter->reservedField==0 ? pos : pos+1;
michael@0 795 } else if(iter->index<0 && iter->length>=0) {
michael@0 796 iter->index= iter->reservedField==0 ? iter->length : iter->length-1;
michael@0 797 }
michael@0 798 }
michael@0 799 } else /* delta<0 */ {
michael@0 800 /* go backward */
michael@0 801 if(iter->reservedField!=0) {
michael@0 802 iter->reservedField=0;
michael@0 803 i-=4; /* we stayed behind the supplementary code point; go before it now */
michael@0 804 --pos;
michael@0 805 ++delta;
michael@0 806 }
michael@0 807 while(delta<0 && i>0) {
michael@0 808 U8_PREV_OR_FFFD(s, 0, i, c);
michael@0 809 if(c<=0xffff) {
michael@0 810 --pos;
michael@0 811 ++delta;
michael@0 812 } else if(delta<=-2) {
michael@0 813 pos-=2;
michael@0 814 delta+=2;
michael@0 815 } else /* delta==-1 */ {
michael@0 816 /* stop in the middle of a supplementary code point */
michael@0 817 i+=4; /* back to behind this supplementary code point for consistent state */
michael@0 818 iter->reservedField=c;
michael@0 819 --pos;
michael@0 820 break; /* delta=0; */
michael@0 821 }
michael@0 822 }
michael@0 823 }
michael@0 824
michael@0 825 iter->start=i;
michael@0 826 if(iter->index>=0) {
michael@0 827 return iter->index=pos;
michael@0 828 } else {
michael@0 829 /* we started with index<0 (unknown) so pos is bogus */
michael@0 830 if(i<=1) {
michael@0 831 return iter->index=i; /* reached the beginning */
michael@0 832 } else {
michael@0 833 /* we still don't know the UTF-16 index */
michael@0 834 return UITER_UNKNOWN_INDEX;
michael@0 835 }
michael@0 836 }
michael@0 837 }
michael@0 838
michael@0 839 static UBool U_CALLCONV
michael@0 840 utf8IteratorHasNext(UCharIterator *iter) {
michael@0 841 return iter->start<iter->limit || iter->reservedField!=0;
michael@0 842 }
michael@0 843
michael@0 844 static UBool U_CALLCONV
michael@0 845 utf8IteratorHasPrevious(UCharIterator *iter) {
michael@0 846 return iter->start>0;
michael@0 847 }
michael@0 848
michael@0 849 static UChar32 U_CALLCONV
michael@0 850 utf8IteratorCurrent(UCharIterator *iter) {
michael@0 851 if(iter->reservedField!=0) {
michael@0 852 return U16_TRAIL(iter->reservedField);
michael@0 853 } else if(iter->start<iter->limit) {
michael@0 854 const uint8_t *s=(const uint8_t *)iter->context;
michael@0 855 UChar32 c;
michael@0 856 int32_t i=iter->start;
michael@0 857
michael@0 858 U8_NEXT_OR_FFFD(s, i, iter->limit, c);
michael@0 859 if(c<=0xffff) {
michael@0 860 return c;
michael@0 861 } else {
michael@0 862 return U16_LEAD(c);
michael@0 863 }
michael@0 864 } else {
michael@0 865 return U_SENTINEL;
michael@0 866 }
michael@0 867 }
michael@0 868
michael@0 869 static UChar32 U_CALLCONV
michael@0 870 utf8IteratorNext(UCharIterator *iter) {
michael@0 871 int32_t index;
michael@0 872
michael@0 873 if(iter->reservedField!=0) {
michael@0 874 UChar trail=U16_TRAIL(iter->reservedField);
michael@0 875 iter->reservedField=0;
michael@0 876 if((index=iter->index)>=0) {
michael@0 877 iter->index=index+1;
michael@0 878 }
michael@0 879 return trail;
michael@0 880 } else if(iter->start<iter->limit) {
michael@0 881 const uint8_t *s=(const uint8_t *)iter->context;
michael@0 882 UChar32 c;
michael@0 883
michael@0 884 U8_NEXT_OR_FFFD(s, iter->start, iter->limit, c);
michael@0 885 if((index=iter->index)>=0) {
michael@0 886 iter->index=++index;
michael@0 887 if(iter->length<0 && iter->start==iter->limit) {
michael@0 888 iter->length= c<=0xffff ? index : index+1;
michael@0 889 }
michael@0 890 } else if(iter->start==iter->limit && iter->length>=0) {
michael@0 891 iter->index= c<=0xffff ? iter->length : iter->length-1;
michael@0 892 }
michael@0 893 if(c<=0xffff) {
michael@0 894 return c;
michael@0 895 } else {
michael@0 896 iter->reservedField=c;
michael@0 897 return U16_LEAD(c);
michael@0 898 }
michael@0 899 } else {
michael@0 900 return U_SENTINEL;
michael@0 901 }
michael@0 902 }
michael@0 903
michael@0 904 static UChar32 U_CALLCONV
michael@0 905 utf8IteratorPrevious(UCharIterator *iter) {
michael@0 906 int32_t index;
michael@0 907
michael@0 908 if(iter->reservedField!=0) {
michael@0 909 UChar lead=U16_LEAD(iter->reservedField);
michael@0 910 iter->reservedField=0;
michael@0 911 iter->start-=4; /* we stayed behind the supplementary code point; go before it now */
michael@0 912 if((index=iter->index)>0) {
michael@0 913 iter->index=index-1;
michael@0 914 }
michael@0 915 return lead;
michael@0 916 } else if(iter->start>0) {
michael@0 917 const uint8_t *s=(const uint8_t *)iter->context;
michael@0 918 UChar32 c;
michael@0 919
michael@0 920 U8_PREV_OR_FFFD(s, 0, iter->start, c);
michael@0 921 if((index=iter->index)>0) {
michael@0 922 iter->index=index-1;
michael@0 923 } else if(iter->start<=1) {
michael@0 924 iter->index= c<=0xffff ? iter->start : iter->start+1;
michael@0 925 }
michael@0 926 if(c<=0xffff) {
michael@0 927 return c;
michael@0 928 } else {
michael@0 929 iter->start+=4; /* back to behind this supplementary code point for consistent state */
michael@0 930 iter->reservedField=c;
michael@0 931 return U16_TRAIL(c);
michael@0 932 }
michael@0 933 } else {
michael@0 934 return U_SENTINEL;
michael@0 935 }
michael@0 936 }
michael@0 937
michael@0 938 static uint32_t U_CALLCONV
michael@0 939 utf8IteratorGetState(const UCharIterator *iter) {
michael@0 940 uint32_t state=(uint32_t)(iter->start<<1);
michael@0 941 if(iter->reservedField!=0) {
michael@0 942 state|=1;
michael@0 943 }
michael@0 944 return state;
michael@0 945 }
michael@0 946
michael@0 947 static void U_CALLCONV
michael@0 948 utf8IteratorSetState(UCharIterator *iter,
michael@0 949 uint32_t state,
michael@0 950 UErrorCode *pErrorCode)
michael@0 951 {
michael@0 952 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
michael@0 953 /* do nothing */
michael@0 954 } else if(iter==NULL) {
michael@0 955 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 956 } else if(state==utf8IteratorGetState(iter)) {
michael@0 957 /* setting to the current state: no-op */
michael@0 958 } else {
michael@0 959 int32_t index=(int32_t)(state>>1); /* UTF-8 index */
michael@0 960 state&=1; /* 1 if in surrogate pair, must be index>=4 */
michael@0 961
michael@0 962 if((state==0 ? index<0 : index<4) || iter->limit<index) {
michael@0 963 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
michael@0 964 } else {
michael@0 965 iter->start=index; /* restore UTF-8 byte index */
michael@0 966 if(index<=1) {
michael@0 967 iter->index=index;
michael@0 968 } else {
michael@0 969 iter->index=-1; /* unknown UTF-16 index */
michael@0 970 }
michael@0 971 if(state==0) {
michael@0 972 iter->reservedField=0;
michael@0 973 } else {
michael@0 974 /* verified index>=4 above */
michael@0 975 UChar32 c;
michael@0 976 U8_PREV_OR_FFFD((const uint8_t *)iter->context, 0, index, c);
michael@0 977 if(c<=0xffff) {
michael@0 978 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
michael@0 979 } else {
michael@0 980 iter->reservedField=c;
michael@0 981 }
michael@0 982 }
michael@0 983 }
michael@0 984 }
michael@0 985 }
michael@0 986
michael@0 987 static const UCharIterator utf8Iterator={
michael@0 988 0, 0, 0, 0, 0, 0,
michael@0 989 utf8IteratorGetIndex,
michael@0 990 utf8IteratorMove,
michael@0 991 utf8IteratorHasNext,
michael@0 992 utf8IteratorHasPrevious,
michael@0 993 utf8IteratorCurrent,
michael@0 994 utf8IteratorNext,
michael@0 995 utf8IteratorPrevious,
michael@0 996 NULL,
michael@0 997 utf8IteratorGetState,
michael@0 998 utf8IteratorSetState
michael@0 999 };
michael@0 1000
michael@0 1001 U_CAPI void U_EXPORT2
michael@0 1002 uiter_setUTF8(UCharIterator *iter, const char *s, int32_t length) {
michael@0 1003 if(iter!=0) {
michael@0 1004 if(s!=0 && length>=-1) {
michael@0 1005 *iter=utf8Iterator;
michael@0 1006 iter->context=s;
michael@0 1007 if(length>=0) {
michael@0 1008 iter->limit=length;
michael@0 1009 } else {
michael@0 1010 iter->limit=(int32_t)uprv_strlen(s);
michael@0 1011 }
michael@0 1012 iter->length= iter->limit<=1 ? iter->limit : -1;
michael@0 1013 } else {
michael@0 1014 *iter=noopIterator;
michael@0 1015 }
michael@0 1016 }
michael@0 1017 }
michael@0 1018
michael@0 1019 /* Helper functions --------------------------------------------------------- */
michael@0 1020
michael@0 1021 U_CAPI UChar32 U_EXPORT2
michael@0 1022 uiter_current32(UCharIterator *iter) {
michael@0 1023 UChar32 c, c2;
michael@0 1024
michael@0 1025 c=iter->current(iter);
michael@0 1026 if(U16_IS_SURROGATE(c)) {
michael@0 1027 if(U16_IS_SURROGATE_LEAD(c)) {
michael@0 1028 /*
michael@0 1029 * go to the next code unit
michael@0 1030 * we know that we are not at the limit because c!=U_SENTINEL
michael@0 1031 */
michael@0 1032 iter->move(iter, 1, UITER_CURRENT);
michael@0 1033 if(U16_IS_TRAIL(c2=iter->current(iter))) {
michael@0 1034 c=U16_GET_SUPPLEMENTARY(c, c2);
michael@0 1035 }
michael@0 1036
michael@0 1037 /* undo index movement */
michael@0 1038 iter->move(iter, -1, UITER_CURRENT);
michael@0 1039 } else {
michael@0 1040 if(U16_IS_LEAD(c2=iter->previous(iter))) {
michael@0 1041 c=U16_GET_SUPPLEMENTARY(c2, c);
michael@0 1042 }
michael@0 1043 if(c2>=0) {
michael@0 1044 /* undo index movement */
michael@0 1045 iter->move(iter, 1, UITER_CURRENT);
michael@0 1046 }
michael@0 1047 }
michael@0 1048 }
michael@0 1049 return c;
michael@0 1050 }
michael@0 1051
michael@0 1052 U_CAPI UChar32 U_EXPORT2
michael@0 1053 uiter_next32(UCharIterator *iter) {
michael@0 1054 UChar32 c, c2;
michael@0 1055
michael@0 1056 c=iter->next(iter);
michael@0 1057 if(U16_IS_LEAD(c)) {
michael@0 1058 if(U16_IS_TRAIL(c2=iter->next(iter))) {
michael@0 1059 c=U16_GET_SUPPLEMENTARY(c, c2);
michael@0 1060 } else if(c2>=0) {
michael@0 1061 /* unmatched first surrogate, undo index movement */
michael@0 1062 iter->move(iter, -1, UITER_CURRENT);
michael@0 1063 }
michael@0 1064 }
michael@0 1065 return c;
michael@0 1066 }
michael@0 1067
michael@0 1068 U_CAPI UChar32 U_EXPORT2
michael@0 1069 uiter_previous32(UCharIterator *iter) {
michael@0 1070 UChar32 c, c2;
michael@0 1071
michael@0 1072 c=iter->previous(iter);
michael@0 1073 if(U16_IS_TRAIL(c)) {
michael@0 1074 if(U16_IS_LEAD(c2=iter->previous(iter))) {
michael@0 1075 c=U16_GET_SUPPLEMENTARY(c2, c);
michael@0 1076 } else if(c2>=0) {
michael@0 1077 /* unmatched second surrogate, undo index movement */
michael@0 1078 iter->move(iter, 1, UITER_CURRENT);
michael@0 1079 }
michael@0 1080 }
michael@0 1081 return c;
michael@0 1082 }
michael@0 1083
michael@0 1084 U_CAPI uint32_t U_EXPORT2
michael@0 1085 uiter_getState(const UCharIterator *iter) {
michael@0 1086 if(iter==NULL || iter->getState==NULL) {
michael@0 1087 return UITER_NO_STATE;
michael@0 1088 } else {
michael@0 1089 return iter->getState(iter);
michael@0 1090 }
michael@0 1091 }
michael@0 1092
michael@0 1093 U_CAPI void U_EXPORT2
michael@0 1094 uiter_setState(UCharIterator *iter, uint32_t state, UErrorCode *pErrorCode) {
michael@0 1095 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
michael@0 1096 /* do nothing */
michael@0 1097 } else if(iter==NULL) {
michael@0 1098 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 1099 } else if(iter->setState==NULL) {
michael@0 1100 *pErrorCode=U_UNSUPPORTED_ERROR;
michael@0 1101 } else {
michael@0 1102 iter->setState(iter, state, pErrorCode);
michael@0 1103 }
michael@0 1104 }
michael@0 1105
michael@0 1106 U_CDECL_END

mercurial