|
1 /* |
|
2 ******************************************************************************* |
|
3 * |
|
4 * Copyright (C) 1998-2013, International Business Machines |
|
5 * Corporation and others. All Rights Reserved. |
|
6 * |
|
7 ******************************************************************************* |
|
8 * file name: ustr_cnv.c |
|
9 * encoding: US-ASCII |
|
10 * tab size: 8 (not used) |
|
11 * indentation:4 |
|
12 * |
|
13 * created on: 2004aug24 |
|
14 * created by: Markus W. Scherer |
|
15 * |
|
16 * Character conversion functions moved here from ustring.c |
|
17 */ |
|
18 |
|
19 #include "unicode/utypes.h" |
|
20 |
|
21 #if !UCONFIG_NO_CONVERSION |
|
22 |
|
23 #include "unicode/ustring.h" |
|
24 #include "unicode/ucnv.h" |
|
25 #include "cstring.h" |
|
26 #include "cmemory.h" |
|
27 #include "cmutex.h" |
|
28 #include "ustr_cnv.h" |
|
29 |
|
30 /* mutexed access to a shared default converter ----------------------------- */ |
|
31 |
|
32 static UConverter *gDefaultConverter = NULL; |
|
33 |
|
34 U_CAPI UConverter* U_EXPORT2 |
|
35 u_getDefaultConverter(UErrorCode *status) |
|
36 { |
|
37 UConverter *converter = NULL; |
|
38 |
|
39 if (gDefaultConverter != NULL) { |
|
40 umtx_lock(NULL); |
|
41 |
|
42 /* need to check to make sure it wasn't taken out from under us */ |
|
43 if (gDefaultConverter != NULL) { |
|
44 converter = gDefaultConverter; |
|
45 gDefaultConverter = NULL; |
|
46 } |
|
47 umtx_unlock(NULL); |
|
48 } |
|
49 |
|
50 /* if the cache was empty, create a converter */ |
|
51 if(converter == NULL) { |
|
52 converter = ucnv_open(NULL, status); |
|
53 if(U_FAILURE(*status)) { |
|
54 ucnv_close(converter); |
|
55 converter = NULL; |
|
56 } |
|
57 } |
|
58 |
|
59 return converter; |
|
60 } |
|
61 |
|
62 U_CAPI void U_EXPORT2 |
|
63 u_releaseDefaultConverter(UConverter *converter) |
|
64 { |
|
65 if(gDefaultConverter == NULL) { |
|
66 if (converter != NULL) { |
|
67 ucnv_reset(converter); |
|
68 } |
|
69 umtx_lock(NULL); |
|
70 |
|
71 if(gDefaultConverter == NULL) { |
|
72 gDefaultConverter = converter; |
|
73 converter = NULL; |
|
74 } |
|
75 umtx_unlock(NULL); |
|
76 } |
|
77 |
|
78 if(converter != NULL) { |
|
79 ucnv_close(converter); |
|
80 } |
|
81 } |
|
82 |
|
83 U_CAPI void U_EXPORT2 |
|
84 u_flushDefaultConverter() |
|
85 { |
|
86 UConverter *converter = NULL; |
|
87 |
|
88 if (gDefaultConverter != NULL) { |
|
89 umtx_lock(NULL); |
|
90 |
|
91 /* need to check to make sure it wasn't taken out from under us */ |
|
92 if (gDefaultConverter != NULL) { |
|
93 converter = gDefaultConverter; |
|
94 gDefaultConverter = NULL; |
|
95 } |
|
96 umtx_unlock(NULL); |
|
97 } |
|
98 |
|
99 /* if the cache was populated, flush it */ |
|
100 if(converter != NULL) { |
|
101 ucnv_close(converter); |
|
102 } |
|
103 } |
|
104 |
|
105 |
|
106 /* conversions between char* and UChar* ------------------------------------- */ |
|
107 |
|
108 /* maximum string length for u_uastrcpy() and u_austrcpy() implementations */ |
|
109 #define MAX_STRLEN 0x0FFFFFFF |
|
110 |
|
111 /* |
|
112 returns the minimum of (the length of the null-terminated string) and n. |
|
113 */ |
|
114 static int32_t u_astrnlen(const char *s1, int32_t n) |
|
115 { |
|
116 int32_t len = 0; |
|
117 |
|
118 if (s1) |
|
119 { |
|
120 while (n-- && *(s1++)) |
|
121 { |
|
122 len++; |
|
123 } |
|
124 } |
|
125 return len; |
|
126 } |
|
127 |
|
128 U_CAPI UChar* U_EXPORT2 |
|
129 u_uastrncpy(UChar *ucs1, |
|
130 const char *s2, |
|
131 int32_t n) |
|
132 { |
|
133 UChar *target = ucs1; |
|
134 UErrorCode err = U_ZERO_ERROR; |
|
135 UConverter *cnv = u_getDefaultConverter(&err); |
|
136 if(U_SUCCESS(err) && cnv != NULL) { |
|
137 ucnv_reset(cnv); |
|
138 ucnv_toUnicode(cnv, |
|
139 &target, |
|
140 ucs1+n, |
|
141 &s2, |
|
142 s2+u_astrnlen(s2, n), |
|
143 NULL, |
|
144 TRUE, |
|
145 &err); |
|
146 ucnv_reset(cnv); /* be good citizens */ |
|
147 u_releaseDefaultConverter(cnv); |
|
148 if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) { |
|
149 *ucs1 = 0; /* failure */ |
|
150 } |
|
151 if(target < (ucs1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */ |
|
152 *target = 0; /* terminate */ |
|
153 } |
|
154 } else { |
|
155 *ucs1 = 0; |
|
156 } |
|
157 return ucs1; |
|
158 } |
|
159 |
|
160 U_CAPI UChar* U_EXPORT2 |
|
161 u_uastrcpy(UChar *ucs1, |
|
162 const char *s2 ) |
|
163 { |
|
164 UErrorCode err = U_ZERO_ERROR; |
|
165 UConverter *cnv = u_getDefaultConverter(&err); |
|
166 if(U_SUCCESS(err) && cnv != NULL) { |
|
167 ucnv_toUChars(cnv, |
|
168 ucs1, |
|
169 MAX_STRLEN, |
|
170 s2, |
|
171 (int32_t)uprv_strlen(s2), |
|
172 &err); |
|
173 u_releaseDefaultConverter(cnv); |
|
174 if(U_FAILURE(err)) { |
|
175 *ucs1 = 0; |
|
176 } |
|
177 } else { |
|
178 *ucs1 = 0; |
|
179 } |
|
180 return ucs1; |
|
181 } |
|
182 |
|
183 /* |
|
184 returns the minimum of (the length of the null-terminated string) and n. |
|
185 */ |
|
186 static int32_t u_ustrnlen(const UChar *ucs1, int32_t n) |
|
187 { |
|
188 int32_t len = 0; |
|
189 |
|
190 if (ucs1) |
|
191 { |
|
192 while (n-- && *(ucs1++)) |
|
193 { |
|
194 len++; |
|
195 } |
|
196 } |
|
197 return len; |
|
198 } |
|
199 |
|
200 U_CAPI char* U_EXPORT2 |
|
201 u_austrncpy(char *s1, |
|
202 const UChar *ucs2, |
|
203 int32_t n) |
|
204 { |
|
205 char *target = s1; |
|
206 UErrorCode err = U_ZERO_ERROR; |
|
207 UConverter *cnv = u_getDefaultConverter(&err); |
|
208 if(U_SUCCESS(err) && cnv != NULL) { |
|
209 ucnv_reset(cnv); |
|
210 ucnv_fromUnicode(cnv, |
|
211 &target, |
|
212 s1+n, |
|
213 &ucs2, |
|
214 ucs2+u_ustrnlen(ucs2, n), |
|
215 NULL, |
|
216 TRUE, |
|
217 &err); |
|
218 ucnv_reset(cnv); /* be good citizens */ |
|
219 u_releaseDefaultConverter(cnv); |
|
220 if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) { |
|
221 *s1 = 0; /* failure */ |
|
222 } |
|
223 if(target < (s1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */ |
|
224 *target = 0; /* terminate */ |
|
225 } |
|
226 } else { |
|
227 *s1 = 0; |
|
228 } |
|
229 return s1; |
|
230 } |
|
231 |
|
232 U_CAPI char* U_EXPORT2 |
|
233 u_austrcpy(char *s1, |
|
234 const UChar *ucs2 ) |
|
235 { |
|
236 UErrorCode err = U_ZERO_ERROR; |
|
237 UConverter *cnv = u_getDefaultConverter(&err); |
|
238 if(U_SUCCESS(err) && cnv != NULL) { |
|
239 int32_t len = ucnv_fromUChars(cnv, |
|
240 s1, |
|
241 MAX_STRLEN, |
|
242 ucs2, |
|
243 -1, |
|
244 &err); |
|
245 u_releaseDefaultConverter(cnv); |
|
246 s1[len] = 0; |
|
247 } else { |
|
248 *s1 = 0; |
|
249 } |
|
250 return s1; |
|
251 } |
|
252 |
|
253 #endif |