• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
u_getDefaultConverter(UErrorCode * status)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
u_releaseDefaultConverter(UConverter * converter)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
u_flushDefaultConverter()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 */
u_astrnlen(const char * s1,int32_t n)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
u_uastrncpy(UChar * ucs1,const char * s2,int32_t n)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
u_uastrcpy(UChar * ucs1,const char * s2)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 */
u_ustrnlen(const UChar * ucs1,int32_t n)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
u_austrncpy(char * s1,const UChar * ucs2,int32_t n)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
u_austrcpy(char * s1,const UChar * ucs2)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
254