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