diff --git a/src/internal/locale_impl.c b/src/internal/locale_impl.c index 595a44339c0acc4227cead3a85a2b7ba9b2ae985..e7d45890a0cd938f4be6a2def60f13e9b90de442 100644 --- a/src/internal/locale_impl.c +++ b/src/internal/locale_impl.c @@ -141,16 +141,9 @@ bool icuuc_handle_init() return false; } } - if (!g_icu_opt_func.ucnv_toUChars) { - get_icu_symbol(ICU_UC, &(g_icu_opt_func.ucnv_toUChars), ICU_UCNV_TOUCHARS_SYMBOL); - if (!g_icu_opt_func.ucnv_toUChars) { - icuuc_handle_init_fail = 1; - return false; - } - } - if (!g_icu_opt_func.ucnv_fromUChars) { - get_icu_symbol(ICU_UC, &(g_icu_opt_func.ucnv_fromUChars), ICU_UCNV_FROMUCHARS_SYMBOL); - if (!g_icu_opt_func.ucnv_fromUChars) { + if (!g_icu_opt_func.ucnv_convertEx) { + get_icu_symbol(ICU_UC, &(g_icu_opt_func.ucnv_convertEx), ICU_UCNV_CONVERTEX_SYMBOL); + if (!g_icu_opt_func.ucnv_convertEx) { icuuc_handle_init_fail = 1; return false; } diff --git a/src/internal/locale_impl.h b/src/internal/locale_impl.h index 3ca9935009db487bc9192130cc3be81af91634a7..f31983151f14788e213ecdd2ccd9d1041660c389 100644 --- a/src/internal/locale_impl.h +++ b/src/internal/locale_impl.h @@ -46,9 +46,8 @@ hidden char *__gettextdomain(void); #define ICU_UCNV_OPEN_SYMBOL "ucnv_open" #define ICU_UCNV_SETTOUCALLBACK_SYMBOL "ucnv_setToUCallBack" #define ICU_UCNV_SETFROMUCALLBACK_SYMBOL "ucnv_setFromUCallBack" -#define ICU_UCNV_TOUCHARS_SYMBOL "ucnv_toUChars" -#define ICU_UCNV_FROMUCHARS_SYMBOL "ucnv_fromUChars" #define ICU_UCNV_CLOSE_SYMBOL "ucnv_close" +#define ICU_UCNV_CONVERTEX_SYMBOL "ucnv_convertEx" #ifdef FEATURE_ICU_LOCALE_TMP #define ICU_UCHAR_ISALNUM_SYMBOL "u_isalnum" #define ICU_UCHAR_ISALPHA_SYMBOL "u_isalpha" @@ -94,8 +93,8 @@ typedef char *(*f_icuuc_u_austrncpy)(char *, const u_char *, int32_t); typedef void* (*f_ucnv_open)(const char*, int*); typedef int32_t (*f_ucnv_setToUCallBack)(void*, void*, void*, void*, void*, int*); typedef int32_t (*f_ucnv_setFromUCallBack)(void*, void*, void*, void*, void*, int*); -typedef int32_t (*f_ucnv_toUChars)(void*, char*, size_t, void*, size_t, int*); -typedef int32_t (*f_ucnv_fromUChars)(void*, char*, size_t, uint16_t*, size_t, int*); +typedef void (*f_ucnv_convertEx)(void*, void*, char**, const char *,const char **, const char *, + u_char*, u_char **, u_char **, const u_char*, int8_t, int8_t, int*); typedef void (*f_ucnv_close)(void*); #ifdef FEATURE_ICU_LOCALE_TMP typedef int(*f_icu18n_u_isalnum)(int c); @@ -127,8 +126,7 @@ struct icu_opt_func { f_ucnv_open ucnv_open; f_ucnv_setToUCallBack ucnv_setToUCallBack; f_ucnv_setFromUCallBack ucnv_setFromUCallBack; - f_ucnv_toUChars ucnv_toUChars; - f_ucnv_fromUChars ucnv_fromUChars; + f_ucnv_convertEx ucnv_convertEx; f_ucnv_close ucnv_close; #ifdef FEATURE_ICU_LOCALE_TMP f_icu18n_u_isalnum u_isalnum; diff --git a/src/locale/iconv.c b/src/locale/iconv.c index 8ca83a40de240a8b56ffbb7b416025be0e0d4e8c..1497af4dfb6788fc7672644c2f048c2d38043275 100644 --- a/src/locale/iconv.c +++ b/src/locale/iconv.c @@ -46,6 +46,7 @@ #define FROM_IGNORE_FLAG_POS 3 #define TO_TRANSLIT_FLAG_POS 4 #define FROM_TRANSLIT_FLAG_POS 5 +#define ICU_CHUNK_SIZE 1024 #endif #endif /* Definitions of charmaps. Each charmap consists of: @@ -467,44 +468,45 @@ static size_t iconv_icu(unsigned sign, const unsigned char* to, const unsigned c char **restrict in, size_t *restrict inb, char **restrict out, size_t *restrict outb) { int errCode = ICU_ZERO_ERROR; - size_t out_size = 0; - size_t uchars_len = *inb * 4; - uint16_t uchars[uchars_len]; - // (from -> UChars) <=> ucnv_toUChars - void* conv_to_u = g_icu_opt_func.ucnv_open((void*)from, &errCode); + void* conv_in = g_icu_opt_func.ucnv_open((void*)from, &errCode); if (get_from_ignore_flag(sign)) { - g_icu_opt_func.ucnv_setToUCallBack(conv_to_u, ucnv_to_u_callback_ignore, NULL, NULL, NULL, &errCode); + g_icu_opt_func.ucnv_setToUCallBack(conv_in, ucnv_to_u_callback_ignore, NULL, NULL, NULL, &errCode); } else if (!get_from_translit_flag(sign)) { - g_icu_opt_func.ucnv_setFromUCallBack(conv_to_u, ucnv_to_u_callback_stop, NULL, NULL, NULL, &errCode); + g_icu_opt_func.ucnv_setFromUCallBack(conv_in, ucnv_to_u_callback_stop, NULL, NULL, NULL, &errCode); } - uchars_len = g_icu_opt_func.ucnv_toUChars(conv_to_u, uchars, uchars_len, *in, *inb, &errCode); - if (errCode > ICU_ZERO_ERROR) { - set_errno(errCode); - return (size_t)-1; - } else { - errCode = ICU_ZERO_ERROR; - } - g_icu_opt_func.ucnv_close(conv_to_u); - // (UChars -> to) <=> ucnv_fromUChars - void* conv_from_u = g_icu_opt_func.ucnv_open((void*)to, &errCode); + void* conv_out = g_icu_opt_func.ucnv_open((void*)to, &errCode); if (get_to_ignore_flag(sign)) { - g_icu_opt_func.ucnv_setFromUCallBack(conv_from_u, ucnv_from_u_callback_ignore, NULL, NULL, NULL, &errCode); + g_icu_opt_func.ucnv_setFromUCallBack(conv_out, ucnv_from_u_callback_ignore, NULL, NULL, NULL, &errCode); } else if (!get_to_translit_flag(sign)) { - g_icu_opt_func.ucnv_setFromUCallBack(conv_from_u, ucnv_from_u_callback_stop, NULL, NULL, NULL, &errCode); + g_icu_opt_func.ucnv_setFromUCallBack(conv_out, ucnv_from_u_callback_stop, NULL, NULL, NULL, &errCode); } - out_size = g_icu_opt_func.ucnv_fromUChars(conv_from_u, *out, *outb, uchars, uchars_len, &errCode); + + u_char pivot_buffer[ICU_CHUNK_SIZE]; + u_char *pivot, *pivot2; + char *mytarget; + const char *source_limit; + const char *target_limit; + int32_t target_length = 0; + source_limit = *in + *inb; + pivot = pivot2 = pivot_buffer; + mytarget = *out; + target_limit = *out + *outb; + g_icu_opt_func.ucnv_convertEx(conv_out, conv_in, &mytarget, target_limit, in, source_limit, + pivot_buffer, &pivot, &pivot2, pivot_buffer + ICU_CHUNK_SIZE, false, true, &errCode); + target_length = (int32_t)(mytarget - *out); if (errCode > ICU_ZERO_ERROR) { set_errno(errCode); return (size_t)-1; } else { errCode = ICU_ZERO_ERROR; } - g_icu_opt_func.ucnv_close(conv_from_u); + g_icu_opt_func.ucnv_close(conv_in); + g_icu_opt_func.ucnv_close(conv_out); - *out += out_size; - *outb -= out_size; + *out += target_length; + *outb -= target_length; *in += *inb; *inb -= *inb; set_errno(errCode);