intl/icu/source/common/unorm_it.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/intl/icu/source/common/unorm_it.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,646 @@
     1.4 +/*
     1.5 +*******************************************************************************
     1.6 +*
     1.7 +*   Copyright (C) 2003-2011, International Business Machines
     1.8 +*   Corporation and others.  All Rights Reserved.
     1.9 +*
    1.10 +*******************************************************************************
    1.11 +*   file name:  unorm_it.c
    1.12 +*   encoding:   US-ASCII
    1.13 +*   tab size:   8 (not used)
    1.14 +*   indentation:4
    1.15 +*
    1.16 +*   created on: 2003jan21
    1.17 +*   created by: Markus W. Scherer
    1.18 +*/
    1.19 +
    1.20 +#include "unicode/utypes.h"
    1.21 +
    1.22 +#if !UCONFIG_NO_COLLATION && !UCONFIG_NO_NORMALIZATION
    1.23 +
    1.24 +#include "unicode/uiter.h"
    1.25 +#include "unicode/unorm.h"
    1.26 +#include "unicode/utf.h"
    1.27 +#include "unorm_it.h"
    1.28 +#include "cmemory.h"
    1.29 +
    1.30 +/* UNormIterator ------------------------------------------------------------ */
    1.31 +
    1.32 +enum {
    1.33 +    INITIAL_CAPACITY=100
    1.34 +};
    1.35 +
    1.36 +struct UNormIterator {
    1.37 +    UCharIterator api;
    1.38 +    UCharIterator *iter;
    1.39 +
    1.40 +    /*
    1.41 +     * chars and states either use the static buffers
    1.42 +     * or are allocated in the same memory block
    1.43 +     *
    1.44 +     * They are parallel arrays with states[] holding the getState() values
    1.45 +     * from normalization boundaries, and UITER_NO_STATE in between.
    1.46 +     */
    1.47 +    UChar *chars;
    1.48 +    uint32_t *states;
    1.49 +
    1.50 +    /*
    1.51 +     * api.start: first valid character & state in the arrays
    1.52 +     * api.index: current position
    1.53 +     * api.limit: one past the last valid character in chars[], but states[limit] is valid
    1.54 +     * capacity: length of allocated arrays
    1.55 +     */
    1.56 +    int32_t capacity;
    1.57 +
    1.58 +    /* the current iter->getState(), saved to avoid unnecessary setState() calls; may not correspond to api->index! */
    1.59 +    uint32_t state;
    1.60 +
    1.61 +    /* there are UChars available before start or after limit? */
    1.62 +    UBool hasPrevious, hasNext, isStackAllocated;
    1.63 +
    1.64 +    UNormalizationMode mode;
    1.65 +
    1.66 +    UChar charsBuffer[INITIAL_CAPACITY];
    1.67 +    uint32_t statesBuffer[INITIAL_CAPACITY+1]; /* one more than charsBuffer[]! */
    1.68 +};
    1.69 +
    1.70 +static void
    1.71 +initIndexes(UNormIterator *uni, UCharIterator *iter) {
    1.72 +    /* do not pass api so that the compiler knows it's an alias pointer to uni itself */
    1.73 +    UCharIterator *api=&uni->api;
    1.74 +
    1.75 +    if(!iter->hasPrevious(iter)) {
    1.76 +        /* set indexes to the beginning of the arrays */
    1.77 +        api->start=api->index=api->limit=0;
    1.78 +        uni->hasPrevious=FALSE;
    1.79 +        uni->hasNext=iter->hasNext(iter);
    1.80 +    } else if(!iter->hasNext(iter)) {
    1.81 +        /* set indexes to the end of the arrays */
    1.82 +        api->start=api->index=api->limit=uni->capacity;
    1.83 +        uni->hasNext=FALSE;
    1.84 +        uni->hasPrevious=iter->hasPrevious(iter);
    1.85 +    } else {
    1.86 +        /* set indexes into the middle of the arrays */
    1.87 +        api->start=api->index=api->limit=uni->capacity/2;
    1.88 +        uni->hasPrevious=uni->hasNext=TRUE;
    1.89 +    }
    1.90 +}
    1.91 +
    1.92 +static UBool
    1.93 +reallocArrays(UNormIterator *uni, int32_t capacity, UBool addAtStart) {
    1.94 +    /* do not pass api so that the compiler knows it's an alias pointer to uni itself */
    1.95 +    UCharIterator *api=&uni->api;
    1.96 +
    1.97 +    uint32_t *states;
    1.98 +    UChar *chars;
    1.99 +    int32_t start, limit;
   1.100 +
   1.101 +    states=(uint32_t *)uprv_malloc((capacity+1)*4+capacity*2);
   1.102 +    if(states==NULL) {
   1.103 +        return FALSE;
   1.104 +    }
   1.105 +
   1.106 +    chars=(UChar *)(states+(capacity+1));
   1.107 +    uni->capacity=capacity;
   1.108 +
   1.109 +    start=api->start;
   1.110 +    limit=api->limit;
   1.111 +
   1.112 +    if(addAtStart) {
   1.113 +        /* copy old contents to the end of the new arrays */
   1.114 +        int32_t delta;
   1.115 +
   1.116 +        delta=capacity-uni->capacity;
   1.117 +        uprv_memcpy(states+delta+start, uni->states+start, (limit-start+1)*4);
   1.118 +        uprv_memcpy(chars+delta+start, uni->chars+start, (limit-start)*4);
   1.119 +
   1.120 +        api->start=start+delta;
   1.121 +        api->index+=delta;
   1.122 +        api->limit=limit+delta;
   1.123 +    } else {
   1.124 +        /* copy old contents to the beginning of the new arrays */
   1.125 +        uprv_memcpy(states+start, uni->states+start, (limit-start+1)*4);
   1.126 +        uprv_memcpy(chars+start, uni->chars+start, (limit-start)*4);
   1.127 +    }
   1.128 +
   1.129 +    uni->chars=chars;
   1.130 +    uni->states=states;
   1.131 +
   1.132 +    return TRUE;
   1.133 +}
   1.134 +
   1.135 +static void
   1.136 +moveContentsTowardStart(UCharIterator *api, UChar chars[], uint32_t states[], int32_t delta) {
   1.137 +    /* move array contents up to make room */
   1.138 +    int32_t srcIndex, destIndex, limit;
   1.139 +
   1.140 +    limit=api->limit;
   1.141 +    srcIndex=delta;
   1.142 +    if(srcIndex>api->start) {
   1.143 +        /* look for a position in the arrays with a known state */
   1.144 +        while(srcIndex<limit && states[srcIndex]==UITER_NO_STATE) {
   1.145 +            ++srcIndex;
   1.146 +        }
   1.147 +    }
   1.148 +
   1.149 +    /* now actually move the array contents */
   1.150 +    api->start=destIndex=0;
   1.151 +    while(srcIndex<limit) {
   1.152 +        chars[destIndex]=chars[srcIndex];
   1.153 +        states[destIndex++]=states[srcIndex++];
   1.154 +    }
   1.155 +
   1.156 +    /* copy states[limit] as well! */
   1.157 +    states[destIndex]=states[srcIndex];
   1.158 +
   1.159 +    api->limit=destIndex;
   1.160 +}
   1.161 +
   1.162 +static void
   1.163 +moveContentsTowardEnd(UCharIterator *api, UChar chars[], uint32_t states[], int32_t delta) {
   1.164 +    /* move array contents up to make room */
   1.165 +    int32_t srcIndex, destIndex, start;
   1.166 +
   1.167 +    start=api->start;
   1.168 +    destIndex=((UNormIterator *)api)->capacity;
   1.169 +    srcIndex=destIndex-delta;
   1.170 +    if(srcIndex<api->limit) {
   1.171 +        /* look for a position in the arrays with a known state */
   1.172 +        while(srcIndex>start && states[srcIndex]==UITER_NO_STATE) {
   1.173 +            --srcIndex;
   1.174 +        }
   1.175 +    }
   1.176 +
   1.177 +    /* now actually move the array contents */
   1.178 +    api->limit=destIndex;
   1.179 +
   1.180 +    /* copy states[limit] as well! */
   1.181 +    states[destIndex]=states[srcIndex];
   1.182 +
   1.183 +    while(srcIndex>start) {
   1.184 +        chars[--destIndex]=chars[--srcIndex];
   1.185 +        states[destIndex]=states[srcIndex];
   1.186 +    }
   1.187 +
   1.188 +    api->start=destIndex;
   1.189 +}
   1.190 +
   1.191 +/* normalize forward from the limit, assume hasNext is true */
   1.192 +static UBool
   1.193 +readNext(UNormIterator *uni, UCharIterator *iter) {
   1.194 +    /* do not pass api so that the compiler knows it's an alias pointer to uni itself */
   1.195 +    UCharIterator *api=&uni->api;
   1.196 +
   1.197 +    /* make capacity/4 room at the end of the arrays */
   1.198 +    int32_t limit, capacity, room;
   1.199 +    UErrorCode errorCode;
   1.200 +
   1.201 +    limit=api->limit;
   1.202 +    capacity=uni->capacity;
   1.203 +    room=capacity/4;
   1.204 +    if(room>(capacity-limit)) {
   1.205 +        /* move array contents to make room */
   1.206 +        moveContentsTowardStart(api, uni->chars, uni->states, room);
   1.207 +        api->index=limit=api->limit;
   1.208 +        uni->hasPrevious=TRUE;
   1.209 +    }
   1.210 +
   1.211 +    /* normalize starting from the limit position */
   1.212 +    errorCode=U_ZERO_ERROR;
   1.213 +    if(uni->state!=uni->states[limit]) {
   1.214 +        uiter_setState(iter, uni->states[limit], &errorCode);
   1.215 +        if(U_FAILURE(errorCode)) {
   1.216 +            uni->state=UITER_NO_STATE;
   1.217 +            uni->hasNext=FALSE;
   1.218 +            return FALSE;
   1.219 +        }
   1.220 +    }
   1.221 +
   1.222 +    room=unorm_next(iter, uni->chars+limit, capacity-limit, uni->mode, 0, TRUE, NULL, &errorCode);
   1.223 +    if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
   1.224 +        if(room<=capacity) {
   1.225 +            /* empty and re-use the arrays */
   1.226 +            uni->states[0]=uni->states[limit];
   1.227 +            api->start=api->index=api->limit=limit=0;
   1.228 +            uni->hasPrevious=TRUE;
   1.229 +        } else {
   1.230 +            capacity+=room+100;
   1.231 +            if(!reallocArrays(uni, capacity, FALSE)) {
   1.232 +                uni->state=UITER_NO_STATE;
   1.233 +                uni->hasNext=FALSE;
   1.234 +                return FALSE;
   1.235 +            }
   1.236 +            limit=api->limit;
   1.237 +        }
   1.238 +
   1.239 +        errorCode=U_ZERO_ERROR;
   1.240 +        uiter_setState(iter, uni->states[limit], &errorCode);
   1.241 +        room=unorm_next(iter, uni->chars+limit, capacity-limit, uni->mode, 0, TRUE, NULL, &errorCode);
   1.242 +    }
   1.243 +    if(U_FAILURE(errorCode) || room==0) {
   1.244 +        uni->state=UITER_NO_STATE;
   1.245 +        uni->hasNext=FALSE;
   1.246 +        return FALSE;
   1.247 +    }
   1.248 +
   1.249 +    /* room>0 */
   1.250 +    ++limit; /* leave the known states[limit] alone */
   1.251 +    for(--room; room>0; --room) {
   1.252 +        /* set unknown states for all but the normalization boundaries */
   1.253 +        uni->states[limit++]=UITER_NO_STATE;
   1.254 +    }
   1.255 +    uni->states[limit]=uni->state=uiter_getState(iter);
   1.256 +    uni->hasNext=iter->hasNext(iter);
   1.257 +    api->limit=limit;
   1.258 +    return TRUE;
   1.259 +}
   1.260 +
   1.261 +/* normalize backward from the start, assume hasPrevious is true */
   1.262 +static UBool
   1.263 +readPrevious(UNormIterator *uni, UCharIterator *iter) {
   1.264 +    /* do not pass api so that the compiler knows it's an alias pointer to uni itself */
   1.265 +    UCharIterator *api=&uni->api;
   1.266 +
   1.267 +    /* make capacity/4 room at the start of the arrays */
   1.268 +    int32_t start, capacity, room;
   1.269 +    UErrorCode errorCode;
   1.270 +
   1.271 +    start=api->start;
   1.272 +    capacity=uni->capacity;
   1.273 +    room=capacity/4;
   1.274 +    if(room>start) {
   1.275 +        /* move array contents to make room */
   1.276 +        moveContentsTowardEnd(api, uni->chars, uni->states, room);
   1.277 +        api->index=start=api->start;
   1.278 +        uni->hasNext=TRUE;
   1.279 +    }
   1.280 +
   1.281 +    /* normalize ending at the start position */
   1.282 +    errorCode=U_ZERO_ERROR;
   1.283 +    if(uni->state!=uni->states[start]) {
   1.284 +        uiter_setState(iter, uni->states[start], &errorCode);
   1.285 +        if(U_FAILURE(errorCode)) {
   1.286 +            uni->state=UITER_NO_STATE;
   1.287 +            uni->hasPrevious=FALSE;
   1.288 +            return FALSE;
   1.289 +        }
   1.290 +    }
   1.291 +
   1.292 +    room=unorm_previous(iter, uni->chars, start, uni->mode, 0, TRUE, NULL, &errorCode);
   1.293 +    if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
   1.294 +        if(room<=capacity) {
   1.295 +            /* empty and re-use the arrays */
   1.296 +            uni->states[capacity]=uni->states[start];
   1.297 +            api->start=api->index=api->limit=start=capacity;
   1.298 +            uni->hasNext=TRUE;
   1.299 +        } else {
   1.300 +            capacity+=room+100;
   1.301 +            if(!reallocArrays(uni, capacity, TRUE)) {
   1.302 +                uni->state=UITER_NO_STATE;
   1.303 +                uni->hasPrevious=FALSE;
   1.304 +                return FALSE;
   1.305 +            }
   1.306 +            start=api->start;
   1.307 +        }
   1.308 +
   1.309 +        errorCode=U_ZERO_ERROR;
   1.310 +        uiter_setState(iter, uni->states[start], &errorCode);
   1.311 +        room=unorm_previous(iter, uni->chars, start, uni->mode, 0, TRUE, NULL, &errorCode);
   1.312 +    }
   1.313 +    if(U_FAILURE(errorCode) || room==0) {
   1.314 +        uni->state=UITER_NO_STATE;
   1.315 +        uni->hasPrevious=FALSE;
   1.316 +        return FALSE;
   1.317 +    }
   1.318 +
   1.319 +    /* room>0 */
   1.320 +    do {
   1.321 +        /* copy the UChars from chars[0..room[ to chars[(start-room)..start[ */
   1.322 +        uni->chars[--start]=uni->chars[--room];
   1.323 +        /* set unknown states for all but the normalization boundaries */
   1.324 +        uni->states[start]=UITER_NO_STATE;
   1.325 +    } while(room>0);
   1.326 +    uni->states[start]=uni->state=uiter_getState(iter);
   1.327 +    uni->hasPrevious=iter->hasPrevious(iter);
   1.328 +    api->start=start;
   1.329 +    return TRUE;
   1.330 +}
   1.331 +
   1.332 +/* Iterator runtime API functions ------------------------------------------- */
   1.333 +
   1.334 +static int32_t U_CALLCONV
   1.335 +unormIteratorGetIndex(UCharIterator *api, UCharIteratorOrigin origin) {
   1.336 +    switch(origin) {
   1.337 +    case UITER_ZERO:
   1.338 +    case UITER_START:
   1.339 +        return 0;
   1.340 +    case UITER_CURRENT:
   1.341 +    case UITER_LIMIT:
   1.342 +    case UITER_LENGTH:
   1.343 +        return UITER_UNKNOWN_INDEX;
   1.344 +    default:
   1.345 +        /* not a valid origin */
   1.346 +        /* Should never get here! */
   1.347 +        return -1;
   1.348 +    }
   1.349 +}
   1.350 +
   1.351 +static int32_t U_CALLCONV
   1.352 +unormIteratorMove(UCharIterator *api, int32_t delta, UCharIteratorOrigin origin) {
   1.353 +    UNormIterator *uni=(UNormIterator *)api;
   1.354 +    UCharIterator *iter=uni->iter;
   1.355 +    int32_t pos;
   1.356 +
   1.357 +    switch(origin) {
   1.358 +    case UITER_ZERO:
   1.359 +    case UITER_START:
   1.360 +        /* restart from the beginning */
   1.361 +        if(uni->hasPrevious) {
   1.362 +            iter->move(iter, 0, UITER_START);
   1.363 +            api->start=api->index=api->limit=0;
   1.364 +            uni->states[api->limit]=uni->state=uiter_getState(iter);
   1.365 +            uni->hasPrevious=FALSE;
   1.366 +            uni->hasNext=iter->hasNext(iter);
   1.367 +        } else {
   1.368 +            /* we already have the beginning of the normalized text */
   1.369 +            api->index=api->start;
   1.370 +        }
   1.371 +        break;
   1.372 +    case UITER_CURRENT:
   1.373 +        break;
   1.374 +    case UITER_LIMIT:
   1.375 +    case UITER_LENGTH:
   1.376 +        /* restart from the end */
   1.377 +        if(uni->hasNext) {
   1.378 +            iter->move(iter, 0, UITER_LIMIT);
   1.379 +            api->start=api->index=api->limit=uni->capacity;
   1.380 +            uni->states[api->limit]=uni->state=uiter_getState(iter);
   1.381 +            uni->hasPrevious=iter->hasPrevious(iter);
   1.382 +            uni->hasNext=FALSE;
   1.383 +        } else {
   1.384 +            /* we already have the end of the normalized text */
   1.385 +            api->index=api->limit;
   1.386 +        }
   1.387 +        break;
   1.388 +    default:
   1.389 +        return -1;  /* Error */
   1.390 +    }
   1.391 +
   1.392 +    /* move relative to the current position by delta normalized UChars */
   1.393 +    if(delta==0) {
   1.394 +        /* nothing to do */
   1.395 +    } else if(delta>0) {
   1.396 +        /* go forward until the requested position is in the buffer */
   1.397 +        for(;;) {
   1.398 +            pos=api->index+delta;   /* requested position */
   1.399 +            delta=pos-api->limit;   /* remainder beyond buffered text */
   1.400 +            if(delta<=0) {
   1.401 +                api->index=pos;     /* position reached */
   1.402 +                break;
   1.403 +            }
   1.404 +
   1.405 +            /* go to end of buffer and normalize further */
   1.406 +            api->index=api->limit;
   1.407 +            if(!uni->hasNext || !readNext(uni, iter)) {
   1.408 +                break;              /* reached end of text */
   1.409 +            }
   1.410 +        }
   1.411 +    } else /* delta<0 */ {
   1.412 +        /* go backward until the requested position is in the buffer */
   1.413 +        for(;;) {
   1.414 +            pos=api->index+delta;   /* requested position */
   1.415 +            delta=pos-api->start;   /* remainder beyond buffered text */
   1.416 +            if(delta>=0) {
   1.417 +                api->index=pos;     /* position reached */
   1.418 +                break;
   1.419 +            }
   1.420 +
   1.421 +            /* go to start of buffer and normalize further */
   1.422 +            api->index=api->start;
   1.423 +            if(!uni->hasPrevious || !readPrevious(uni, iter)) {
   1.424 +                break;              /* reached start of text */
   1.425 +            }
   1.426 +        }
   1.427 +    }
   1.428 +
   1.429 +    if(api->index==api->start && !uni->hasPrevious) {
   1.430 +        return 0;
   1.431 +    } else {
   1.432 +        return UITER_UNKNOWN_INDEX;
   1.433 +    }
   1.434 +}
   1.435 +
   1.436 +static UBool U_CALLCONV
   1.437 +unormIteratorHasNext(UCharIterator *api) {
   1.438 +    return api->index<api->limit || ((UNormIterator *)api)->hasNext;
   1.439 +}
   1.440 +
   1.441 +static UBool U_CALLCONV
   1.442 +unormIteratorHasPrevious(UCharIterator *api) {
   1.443 +    return api->index>api->start || ((UNormIterator *)api)->hasPrevious;
   1.444 +}
   1.445 +
   1.446 +static UChar32 U_CALLCONV
   1.447 +unormIteratorCurrent(UCharIterator *api) {
   1.448 +    UNormIterator *uni=(UNormIterator *)api;
   1.449 +
   1.450 +    if( api->index<api->limit ||
   1.451 +        (uni->hasNext && readNext(uni, uni->iter))
   1.452 +    ) {
   1.453 +        return uni->chars[api->index];
   1.454 +    } else {
   1.455 +        return U_SENTINEL;
   1.456 +    }
   1.457 +}
   1.458 +
   1.459 +static UChar32 U_CALLCONV
   1.460 +unormIteratorNext(UCharIterator *api) {
   1.461 +    UNormIterator *uni=(UNormIterator *)api;
   1.462 +
   1.463 +    if( api->index<api->limit ||
   1.464 +        (uni->hasNext && readNext(uni, uni->iter))
   1.465 +    ) {
   1.466 +        return uni->chars[api->index++];
   1.467 +    } else {
   1.468 +        return U_SENTINEL;
   1.469 +    }
   1.470 +}
   1.471 +
   1.472 +static UChar32 U_CALLCONV
   1.473 +unormIteratorPrevious(UCharIterator *api) {
   1.474 +    UNormIterator *uni=(UNormIterator *)api;
   1.475 +
   1.476 +    if( api->index>api->start ||
   1.477 +        (uni->hasPrevious && readPrevious(uni, uni->iter))
   1.478 +    ) {
   1.479 +        return uni->chars[--api->index];
   1.480 +    } else {
   1.481 +        return U_SENTINEL;
   1.482 +    }
   1.483 +}
   1.484 +
   1.485 +static uint32_t U_CALLCONV
   1.486 +unormIteratorGetState(const UCharIterator *api) {
   1.487 +    /* not uni->state because that may not be at api->index */
   1.488 +    return ((UNormIterator *)api)->states[api->index];
   1.489 +}
   1.490 +
   1.491 +static void U_CALLCONV
   1.492 +unormIteratorSetState(UCharIterator *api, uint32_t state, UErrorCode *pErrorCode) {
   1.493 +    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
   1.494 +        /* do nothing */
   1.495 +    } else if(api==NULL) {
   1.496 +        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
   1.497 +    } else if(state==UITER_NO_STATE) {
   1.498 +        *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
   1.499 +    } else {
   1.500 +        UNormIterator *uni=(UNormIterator *)api;
   1.501 +        UCharIterator *iter=((UNormIterator *)api)->iter;
   1.502 +        if(state!=uni->state) {
   1.503 +            uni->state=state;
   1.504 +            uiter_setState(iter, state, pErrorCode);
   1.505 +        }
   1.506 +
   1.507 +        /*
   1.508 +         * Try shortcuts: If the requested state is in the array contents
   1.509 +         * then just set the index there.
   1.510 +         *
   1.511 +         * We assume that the state is unique per position!
   1.512 +         */
   1.513 +        if(state==uni->states[api->index]) {
   1.514 +            return;
   1.515 +        } else if(state==uni->states[api->limit]) {
   1.516 +            api->index=api->limit;
   1.517 +            return;
   1.518 +        } else {
   1.519 +            /* search for the index with this state */
   1.520 +            int32_t i;
   1.521 +
   1.522 +            for(i=api->start; i<api->limit; ++i) {
   1.523 +                if(state==uni->states[i]) {
   1.524 +                    api->index=i;
   1.525 +                    return;
   1.526 +                }
   1.527 +            }
   1.528 +        }
   1.529 +
   1.530 +        /* there is no array index for this state, reset for fresh contents */
   1.531 +        initIndexes((UNormIterator *)api, iter);
   1.532 +        uni->states[api->limit]=state;
   1.533 +    }
   1.534 +}
   1.535 +
   1.536 +static const UCharIterator unormIterator={
   1.537 +    NULL, 0, 0, 0, 0, 0,
   1.538 +    unormIteratorGetIndex,
   1.539 +    unormIteratorMove,
   1.540 +    unormIteratorHasNext,
   1.541 +    unormIteratorHasPrevious,
   1.542 +    unormIteratorCurrent,
   1.543 +    unormIteratorNext,
   1.544 +    unormIteratorPrevious,
   1.545 +    NULL,
   1.546 +    unormIteratorGetState,
   1.547 +    unormIteratorSetState
   1.548 +};
   1.549 +
   1.550 +/* Setup functions ---------------------------------------------------------- */
   1.551 +
   1.552 +U_CAPI UNormIterator * U_EXPORT2
   1.553 +unorm_openIter(void *stackMem, int32_t stackMemSize, UErrorCode *pErrorCode) {
   1.554 +    UNormIterator *uni;
   1.555 +
   1.556 +    /* argument checking */
   1.557 +    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
   1.558 +        return NULL;
   1.559 +    }
   1.560 +
   1.561 +    /* allocate */
   1.562 +    uni=NULL;
   1.563 +    if(stackMem!=NULL && stackMemSize>=sizeof(UNormIterator)) {
   1.564 +        if(U_ALIGNMENT_OFFSET(stackMem)==0) {
   1.565 +            /* already aligned */
   1.566 +            uni=(UNormIterator *)stackMem;
   1.567 +        } else {
   1.568 +            int32_t align=(int32_t)U_ALIGNMENT_OFFSET_UP(stackMem);
   1.569 +            if((stackMemSize-=align)>=(int32_t)sizeof(UNormIterator)) {
   1.570 +                /* needs alignment */
   1.571 +                uni=(UNormIterator *)((char *)stackMem+align);
   1.572 +            }
   1.573 +        }
   1.574 +        /* else does not fit */
   1.575 +    }
   1.576 +
   1.577 +    if(uni!=NULL) {
   1.578 +        uni->isStackAllocated=TRUE;
   1.579 +    } else {
   1.580 +        uni=(UNormIterator *)uprv_malloc(sizeof(UNormIterator));
   1.581 +        if(uni==NULL) {
   1.582 +            *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
   1.583 +            return NULL;
   1.584 +        }
   1.585 +        uni->isStackAllocated=FALSE;
   1.586 +    }
   1.587 +
   1.588 +    /*
   1.589 +     * initialize
   1.590 +     * do not memset because that would unnecessarily initialize the arrays
   1.591 +     */
   1.592 +    uni->iter=NULL;
   1.593 +    uni->chars=uni->charsBuffer;
   1.594 +    uni->states=uni->statesBuffer;
   1.595 +    uni->capacity=INITIAL_CAPACITY;
   1.596 +    uni->state=UITER_NO_STATE;
   1.597 +    uni->hasPrevious=uni->hasNext=FALSE;
   1.598 +    uni->mode=UNORM_NONE;
   1.599 +
   1.600 +    /* set a no-op iterator into the api */
   1.601 +    uiter_setString(&uni->api, NULL, 0);
   1.602 +    return uni;
   1.603 +}
   1.604 +
   1.605 +U_CAPI void U_EXPORT2
   1.606 +unorm_closeIter(UNormIterator *uni) {
   1.607 +    if(uni!=NULL) {
   1.608 +        if(uni->states!=uni->statesBuffer) {
   1.609 +            /* chars and states are allocated in the same memory block */
   1.610 +            uprv_free(uni->states);
   1.611 +        }
   1.612 +        if(!uni->isStackAllocated) {
   1.613 +            uprv_free(uni);
   1.614 +        }
   1.615 +    }
   1.616 +}
   1.617 +
   1.618 +U_CAPI UCharIterator * U_EXPORT2
   1.619 +unorm_setIter(UNormIterator *uni, UCharIterator *iter, UNormalizationMode mode, UErrorCode *pErrorCode) {
   1.620 +    /* argument checking */
   1.621 +    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
   1.622 +        return NULL;
   1.623 +    }
   1.624 +    if(uni==NULL) {
   1.625 +        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
   1.626 +        return NULL;
   1.627 +    }
   1.628 +    if( iter==NULL || iter->getState==NULL || iter->setState==NULL ||
   1.629 +        mode<UNORM_NONE || UNORM_MODE_COUNT<=mode
   1.630 +    ) {
   1.631 +        /* set a no-op iterator into the api */
   1.632 +        uiter_setString(&uni->api, NULL, 0);
   1.633 +        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
   1.634 +        return NULL;
   1.635 +    }
   1.636 +
   1.637 +    /* set the iterator and initialize */
   1.638 +    uprv_memcpy(&uni->api, &unormIterator, sizeof(unormIterator));
   1.639 +
   1.640 +    uni->iter=iter;
   1.641 +    uni->mode=mode;
   1.642 +
   1.643 +    initIndexes(uni, iter);
   1.644 +    uni->states[uni->api.limit]=uni->state=uiter_getState(iter);
   1.645 +
   1.646 +    return &uni->api;
   1.647 +}
   1.648 +
   1.649 +#endif /* uconfig.h switches */

mercurial