]> git.saurik.com Git - apple/icu.git/blame - icuSources/common/ustr_cnv.c
ICU-8.11.1.tar.gz
[apple/icu.git] / icuSources / common / ustr_cnv.c
CommitLineData
374ca955
A
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
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
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*/
91static 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
105U_CAPI UChar* U_EXPORT2
106u_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
137U_CAPI UChar* U_EXPORT2
138u_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,
73c04bcf 148 (int32_t)uprv_strlen(s2),
374ca955
A
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*/
163static 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
177U_CAPI char* U_EXPORT2
178u_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
209U_CAPI char* U_EXPORT2
210u_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