diff options
Diffstat (limited to 'contrib/replxx/src/conversion.cxx')
-rw-r--r-- | contrib/replxx/src/conversion.cxx | 86 |
1 files changed, 56 insertions, 30 deletions
diff --git a/contrib/replxx/src/conversion.cxx b/contrib/replxx/src/conversion.cxx index bcdbe048e..f629f910e 100644 --- a/contrib/replxx/src/conversion.cxx +++ b/contrib/replxx/src/conversion.cxx @@ -2,8 +2,9 @@ #include <string> #include <cstring> #include <cctype> -#include <locale.h> +#include <clocale> +#include "unicode/utf8.h" #include "conversion.hxx" #ifdef _WIN32 @@ -44,20 +45,38 @@ bool is8BitEncoding( is_8bit_encoding() ); ConversionResult copyString8to32(char32_t* dst, int dstSize, int& dstCount, const char* src) { ConversionResult res = ConversionResult::conversionOK; if ( ! locale::is8BitEncoding ) { - const UTF8* sourceStart = reinterpret_cast<const UTF8*>(src); - const UTF8* sourceEnd = sourceStart + strlen(src); - UTF32* targetStart = reinterpret_cast<UTF32*>(dst); - UTF32* targetEnd = targetStart + dstSize; - - res = ConvertUTF8toUTF32( - &sourceStart, sourceEnd, &targetStart, targetEnd, lenientConversion); + auto sourceStart = reinterpret_cast<const unsigned char*>(src); + auto slen = strlen(src); + auto targetStart = reinterpret_cast<UChar32*>(dst); + int i = 0, j = 0; + + while (i < slen && j < dstSize) { + UChar32 uc; + auto prev_i = i; + U8_NEXT (sourceStart, i, slen, uc); + + if (uc <= 0) { + if (U8_IS_LEAD (sourceStart[prev_i])) { + auto lead_byte = sourceStart[prev_i]; + auto trailing_bytes = (((uint8_t)(lead_byte)>=0xc2)+ + ((uint8_t)(lead_byte)>=0xe0)+ + ((uint8_t)(lead_byte)>=0xf0)); + + if (trailing_bytes + i > slen) { + return ConversionResult::sourceExhausted; + } + } + + /* Replace with 0xFFFD */ + uc = 0x0000FFFD; + } + targetStart[j++] = uc; + } - if (res == conversionOK) { - dstCount = static_cast<int>( targetStart - reinterpret_cast<UTF32*>( dst ) ); + dstCount = j; - if (dstCount < dstSize) { - *targetStart = 0; - } + if (j < dstSize) { + targetStart[j] = 0; } } else { for ( dstCount = 0; ( dstCount < dstSize ) && src[dstCount]; ++ dstCount ) { @@ -69,26 +88,32 @@ ConversionResult copyString8to32(char32_t* dst, int dstSize, int& dstCount, cons ConversionResult copyString8to32(char32_t* dst, int dstSize, int& dstCount, const char8_t* src) { return copyString8to32( - dst, dstSize, dstCount, reinterpret_cast<const char*>(src) + dst, dstSize, dstCount, reinterpret_cast<const char*>(src) ); } -int copyString32to8( char* dst, int dstSize, const char32_t* src, int srcSize ) { - int resCount( 0 ); +int copyString32to8( + char* dst, int dstSize, const char32_t* src, int srcSize +) { + int resCount = 0; + if ( ! locale::is8BitEncoding ) { - const UTF32* sourceStart = reinterpret_cast<const UTF32*>(src); - const UTF32* sourceEnd = sourceStart + srcSize; - UTF8* targetStart = reinterpret_cast<UTF8*>(dst); - UTF8* targetEnd = targetStart + dstSize; - - ConversionResult res = ConvertUTF32toUTF8( - &sourceStart, sourceEnd, &targetStart, targetEnd, lenientConversion - ); - - if ( res == conversionOK ) { - resCount = static_cast<int>( targetStart - reinterpret_cast<UTF8*>( dst ) ); - if ( resCount < dstSize ) { - *targetStart = 0; + int j = 0; + UBool is_error = 0; + + for (auto i = 0; i < srcSize; i ++) { + U8_APPEND ((uint8_t *)dst, j, dstSize, src[i], is_error); + + if (is_error) { + break; + } + } + + if (!is_error) { + resCount = j; + + if (j < dstSize) { + dst[j] = '\0'; } } } else { @@ -101,7 +126,8 @@ int copyString32to8( char* dst, int dstSize, const char32_t* src, int srcSize ) dst[i] = 0; } } - return ( resCount ); + + return resCount; } } |