| /* |
| ****************************************************************************** |
| * Copyright (C) 2001, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| ****************************************************************************** |
| * |
| * File ucoleitr.cpp |
| * |
| * Modification History: |
| * |
| * Date Name Description |
| * 02/15/2001 synwee Modified all methods to process its own function |
| * instead of calling the equivalent c++ api (coleitr.h) |
| ******************************************************************************/ |
| |
| #include "unicode/ucoleitr.h" |
| #include "unicode/ustring.h" |
| #include "unicode/sortkey.h" |
| #include "ucolimp.h" |
| #include "cmemory.h" |
| |
| #define BUFFER_LENGTH 100 |
| |
| typedef struct collIterate collIterator; |
| |
| /* public methods ---------------------------------------------------- */ |
| |
| /** |
| * Since this is going to be deprecated, I'll leave it as it is |
| */ |
| U_CAPI int32_t |
| ucol_keyHashCode(const uint8_t *key, |
| int32_t length) |
| { |
| CollationKey newKey(key, length); |
| return newKey.hashCode(); |
| } |
| |
| |
| UCollationElements* |
| ucol_openElements(const UCollator *coll, |
| const UChar *text, |
| int32_t textLength, |
| UErrorCode *status) |
| { |
| UCollationElements *result; |
| |
| if (U_FAILURE(*status)) |
| return NULL; |
| |
| result = (UCollationElements *)uprv_malloc(sizeof(UCollationElements)); |
| |
| result->collator_ = coll; |
| |
| /* gets the correct length of the null-terminated string */ |
| if (textLength == -1) |
| textLength = u_strlen(text); |
| |
| result->length_ = textLength; |
| init_collIterate(text, textLength, &result->iteratordata_, FALSE); |
| |
| return result; |
| } |
| |
| U_CAPI void |
| ucol_closeElements(UCollationElements *elems) |
| { |
| collIterate *ci = &elems->iteratordata_; |
| if (ci->writableBuffer != ci->stackWritableBuffer) |
| uprv_free(ci->writableBuffer); |
| if (elems->iteratordata_.isWritable && elems->iteratordata_.string != NULL) |
| uprv_free(elems->iteratordata_.string); |
| uprv_free(elems); |
| } |
| |
| U_CAPI void |
| ucol_reset(UCollationElements *elems) |
| { |
| collIterate *ci = &(elems->iteratordata_); |
| ci->pos = ci->string; |
| ci->len = ci->string + elems->length_; |
| ci->CEpos = ci->toReturn = ci->CEs; |
| /* |
| problem here, that means we'll have to keep calculating the new thai set |
| whenever we reset. maybe getSpecialCE should just do up the whole string |
| instead of only a substring of it. |
| */ |
| ci->isThai = TRUE; |
| if (ci->stackWritableBuffer != ci->writableBuffer) |
| { |
| uprv_free(ci->writableBuffer); |
| ci->writableBuffer = ci->stackWritableBuffer; |
| } |
| } |
| |
| U_CAPI int32_t |
| ucol_next(UCollationElements *elems, |
| UErrorCode *status) |
| { |
| if (U_FAILURE(*status)) |
| return UCOL_NULLORDER; |
| |
| int32_t result; |
| UCOL_GETNEXTCE(result, elems->collator_, elems->iteratordata_, status); |
| return result; |
| } |
| |
| U_CAPI int32_t |
| ucol_previous(UCollationElements *elems, |
| UErrorCode *status) |
| { |
| if(U_FAILURE(*status)) |
| return UCOL_NULLORDER; |
| |
| int32_t result; |
| /* UCOL_GETPREVCE(result, elems->collator_, elems->iteratordata_, |
| elems->length_, status); */ |
| |
| /* synwee : to be removed, only for testing */ |
| const UCollator *coll = elems->collator_; |
| collIterate *data = &(elems->iteratordata_); |
| int32_t length = elems->length_; |
| |
| if (data->CEpos > data->CEs) |
| { |
| (result) = *(data->toReturn --); |
| if (data->CEs == data->toReturn) |
| data->CEpos = data->toReturn = data->CEs; |
| } |
| else |
| { |
| /* |
| pointers are always at the next position to be retrieved for getnextce |
| for every first previous step after a next, value returned will the same |
| as the last next value |
| */ |
| if (data->len - data->pos == length) |
| (result) = UCOL_NO_MORE_CES; |
| else |
| { |
| if (data->pos != data->writableBuffer) |
| data->pos --; |
| else |
| { |
| data->pos = data->string + |
| (length - (data->len - data->writableBuffer)); |
| data->len = data->string + length; |
| data->isThai = TRUE; |
| } |
| |
| UChar ch = *(data->pos); |
| if (ch <= 0xFF) |
| (result) = (coll)->latinOneMapping[ch]; |
| else |
| (result) = ucmp32_get((coll)->mapping, ch); |
| |
| if ((result) >= UCOL_NOT_FOUND) |
| { |
| (result) = getSpecialPrevCE(coll, result, data, length, status); |
| if ((result) == UCOL_NOT_FOUND) |
| (result) = ucol_getPrevUCA(ch, data, length, status); |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| U_CAPI int32_t |
| ucol_getMaxExpansion(const UCollationElements *elems, |
| int32_t order) |
| { |
| /* |
| synwee : requested this implementation from vladimir, need discussion. so |
| hang on. |
| */ |
| /* return ((CollationElementIterator*)elems)->getMaxExpansion(order); */ |
| return -1; |
| } |
| |
| U_CAPI void |
| ucol_setText( UCollationElements *elems, |
| const UChar *text, |
| int32_t textLength, |
| UErrorCode *status) |
| { |
| if (U_FAILURE(*status)) |
| return; |
| |
| /* gets the correct length of the null-terminated string */ |
| if (textLength == -1) |
| textLength = u_strlen(text); |
| |
| elems->length_ = textLength; |
| |
| if (elems->iteratordata_.isWritable && elems->iteratordata_.string != NULL) |
| uprv_free(elems->iteratordata_.string); |
| init_collIterate(text, textLength, &elems->iteratordata_, FALSE); |
| } |
| |
| U_CAPI UTextOffset |
| ucol_getOffset(const UCollationElements *elems) |
| { |
| /* return ((CollationElementIterator*)elems)->getOffset(); */ |
| const collIterate *ci = &(elems->iteratordata_); |
| if (ci->isThai == TRUE) |
| return ci->pos - ci->string; |
| |
| /* |
| if it is a thai string with reversed elements, since getNextCE does not |
| store only a substring in writeablebuffer, we'll have to do some calculation |
| to get the offset out. |
| need discussion to see if it is a better idea to store the whole string |
| instead. |
| */ |
| return elems->length_ - (ci->len - ci->pos); |
| } |
| |
| U_CAPI void |
| ucol_setOffset(UCollationElements *elems, |
| UTextOffset offset, |
| UErrorCode *status) |
| { |
| if (U_FAILURE(*status)) |
| return; |
| |
| collIterate *ci = &(elems->iteratordata_); |
| ci->pos = ci->string + offset; |
| ci->CEpos = ci->toReturn = ci->CEs; |
| /* |
| problem here, that means we'll have to keep calculating the new thai set |
| whenever we reset. maybe getSpecialCE should just do up the whole string |
| instead of only a substring of it. |
| */ |
| ci->isThai = TRUE; |
| if (ci->stackWritableBuffer != ci->writableBuffer) |
| { |
| uprv_free(ci->writableBuffer); |
| ci->writableBuffer = ci->stackWritableBuffer; |
| } |
| } |
| |
| |
| |
| |
| |