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