From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- intl/icu/source/common/ustr_cnv.cpp | 256 ++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 intl/icu/source/common/ustr_cnv.cpp (limited to 'intl/icu/source/common/ustr_cnv.cpp') diff --git a/intl/icu/source/common/ustr_cnv.cpp b/intl/icu/source/common/ustr_cnv.cpp new file mode 100644 index 0000000000..abcc12f683 --- /dev/null +++ b/intl/icu/source/common/ustr_cnv.cpp @@ -0,0 +1,256 @@ +// © 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 -- cgit v1.2.3