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