1 /*
2 ******************************************************************************
3 * Copyright (C) 2001-2006, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 ******************************************************************************
6 *
7 * File ucoleitr.cpp
8 *
9 * Modification History:
10 *
11 * Date Name Description
12 * 02/15/2001 synwee Modified all methods to process its own function
13 * instead of calling the equivalent c++ api (coleitr.h)
14 ******************************************************************************/
15
16 #include "unicode/utypes.h"
17
18 #if !UCONFIG_NO_COLLATION
19
20 #include "unicode/ucoleitr.h"
21 #include "unicode/ustring.h"
22 #include "unicode/sortkey.h"
23 #include "ucol_imp.h"
24 #include "cmemory.h"
25
26 U_NAMESPACE_USE
27
28 #define BUFFER_LENGTH 100
29
30 typedef struct collIterate collIterator;
31
32 /* public methods ---------------------------------------------------- */
33
34 U_CAPI UCollationElements* U_EXPORT2
ucol_openElements(const UCollator * coll,const UChar * text,int32_t textLength,UErrorCode * status)35 ucol_openElements(const UCollator *coll,
36 const UChar *text,
37 int32_t textLength,
38 UErrorCode *status)
39 {
40 UCollationElements *result;
41
42 if (U_FAILURE(*status)) {
43 return NULL;
44 }
45
46 result = (UCollationElements *)uprv_malloc(sizeof(UCollationElements));
47 /* test for NULL */
48 if (result == NULL) {
49 *status = U_MEMORY_ALLOCATION_ERROR;
50 return NULL;
51 }
52
53 result->reset_ = TRUE;
54 result->isWritable = FALSE;
55
56 if (text == NULL) {
57 textLength = 0;
58 }
59 uprv_init_collIterate(coll, text, textLength, &result->iteratordata_);
60
61 return result;
62 }
63
64 U_CAPI void U_EXPORT2
ucol_closeElements(UCollationElements * elems)65 ucol_closeElements(UCollationElements *elems)
66 {
67 collIterate *ci = &elems->iteratordata_;
68 if (ci->writableBuffer != ci->stackWritableBuffer) {
69 uprv_free(ci->writableBuffer);
70 }
71 if (elems->isWritable && elems->iteratordata_.string != NULL)
72 {
73 uprv_free(elems->iteratordata_.string);
74 }
75 uprv_free(elems);
76 }
77
78 U_CAPI void U_EXPORT2
ucol_reset(UCollationElements * elems)79 ucol_reset(UCollationElements *elems)
80 {
81 collIterate *ci = &(elems->iteratordata_);
82 elems->reset_ = TRUE;
83 ci->pos = ci->string;
84 if ((ci->flags & UCOL_ITER_HASLEN) == 0 || ci->endp == NULL) {
85 ci->endp = ci->string + u_strlen(ci->string);
86 }
87 ci->CEpos = ci->toReturn = ci->CEs;
88 ci->flags = UCOL_ITER_HASLEN;
89 if (ci->coll->normalizationMode == UCOL_ON) {
90 ci->flags |= UCOL_ITER_NORM;
91 }
92
93 if (ci->stackWritableBuffer != ci->writableBuffer) {
94 uprv_free(ci->writableBuffer);
95 ci->writableBuffer = ci->stackWritableBuffer;
96 ci->writableBufSize = UCOL_WRITABLE_BUFFER_SIZE;
97 }
98 ci->fcdPosition = NULL;
99 }
100
101 U_CAPI int32_t U_EXPORT2
ucol_next(UCollationElements * elems,UErrorCode * status)102 ucol_next(UCollationElements *elems,
103 UErrorCode *status)
104 {
105 int32_t result;
106 if (U_FAILURE(*status)) {
107 return UCOL_NULLORDER;
108 }
109
110 elems->reset_ = FALSE;
111
112 result = (int32_t)ucol_getNextCE(elems->iteratordata_.coll,
113 &elems->iteratordata_,
114 status);
115
116 if (result == UCOL_NO_MORE_CES) {
117 result = UCOL_NULLORDER;
118 }
119 return result;
120 }
121
122 U_CAPI int32_t U_EXPORT2
ucol_previous(UCollationElements * elems,UErrorCode * status)123 ucol_previous(UCollationElements *elems,
124 UErrorCode *status)
125 {
126 if(U_FAILURE(*status)) {
127 return UCOL_NULLORDER;
128 }
129 else
130 {
131 int32_t result;
132
133 if (elems->reset_ &&
134 (elems->iteratordata_.pos == elems->iteratordata_.string)) {
135 if (elems->iteratordata_.endp == NULL) {
136 elems->iteratordata_.endp = elems->iteratordata_.string +
137 u_strlen(elems->iteratordata_.string);
138 elems->iteratordata_.flags |= UCOL_ITER_HASLEN;
139 }
140 elems->iteratordata_.pos = elems->iteratordata_.endp;
141 elems->iteratordata_.fcdPosition = elems->iteratordata_.endp;
142 }
143
144 elems->reset_ = FALSE;
145
146 result = (int32_t)ucol_getPrevCE(elems->iteratordata_.coll,
147 &(elems->iteratordata_),
148 status);
149
150 if (result == UCOL_NO_MORE_CES) {
151 result = UCOL_NULLORDER;
152 }
153
154 return result;
155 }
156 }
157
158 U_CAPI int32_t U_EXPORT2
ucol_getMaxExpansion(const UCollationElements * elems,int32_t order)159 ucol_getMaxExpansion(const UCollationElements *elems,
160 int32_t order)
161 {
162 uint8_t result;
163 UCOL_GETMAXEXPANSION(elems->iteratordata_.coll, (uint32_t)order, result);
164 return result;
165 }
166
167 U_CAPI void U_EXPORT2
ucol_setText(UCollationElements * elems,const UChar * text,int32_t textLength,UErrorCode * status)168 ucol_setText( UCollationElements *elems,
169 const UChar *text,
170 int32_t textLength,
171 UErrorCode *status)
172 {
173 if (U_FAILURE(*status)) {
174 return;
175 }
176
177 if (elems->isWritable && elems->iteratordata_.string != NULL)
178 {
179 uprv_free(elems->iteratordata_.string);
180 }
181
182 if (text == NULL) {
183 textLength = 0;
184 }
185
186 elems->isWritable = FALSE;
187 uprv_init_collIterate(elems->iteratordata_.coll, text, textLength,
188 &elems->iteratordata_);
189
190 elems->reset_ = TRUE;
191 }
192
193 U_CAPI int32_t U_EXPORT2
ucol_getOffset(const UCollationElements * elems)194 ucol_getOffset(const UCollationElements *elems)
195 {
196 const collIterate *ci = &(elems->iteratordata_);
197 // while processing characters in normalization buffer getOffset will
198 // return the next non-normalized character.
199 // should be inline with the old implementation since the old codes uses
200 // nextDecomp in normalizer which also decomposes the string till the
201 // first base character is found.
202 if (ci->flags & UCOL_ITER_INNORMBUF) {
203 if (ci->fcdPosition == NULL) {
204 return 0;
205 }
206 return (int32_t)(ci->fcdPosition - ci->string);
207 }
208 else {
209 return (int32_t)(ci->pos - ci->string);
210 }
211 }
212
213 U_CAPI void U_EXPORT2
ucol_setOffset(UCollationElements * elems,int32_t offset,UErrorCode * status)214 ucol_setOffset(UCollationElements *elems,
215 int32_t offset,
216 UErrorCode *status)
217 {
218 if (U_FAILURE(*status)) {
219 return;
220 }
221
222 // this methods will clean up any use of the writable buffer and points to
223 // the original string
224 collIterate *ci = &(elems->iteratordata_);
225 ci->pos = ci->string + offset;
226 ci->CEpos = ci->toReturn = ci->CEs;
227 if (ci->flags & UCOL_ITER_INNORMBUF) {
228 ci->flags = ci->origFlags;
229 }
230 if ((ci->flags & UCOL_ITER_HASLEN) == 0) {
231 ci->endp = ci->string + u_strlen(ci->string);
232 ci->flags |= UCOL_ITER_HASLEN;
233 }
234 ci->fcdPosition = NULL;
235 elems->reset_ = FALSE;
236 }
237
238 U_CAPI int32_t U_EXPORT2
ucol_primaryOrder(int32_t order)239 ucol_primaryOrder (int32_t order)
240 {
241 order &= UCOL_PRIMARYMASK;
242 return (order >> UCOL_PRIMARYORDERSHIFT);
243 }
244
245 U_CAPI int32_t U_EXPORT2
ucol_secondaryOrder(int32_t order)246 ucol_secondaryOrder (int32_t order)
247 {
248 order &= UCOL_SECONDARYMASK;
249 return (order >> UCOL_SECONDARYORDERSHIFT);
250 }
251
252 U_CAPI int32_t U_EXPORT2
ucol_tertiaryOrder(int32_t order)253 ucol_tertiaryOrder (int32_t order)
254 {
255 return (order & UCOL_TERTIARYMASK);
256 }
257
258 #endif /* #if !UCONFIG_NO_COLLATION */
259