• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 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:   US-ASCII
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
u_getDefaultConverter(UErrorCode * status)37 u_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 
64 U_CAPI void U_EXPORT2
u_releaseDefaultConverter(UConverter * converter)65 u_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 
85 U_CAPI void U_EXPORT2
u_flushDefaultConverter()86 u_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 
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 */
u_astrnlen(const char * s1,int32_t n)116 static 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 
130 U_CAPI UChar*  U_EXPORT2
u_uastrncpy(UChar * ucs1,const char * s2,int32_t n)131 u_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 
162 U_CAPI UChar*  U_EXPORT2
u_uastrcpy(UChar * ucs1,const char * s2)163 u_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,
173                     (int32_t)uprv_strlen(s2),
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 */
u_ustrnlen(const UChar * ucs1,int32_t n)188 static 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 
202 U_CAPI char*  U_EXPORT2
u_austrncpy(char * s1,const UChar * ucs2,int32_t n)203 u_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 
234 U_CAPI char*  U_EXPORT2
u_austrcpy(char * s1,const UChar * ucs2)235 u_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
256