• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 *
4 *   Copyright (C) 1998-2004, 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 "umutex.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 /* conversions between char* and UChar* ------------------------------------- */
84 
85 /* maximum string length for u_uastrcpy() and u_austrcpy() implementations */
86 #define MAX_STRLEN 0x0FFFFFFF
87 
88 /*
89  returns the minimum of (the length of the null-terminated string) and n.
90 */
u_astrnlen(const char * s1,int32_t n)91 static int32_t u_astrnlen(const char *s1, int32_t n)
92 {
93     int32_t len = 0;
94 
95     if (s1)
96     {
97         while (n-- && *(s1++))
98         {
99             len++;
100         }
101     }
102     return len;
103 }
104 
105 U_CAPI UChar*  U_EXPORT2
u_uastrncpy(UChar * ucs1,const char * s2,int32_t n)106 u_uastrncpy(UChar *ucs1,
107            const char *s2,
108            int32_t n)
109 {
110   UChar *target = ucs1;
111   UErrorCode err = U_ZERO_ERROR;
112   UConverter *cnv = u_getDefaultConverter(&err);
113   if(U_SUCCESS(err) && cnv != NULL) {
114     ucnv_reset(cnv);
115     ucnv_toUnicode(cnv,
116                    &target,
117                    ucs1+n,
118                    &s2,
119                    s2+u_astrnlen(s2, n),
120                    NULL,
121                    TRUE,
122                    &err);
123     ucnv_reset(cnv); /* be good citizens */
124     u_releaseDefaultConverter(cnv);
125     if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
126       *ucs1 = 0; /* failure */
127     }
128     if(target < (ucs1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
129       *target = 0;  /* terminate */
130     }
131   } else {
132     *ucs1 = 0;
133   }
134   return ucs1;
135 }
136 
137 U_CAPI UChar*  U_EXPORT2
u_uastrcpy(UChar * ucs1,const char * s2)138 u_uastrcpy(UChar *ucs1,
139           const char *s2 )
140 {
141   UErrorCode err = U_ZERO_ERROR;
142   UConverter *cnv = u_getDefaultConverter(&err);
143   if(U_SUCCESS(err) && cnv != NULL) {
144     ucnv_toUChars(cnv,
145                     ucs1,
146                     MAX_STRLEN,
147                     s2,
148                     (int32_t)uprv_strlen(s2),
149                     &err);
150     u_releaseDefaultConverter(cnv);
151     if(U_FAILURE(err)) {
152       *ucs1 = 0;
153     }
154   } else {
155     *ucs1 = 0;
156   }
157   return ucs1;
158 }
159 
160 /*
161  returns the minimum of (the length of the null-terminated string) and n.
162 */
u_ustrnlen(const UChar * ucs1,int32_t n)163 static int32_t u_ustrnlen(const UChar *ucs1, int32_t n)
164 {
165     int32_t len = 0;
166 
167     if (ucs1)
168     {
169         while (n-- && *(ucs1++))
170         {
171             len++;
172         }
173     }
174     return len;
175 }
176 
177 U_CAPI char*  U_EXPORT2
u_austrncpy(char * s1,const UChar * ucs2,int32_t n)178 u_austrncpy(char *s1,
179         const UChar *ucs2,
180         int32_t n)
181 {
182   char *target = s1;
183   UErrorCode err = U_ZERO_ERROR;
184   UConverter *cnv = u_getDefaultConverter(&err);
185   if(U_SUCCESS(err) && cnv != NULL) {
186     ucnv_reset(cnv);
187     ucnv_fromUnicode(cnv,
188                   &target,
189                   s1+n,
190                   &ucs2,
191                   ucs2+u_ustrnlen(ucs2, n),
192                   NULL,
193                   TRUE,
194                   &err);
195     ucnv_reset(cnv); /* be good citizens */
196     u_releaseDefaultConverter(cnv);
197     if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
198       *s1 = 0; /* failure */
199     }
200     if(target < (s1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
201       *target = 0;  /* terminate */
202     }
203   } else {
204     *s1 = 0;
205   }
206   return s1;
207 }
208 
209 U_CAPI char*  U_EXPORT2
u_austrcpy(char * s1,const UChar * ucs2)210 u_austrcpy(char *s1,
211          const UChar *ucs2 )
212 {
213   UErrorCode err = U_ZERO_ERROR;
214   UConverter *cnv = u_getDefaultConverter(&err);
215   if(U_SUCCESS(err) && cnv != NULL) {
216     int32_t len = ucnv_fromUChars(cnv,
217                   s1,
218                   MAX_STRLEN,
219                   ucs2,
220                   -1,
221                   &err);
222     u_releaseDefaultConverter(cnv);
223     s1[len] = 0;
224   } else {
225     *s1 = 0;
226   }
227   return s1;
228 }
229 
230 #endif
231