OLD | NEW |
| (Empty) |
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 | |
OLD | NEW |