123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- // © 2016 and later: Unicode, Inc. and others.
- // License & terms of use: http://www.unicode.org/copyright.html
- /*
- *******************************************************************************
- *
- * Copyright (C) 1998-2014, International Business Machines
- * Corporation and others. All Rights Reserved.
- *
- *******************************************************************************
- * file name: ustr_cnv.cpp
- * encoding: UTF-8
- * tab size: 8 (not used)
- * indentation:4
- *
- * created on: 2004aug24
- * created by: Markus W. Scherer
- *
- * Character conversion functions moved here from ustring.c
- */
- #include "unicode/utypes.h"
- #if !UCONFIG_NO_CONVERSION
- #include "unicode/ustring.h"
- #include "unicode/ucnv.h"
- #include "cstring.h"
- #include "cmemory.h"
- #include "umutex.h"
- #include "ustr_cnv.h"
- #include "ucnv_bld.h"
- /* mutexed access to a shared default converter ----------------------------- */
- static UConverter *gDefaultConverter = nullptr;
- U_CAPI UConverter* U_EXPORT2
- u_getDefaultConverter(UErrorCode *status)
- {
- UConverter *converter = nullptr;
-
- if (gDefaultConverter != nullptr) {
- icu::umtx_lock(nullptr);
-
- /* need to check to make sure it wasn't taken out from under us */
- if (gDefaultConverter != nullptr) {
- converter = gDefaultConverter;
- gDefaultConverter = nullptr;
- }
- icu::umtx_unlock(nullptr);
- }
- /* if the cache was empty, create a converter */
- if(converter == nullptr) {
- converter = ucnv_open(nullptr, status);
- if(U_FAILURE(*status)) {
- ucnv_close(converter);
- converter = nullptr;
- }
- }
- return converter;
- }
- U_CAPI void U_EXPORT2
- u_releaseDefaultConverter(UConverter *converter)
- {
- if(gDefaultConverter == nullptr) {
- if (converter != nullptr) {
- ucnv_reset(converter);
- }
- ucnv_enableCleanup();
- icu::umtx_lock(nullptr);
- if(gDefaultConverter == nullptr) {
- gDefaultConverter = converter;
- converter = nullptr;
- }
- icu::umtx_unlock(nullptr);
- }
- if(converter != nullptr) {
- ucnv_close(converter);
- }
- }
- U_CAPI void U_EXPORT2
- u_flushDefaultConverter()
- {
- UConverter *converter = nullptr;
-
- if (gDefaultConverter != nullptr) {
- icu::umtx_lock(nullptr);
-
- /* need to check to make sure it wasn't taken out from under us */
- if (gDefaultConverter != nullptr) {
- converter = gDefaultConverter;
- gDefaultConverter = nullptr;
- }
- icu::umtx_unlock(nullptr);
- }
- /* if the cache was populated, flush it */
- if(converter != nullptr) {
- ucnv_close(converter);
- }
- }
- /* conversions between char* and char16_t* ------------------------------------- */
- /* maximum string length for u_uastrcpy() and u_austrcpy() implementations */
- #define MAX_STRLEN 0x0FFFFFFF
- /*
- returns the minimum of (the length of the null-terminated string) and n.
- */
- static int32_t u_astrnlen(const char *s1, int32_t n)
- {
- int32_t len = 0;
- if (s1)
- {
- while (n-- && *(s1++))
- {
- len++;
- }
- }
- return len;
- }
- U_CAPI char16_t* U_EXPORT2
- u_uastrncpy(char16_t *ucs1,
- const char *s2,
- int32_t n)
- {
- char16_t *target = ucs1;
- UErrorCode err = U_ZERO_ERROR;
- UConverter *cnv = u_getDefaultConverter(&err);
- if(U_SUCCESS(err) && cnv != nullptr) {
- ucnv_reset(cnv);
- ucnv_toUnicode(cnv,
- &target,
- ucs1+n,
- &s2,
- s2+u_astrnlen(s2, n),
- nullptr,
- true,
- &err);
- ucnv_reset(cnv); /* be good citizens */
- u_releaseDefaultConverter(cnv);
- if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
- *ucs1 = 0; /* failure */
- }
- if(target < (ucs1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
- *target = 0; /* terminate */
- }
- } else {
- *ucs1 = 0;
- }
- return ucs1;
- }
- U_CAPI char16_t* U_EXPORT2
- u_uastrcpy(char16_t *ucs1,
- const char *s2 )
- {
- UErrorCode err = U_ZERO_ERROR;
- UConverter *cnv = u_getDefaultConverter(&err);
- if(U_SUCCESS(err) && cnv != nullptr) {
- ucnv_toUChars(cnv,
- ucs1,
- MAX_STRLEN,
- s2,
- (int32_t)uprv_strlen(s2),
- &err);
- u_releaseDefaultConverter(cnv);
- if(U_FAILURE(err)) {
- *ucs1 = 0;
- }
- } else {
- *ucs1 = 0;
- }
- return ucs1;
- }
- /*
- returns the minimum of (the length of the null-terminated string) and n.
- */
- static int32_t u_ustrnlen(const char16_t *ucs1, int32_t n)
- {
- int32_t len = 0;
- if (ucs1)
- {
- while (n-- && *(ucs1++))
- {
- len++;
- }
- }
- return len;
- }
- U_CAPI char* U_EXPORT2
- u_austrncpy(char *s1,
- const char16_t *ucs2,
- int32_t n)
- {
- char *target = s1;
- UErrorCode err = U_ZERO_ERROR;
- UConverter *cnv = u_getDefaultConverter(&err);
- if(U_SUCCESS(err) && cnv != nullptr) {
- ucnv_reset(cnv);
- ucnv_fromUnicode(cnv,
- &target,
- s1+n,
- &ucs2,
- ucs2+u_ustrnlen(ucs2, n),
- nullptr,
- true,
- &err);
- ucnv_reset(cnv); /* be good citizens */
- u_releaseDefaultConverter(cnv);
- if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
- *s1 = 0; /* failure */
- }
- if(target < (s1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
- *target = 0; /* terminate */
- }
- } else {
- *s1 = 0;
- }
- return s1;
- }
- U_CAPI char* U_EXPORT2
- u_austrcpy(char *s1,
- const char16_t *ucs2 )
- {
- UErrorCode err = U_ZERO_ERROR;
- UConverter *cnv = u_getDefaultConverter(&err);
- if(U_SUCCESS(err) && cnv != nullptr) {
- int32_t len = ucnv_fromUChars(cnv,
- s1,
- MAX_STRLEN,
- ucs2,
- -1,
- &err);
- u_releaseDefaultConverter(cnv);
- s1[len] = 0;
- } else {
- *s1 = 0;
- }
- return s1;
- }
- #endif
|