~ubuntu-branches/ubuntu/vivid/mozjs24/vivid

« back to all changes in this revision

Viewing changes to intl/icu/source/common/unorm_it.c

  • Committer: Package Import Robot
  • Author(s): Tim Lunn
  • Date: 2014-02-11 21:55:34 UTC
  • Revision ID: package-import@ubuntu.com-20140211215534-m1zyq5aj59md3y07
Tags: upstream-24.2.0
ImportĀ upstreamĀ versionĀ 24.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 itself */
 
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 itself */
 
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[], int32_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[], int32_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 itself */
 
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, TRUE, 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 itself */
 
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, &errorCode);
 
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 */