1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 1998-2010, 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 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 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 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 */ 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 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 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 */ 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 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 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