ustr_cnv.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. *******************************************************************************
  5. *
  6. * Copyright (C) 1998-2014, International Business Machines
  7. * Corporation and others. All Rights Reserved.
  8. *
  9. *******************************************************************************
  10. * file name: ustr_cnv.cpp
  11. * encoding: UTF-8
  12. * tab size: 8 (not used)
  13. * indentation:4
  14. *
  15. * created on: 2004aug24
  16. * created by: Markus W. Scherer
  17. *
  18. * Character conversion functions moved here from ustring.c
  19. */
  20. #include "unicode/utypes.h"
  21. #if !UCONFIG_NO_CONVERSION
  22. #include "unicode/ustring.h"
  23. #include "unicode/ucnv.h"
  24. #include "cstring.h"
  25. #include "cmemory.h"
  26. #include "umutex.h"
  27. #include "ustr_cnv.h"
  28. #include "ucnv_bld.h"
  29. /* mutexed access to a shared default converter ----------------------------- */
  30. static UConverter *gDefaultConverter = nullptr;
  31. U_CAPI UConverter* U_EXPORT2
  32. u_getDefaultConverter(UErrorCode *status)
  33. {
  34. UConverter *converter = nullptr;
  35. if (gDefaultConverter != nullptr) {
  36. icu::umtx_lock(nullptr);
  37. /* need to check to make sure it wasn't taken out from under us */
  38. if (gDefaultConverter != nullptr) {
  39. converter = gDefaultConverter;
  40. gDefaultConverter = nullptr;
  41. }
  42. icu::umtx_unlock(nullptr);
  43. }
  44. /* if the cache was empty, create a converter */
  45. if(converter == nullptr) {
  46. converter = ucnv_open(nullptr, status);
  47. if(U_FAILURE(*status)) {
  48. ucnv_close(converter);
  49. converter = nullptr;
  50. }
  51. }
  52. return converter;
  53. }
  54. U_CAPI void U_EXPORT2
  55. u_releaseDefaultConverter(UConverter *converter)
  56. {
  57. if(gDefaultConverter == nullptr) {
  58. if (converter != nullptr) {
  59. ucnv_reset(converter);
  60. }
  61. ucnv_enableCleanup();
  62. icu::umtx_lock(nullptr);
  63. if(gDefaultConverter == nullptr) {
  64. gDefaultConverter = converter;
  65. converter = nullptr;
  66. }
  67. icu::umtx_unlock(nullptr);
  68. }
  69. if(converter != nullptr) {
  70. ucnv_close(converter);
  71. }
  72. }
  73. U_CAPI void U_EXPORT2
  74. u_flushDefaultConverter()
  75. {
  76. UConverter *converter = nullptr;
  77. if (gDefaultConverter != nullptr) {
  78. icu::umtx_lock(nullptr);
  79. /* need to check to make sure it wasn't taken out from under us */
  80. if (gDefaultConverter != nullptr) {
  81. converter = gDefaultConverter;
  82. gDefaultConverter = nullptr;
  83. }
  84. icu::umtx_unlock(nullptr);
  85. }
  86. /* if the cache was populated, flush it */
  87. if(converter != nullptr) {
  88. ucnv_close(converter);
  89. }
  90. }
  91. /* conversions between char* and char16_t* ------------------------------------- */
  92. /* maximum string length for u_uastrcpy() and u_austrcpy() implementations */
  93. #define MAX_STRLEN 0x0FFFFFFF
  94. /*
  95. returns the minimum of (the length of the null-terminated string) and n.
  96. */
  97. static int32_t u_astrnlen(const char *s1, int32_t n)
  98. {
  99. int32_t len = 0;
  100. if (s1)
  101. {
  102. while (n-- && *(s1++))
  103. {
  104. len++;
  105. }
  106. }
  107. return len;
  108. }
  109. U_CAPI char16_t* U_EXPORT2
  110. u_uastrncpy(char16_t *ucs1,
  111. const char *s2,
  112. int32_t n)
  113. {
  114. char16_t *target = ucs1;
  115. UErrorCode err = U_ZERO_ERROR;
  116. UConverter *cnv = u_getDefaultConverter(&err);
  117. if(U_SUCCESS(err) && cnv != nullptr) {
  118. ucnv_reset(cnv);
  119. ucnv_toUnicode(cnv,
  120. &target,
  121. ucs1+n,
  122. &s2,
  123. s2+u_astrnlen(s2, n),
  124. nullptr,
  125. true,
  126. &err);
  127. ucnv_reset(cnv); /* be good citizens */
  128. u_releaseDefaultConverter(cnv);
  129. if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
  130. *ucs1 = 0; /* failure */
  131. }
  132. if(target < (ucs1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
  133. *target = 0; /* terminate */
  134. }
  135. } else {
  136. *ucs1 = 0;
  137. }
  138. return ucs1;
  139. }
  140. U_CAPI char16_t* U_EXPORT2
  141. u_uastrcpy(char16_t *ucs1,
  142. const char *s2 )
  143. {
  144. UErrorCode err = U_ZERO_ERROR;
  145. UConverter *cnv = u_getDefaultConverter(&err);
  146. if(U_SUCCESS(err) && cnv != nullptr) {
  147. ucnv_toUChars(cnv,
  148. ucs1,
  149. MAX_STRLEN,
  150. s2,
  151. (int32_t)uprv_strlen(s2),
  152. &err);
  153. u_releaseDefaultConverter(cnv);
  154. if(U_FAILURE(err)) {
  155. *ucs1 = 0;
  156. }
  157. } else {
  158. *ucs1 = 0;
  159. }
  160. return ucs1;
  161. }
  162. /*
  163. returns the minimum of (the length of the null-terminated string) and n.
  164. */
  165. static int32_t u_ustrnlen(const char16_t *ucs1, int32_t n)
  166. {
  167. int32_t len = 0;
  168. if (ucs1)
  169. {
  170. while (n-- && *(ucs1++))
  171. {
  172. len++;
  173. }
  174. }
  175. return len;
  176. }
  177. U_CAPI char* U_EXPORT2
  178. u_austrncpy(char *s1,
  179. const char16_t *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 != nullptr) {
  186. ucnv_reset(cnv);
  187. ucnv_fromUnicode(cnv,
  188. &target,
  189. s1+n,
  190. &ucs2,
  191. ucs2+u_ustrnlen(ucs2, n),
  192. nullptr,
  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. U_CAPI char* U_EXPORT2
  209. u_austrcpy(char *s1,
  210. const char16_t *ucs2 )
  211. {
  212. UErrorCode err = U_ZERO_ERROR;
  213. UConverter *cnv = u_getDefaultConverter(&err);
  214. if(U_SUCCESS(err) && cnv != nullptr) {
  215. int32_t len = ucnv_fromUChars(cnv,
  216. s1,
  217. MAX_STRLEN,
  218. ucs2,
  219. -1,
  220. &err);
  221. u_releaseDefaultConverter(cnv);
  222. s1[len] = 0;
  223. } else {
  224. *s1 = 0;
  225. }
  226. return s1;
  227. }
  228. #endif