initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
256
thirdparty/icu4c/common/ustr_cnv.cpp
vendored
Normal file
256
thirdparty/icu4c/common/ustr_cnv.cpp
vendored
Normal file
@@ -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
|
Reference in New Issue
Block a user