]> git.saurik.com Git - apple/icu.git/blame - icuSources/common/ustr_cnv.cpp
ICU-57131.0.1.tar.gz
[apple/icu.git] / icuSources / common / ustr_cnv.cpp
CommitLineData
374ca955
A
1/*
2*******************************************************************************
3*
b331163b 4* Copyright (C) 1998-2014, International Business Machines
374ca955
A
5* Corporation and others. All Rights Reserved.
6*
7*******************************************************************************
b331163b 8* file name: ustr_cnv.cpp
374ca955
A
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"
b331163b 27#include "umutex.h"
374ca955
A
28#include "ustr_cnv.h"
29
30/* mutexed access to a shared default converter ----------------------------- */
31
32static UConverter *gDefaultConverter = NULL;
33
34U_CAPI UConverter* U_EXPORT2
35u_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
62U_CAPI void U_EXPORT2
63u_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
729e4ab9
A
83U_CAPI void U_EXPORT2
84u_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
374ca955
A
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*/
114static 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
128U_CAPI UChar* U_EXPORT2
129u_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
160U_CAPI UChar* U_EXPORT2
161u_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,
73c04bcf 171 (int32_t)uprv_strlen(s2),
374ca955
A
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*/
186static 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
200U_CAPI char* U_EXPORT2
201u_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
232U_CAPI char* U_EXPORT2
233u_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