1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/common/ustr_cnv.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,253 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* 1.7 +* Copyright (C) 1998-2013, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +******************************************************************************* 1.11 +* file name: ustr_cnv.c 1.12 +* encoding: US-ASCII 1.13 +* tab size: 8 (not used) 1.14 +* indentation:4 1.15 +* 1.16 +* created on: 2004aug24 1.17 +* created by: Markus W. Scherer 1.18 +* 1.19 +* Character conversion functions moved here from ustring.c 1.20 +*/ 1.21 + 1.22 +#include "unicode/utypes.h" 1.23 + 1.24 +#if !UCONFIG_NO_CONVERSION 1.25 + 1.26 +#include "unicode/ustring.h" 1.27 +#include "unicode/ucnv.h" 1.28 +#include "cstring.h" 1.29 +#include "cmemory.h" 1.30 +#include "cmutex.h" 1.31 +#include "ustr_cnv.h" 1.32 + 1.33 +/* mutexed access to a shared default converter ----------------------------- */ 1.34 + 1.35 +static UConverter *gDefaultConverter = NULL; 1.36 + 1.37 +U_CAPI UConverter* U_EXPORT2 1.38 +u_getDefaultConverter(UErrorCode *status) 1.39 +{ 1.40 + UConverter *converter = NULL; 1.41 + 1.42 + if (gDefaultConverter != NULL) { 1.43 + umtx_lock(NULL); 1.44 + 1.45 + /* need to check to make sure it wasn't taken out from under us */ 1.46 + if (gDefaultConverter != NULL) { 1.47 + converter = gDefaultConverter; 1.48 + gDefaultConverter = NULL; 1.49 + } 1.50 + umtx_unlock(NULL); 1.51 + } 1.52 + 1.53 + /* if the cache was empty, create a converter */ 1.54 + if(converter == NULL) { 1.55 + converter = ucnv_open(NULL, status); 1.56 + if(U_FAILURE(*status)) { 1.57 + ucnv_close(converter); 1.58 + converter = NULL; 1.59 + } 1.60 + } 1.61 + 1.62 + return converter; 1.63 +} 1.64 + 1.65 +U_CAPI void U_EXPORT2 1.66 +u_releaseDefaultConverter(UConverter *converter) 1.67 +{ 1.68 + if(gDefaultConverter == NULL) { 1.69 + if (converter != NULL) { 1.70 + ucnv_reset(converter); 1.71 + } 1.72 + umtx_lock(NULL); 1.73 + 1.74 + if(gDefaultConverter == NULL) { 1.75 + gDefaultConverter = converter; 1.76 + converter = NULL; 1.77 + } 1.78 + umtx_unlock(NULL); 1.79 + } 1.80 + 1.81 + if(converter != NULL) { 1.82 + ucnv_close(converter); 1.83 + } 1.84 +} 1.85 + 1.86 +U_CAPI void U_EXPORT2 1.87 +u_flushDefaultConverter() 1.88 +{ 1.89 + UConverter *converter = NULL; 1.90 + 1.91 + if (gDefaultConverter != NULL) { 1.92 + umtx_lock(NULL); 1.93 + 1.94 + /* need to check to make sure it wasn't taken out from under us */ 1.95 + if (gDefaultConverter != NULL) { 1.96 + converter = gDefaultConverter; 1.97 + gDefaultConverter = NULL; 1.98 + } 1.99 + umtx_unlock(NULL); 1.100 + } 1.101 + 1.102 + /* if the cache was populated, flush it */ 1.103 + if(converter != NULL) { 1.104 + ucnv_close(converter); 1.105 + } 1.106 +} 1.107 + 1.108 + 1.109 +/* conversions between char* and UChar* ------------------------------------- */ 1.110 + 1.111 +/* maximum string length for u_uastrcpy() and u_austrcpy() implementations */ 1.112 +#define MAX_STRLEN 0x0FFFFFFF 1.113 + 1.114 +/* 1.115 + returns the minimum of (the length of the null-terminated string) and n. 1.116 +*/ 1.117 +static int32_t u_astrnlen(const char *s1, int32_t n) 1.118 +{ 1.119 + int32_t len = 0; 1.120 + 1.121 + if (s1) 1.122 + { 1.123 + while (n-- && *(s1++)) 1.124 + { 1.125 + len++; 1.126 + } 1.127 + } 1.128 + return len; 1.129 +} 1.130 + 1.131 +U_CAPI UChar* U_EXPORT2 1.132 +u_uastrncpy(UChar *ucs1, 1.133 + const char *s2, 1.134 + int32_t n) 1.135 +{ 1.136 + UChar *target = ucs1; 1.137 + UErrorCode err = U_ZERO_ERROR; 1.138 + UConverter *cnv = u_getDefaultConverter(&err); 1.139 + if(U_SUCCESS(err) && cnv != NULL) { 1.140 + ucnv_reset(cnv); 1.141 + ucnv_toUnicode(cnv, 1.142 + &target, 1.143 + ucs1+n, 1.144 + &s2, 1.145 + s2+u_astrnlen(s2, n), 1.146 + NULL, 1.147 + TRUE, 1.148 + &err); 1.149 + ucnv_reset(cnv); /* be good citizens */ 1.150 + u_releaseDefaultConverter(cnv); 1.151 + if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) { 1.152 + *ucs1 = 0; /* failure */ 1.153 + } 1.154 + if(target < (ucs1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */ 1.155 + *target = 0; /* terminate */ 1.156 + } 1.157 + } else { 1.158 + *ucs1 = 0; 1.159 + } 1.160 + return ucs1; 1.161 +} 1.162 + 1.163 +U_CAPI UChar* U_EXPORT2 1.164 +u_uastrcpy(UChar *ucs1, 1.165 + const char *s2 ) 1.166 +{ 1.167 + UErrorCode err = U_ZERO_ERROR; 1.168 + UConverter *cnv = u_getDefaultConverter(&err); 1.169 + if(U_SUCCESS(err) && cnv != NULL) { 1.170 + ucnv_toUChars(cnv, 1.171 + ucs1, 1.172 + MAX_STRLEN, 1.173 + s2, 1.174 + (int32_t)uprv_strlen(s2), 1.175 + &err); 1.176 + u_releaseDefaultConverter(cnv); 1.177 + if(U_FAILURE(err)) { 1.178 + *ucs1 = 0; 1.179 + } 1.180 + } else { 1.181 + *ucs1 = 0; 1.182 + } 1.183 + return ucs1; 1.184 +} 1.185 + 1.186 +/* 1.187 + returns the minimum of (the length of the null-terminated string) and n. 1.188 +*/ 1.189 +static int32_t u_ustrnlen(const UChar *ucs1, int32_t n) 1.190 +{ 1.191 + int32_t len = 0; 1.192 + 1.193 + if (ucs1) 1.194 + { 1.195 + while (n-- && *(ucs1++)) 1.196 + { 1.197 + len++; 1.198 + } 1.199 + } 1.200 + return len; 1.201 +} 1.202 + 1.203 +U_CAPI char* U_EXPORT2 1.204 +u_austrncpy(char *s1, 1.205 + const UChar *ucs2, 1.206 + int32_t n) 1.207 +{ 1.208 + char *target = s1; 1.209 + UErrorCode err = U_ZERO_ERROR; 1.210 + UConverter *cnv = u_getDefaultConverter(&err); 1.211 + if(U_SUCCESS(err) && cnv != NULL) { 1.212 + ucnv_reset(cnv); 1.213 + ucnv_fromUnicode(cnv, 1.214 + &target, 1.215 + s1+n, 1.216 + &ucs2, 1.217 + ucs2+u_ustrnlen(ucs2, n), 1.218 + NULL, 1.219 + TRUE, 1.220 + &err); 1.221 + ucnv_reset(cnv); /* be good citizens */ 1.222 + u_releaseDefaultConverter(cnv); 1.223 + if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) { 1.224 + *s1 = 0; /* failure */ 1.225 + } 1.226 + if(target < (s1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */ 1.227 + *target = 0; /* terminate */ 1.228 + } 1.229 + } else { 1.230 + *s1 = 0; 1.231 + } 1.232 + return s1; 1.233 +} 1.234 + 1.235 +U_CAPI char* U_EXPORT2 1.236 +u_austrcpy(char *s1, 1.237 + const UChar *ucs2 ) 1.238 +{ 1.239 + UErrorCode err = U_ZERO_ERROR; 1.240 + UConverter *cnv = u_getDefaultConverter(&err); 1.241 + if(U_SUCCESS(err) && cnv != NULL) { 1.242 + int32_t len = ucnv_fromUChars(cnv, 1.243 + s1, 1.244 + MAX_STRLEN, 1.245 + ucs2, 1.246 + -1, 1.247 + &err); 1.248 + u_releaseDefaultConverter(cnv); 1.249 + s1[len] = 0; 1.250 + } else { 1.251 + *s1 = 0; 1.252 + } 1.253 + return s1; 1.254 +} 1.255 + 1.256 +#endif