]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/ucasemap.c
2 *******************************************************************************
4 * Copyright (C) 2005, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: ucasemap.c
10 * tab size: 8 (not used)
13 * created on: 2005may06
14 * created by: Markus W. Scherer
16 * Case mapping service object and functions using it.
19 #include "unicode/utypes.h"
20 #include "unicode/uloc.h"
21 #include "unicode/ustring.h"
22 #include "unicode/ucasemap.h"
28 /* UCaseMap service object -------------------------------------------------- */
31 const UCaseProps
*csp
;
37 U_DRAFT UCaseMap
* U_EXPORT2
38 ucasemap_open(const char *locale
, uint32_t options
, UErrorCode
*pErrorCode
) {
41 if(U_FAILURE(*pErrorCode
)) {
45 csm
=(UCaseMap
*)uprv_malloc(sizeof(UCaseMap
));
49 uprv_memset(csm
, 0, sizeof(UCaseMap
));
51 csm
->csp
=ucase_getSingleton(pErrorCode
);
52 ucasemap_setLocale(csm
, locale
, pErrorCode
);
53 if(U_FAILURE(*pErrorCode
)) {
62 U_DRAFT
void U_EXPORT2
63 ucasemap_close(UCaseMap
*csm
) {
69 U_DRAFT
const char * U_EXPORT2
70 ucasemap_getLocale(const UCaseMap
*csm
) {
74 U_DRAFT
uint32_t U_EXPORT2
75 ucasemap_getOptions(const UCaseMap
*csm
) {
79 U_DRAFT
void U_EXPORT2
80 ucasemap_setLocale(UCaseMap
*csm
, const char *locale
, UErrorCode
*pErrorCode
) {
83 if(U_FAILURE(*pErrorCode
)) {
87 length
=uloc_getName(locale
, csm
->locale
, (int32_t)sizeof(csm
->locale
), pErrorCode
);
88 if(*pErrorCode
==U_BUFFER_OVERFLOW_ERROR
|| length
==sizeof(csm
->locale
)) {
89 *pErrorCode
=U_ZERO_ERROR
;
90 /* we only really need the language code for case mappings */
91 length
=uloc_getLanguage(locale
, csm
->locale
, (int32_t)sizeof(csm
->locale
), pErrorCode
);
93 if(length
==sizeof(csm
->locale
)) {
94 *pErrorCode
=U_BUFFER_OVERFLOW_ERROR
;
97 if(U_SUCCESS(*pErrorCode
)) {
98 ucase_getCaseLocale(csm
->locale
, &csm
->locCache
);
104 U_DRAFT
void U_EXPORT2
105 ucasemap_setOptions(UCaseMap
*csm
, uint32_t options
, UErrorCode
*pErrorCode
) {
106 csm
->options
=options
;
109 /* UTF-8 string case mappings ----------------------------------------------- */
111 /* append a full case mapping result, see UCASE_MAX_STRING_LENGTH */
112 static U_INLINE
int32_t
113 appendResult(uint8_t *dest
, int32_t destIndex
, int32_t destCapacity
,
114 int32_t result
, const UChar
*s
) {
116 int32_t length
, destLength
;
117 UErrorCode errorCode
;
119 /* decode the result */
121 /* (not) original code point */
124 } else if(result
<=UCASE_MAX_STRING_LENGTH
) {
132 if(destIndex
<destCapacity
) {
133 /* append the result */
137 U8_APPEND(dest
, destIndex
, destCapacity
, c
, isError
);
139 /* overflow, nothing written */
140 destIndex
+=U8_LENGTH(c
);
144 errorCode
=U_ZERO_ERROR
;
146 (char *)(dest
+destIndex
), destCapacity
-destIndex
, &destLength
,
150 /* we might have an overflow, but we know the actual length */
155 destIndex
+=U8_LENGTH(c
);
157 errorCode
=U_ZERO_ERROR
;
159 NULL
, 0, &destLength
,
168 static UChar32 U_CALLCONV
169 utf8_caseContextIterator(void *context
, int8_t dir
) {
170 UCaseContext
*csc
=(UCaseContext
*)context
;
174 /* reset for backward iteration */
175 csc
->index
=csc
->cpStart
;
178 /* reset for forward iteration */
179 csc
->index
=csc
->cpLimit
;
182 /* continue current iteration direction */
187 if(csc
->start
<csc
->index
) {
188 U8_PREV((const uint8_t *)csc
->p
, csc
->start
, csc
->index
, c
);
192 if(csc
->index
<csc
->limit
) {
193 U8_NEXT((const uint8_t *)csc
->p
, csc
->index
, csc
->limit
, c
);
200 typedef int32_t U_CALLCONV
201 UCaseMapFull(const UCaseProps
*csp
, UChar32 c
,
202 UCaseContextIterator
*iter
, void *context
,
203 const UChar
**pString
,
204 const char *locale
, int32_t *locCache
);
207 * Case-maps [srcStart..srcLimit[ but takes
208 * context [0..srcLength[ into account.
211 _caseMap(const UCaseMap
*csm
, UCaseMapFull
*map
,
212 uint8_t *dest
, int32_t destCapacity
,
213 const uint8_t *src
, UCaseContext
*csc
,
214 int32_t srcStart
, int32_t srcLimit
,
215 UErrorCode
*pErrorCode
) {
218 int32_t srcIndex
, destIndex
;
221 locCache
=csm
->locCache
;
223 /* case mapping loop */
226 while(srcIndex
<srcLimit
) {
227 csc
->cpStart
=srcIndex
;
228 U8_NEXT(src
, srcIndex
, srcLimit
, c
);
229 csc
->cpLimit
=srcIndex
;
230 c
=map(csm
->csp
, c
, utf8_caseContextIterator
, csc
, &s
, csm
->locale
, &locCache
);
231 destIndex
=appendResult(dest
, destIndex
, destCapacity
, c
, s
);
234 if(destIndex
>destCapacity
) {
235 *pErrorCode
=U_BUFFER_OVERFLOW_ERROR
;
241 * Implement argument checking and buffer handling
242 * for string case mapping as a common function.
251 /* common internal function for public API functions */
254 caseMap(const UCaseMap
*csm
,
255 uint8_t *dest
, int32_t destCapacity
,
256 const uint8_t *src
, int32_t srcLength
,
258 UErrorCode
*pErrorCode
) {
259 UCaseContext csc
={ NULL
};
262 /* check argument values */
263 if(U_FAILURE(*pErrorCode
)) {
266 if( destCapacity
<0 ||
267 (dest
==NULL
&& destCapacity
>0) ||
271 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
275 /* get the string length */
277 srcLength
=uprv_strlen((const char *)src
);
280 /* check for overlapping source and destination */
282 ((src
>=dest
&& src
<(dest
+destCapacity
)) ||
283 (dest
>=src
&& dest
<(src
+srcLength
)))
285 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
294 if(toWhichCase
==TO_LOWER
) {
295 destLength
=_caseMap(csm
, ucase_toFullLower
,
300 } else /* if(toWhichCase==TO_UPPER) */ {
301 destLength
=_caseMap(csm
, ucase_toFullUpper
,
308 return u_terminateChars((char *)dest
, destCapacity
, destLength
, pErrorCode
);
311 /* public API functions */
313 U_DRAFT
int32_t U_EXPORT2
314 ucasemap_utf8ToLower(const UCaseMap
*csm
,
315 char *dest
, int32_t destCapacity
,
316 const char *src
, int32_t srcLength
,
317 UErrorCode
*pErrorCode
) {
319 (uint8_t *)dest
, destCapacity
,
320 (const uint8_t *)src
, srcLength
,
321 TO_LOWER
, pErrorCode
);
324 U_DRAFT
int32_t U_EXPORT2
325 ucasemap_utf8ToUpper(const UCaseMap
*csm
,
326 char *dest
, int32_t destCapacity
,
327 const char *src
, int32_t srcLength
,
328 UErrorCode
*pErrorCode
) {
330 (uint8_t *)dest
, destCapacity
,
331 (const uint8_t *)src
, srcLength
,
332 TO_UPPER
, pErrorCode
);