6inline ::i32 utf8_o(::i8 cExtraBytes)
30inline ::i8 utf8_e(::u8 c)
35 else if (c < 192 + 32)
37 else if (c < 192 + 32 + 16)
39 else if (c < 192 + 32 + 16 + 8)
41 else if (c < 192 + 32 + 16 + 8 + 4)
51inline character_count wd32_to_ansi_char_len(::wd32_character wch)
62 else if (wch <= 0x07FF)
67 else if (wch <= 0xFFFF)
72 else if (wch <= 0x10FFFF)
84inline character_count wd16_to_wd32_char(::wd32_character * output, const ::wd16_character * input, character_count len)
94 auto _1stSurrogateCandidate = input[0];
96 if (_1stSurrogateCandidate == 0)
103 if (utf16_is_2nd_surrogate(_1stSurrogateCandidate))
111 else if (utf16_is_1st_surrogate(_1stSurrogateCandidate))
121 auto _2ndSurrogateCandidate = input[1];
123 if (utf16_is_2nd_surrogate(_2ndSurrogateCandidate))
126 *output = utf16_surrogate_to_utf32(_1stSurrogateCandidate, _2ndSurrogateCandidate);
142 *output = _1stSurrogateCandidate;
151inline character_count ansi_to_wd32_char(::wd32_character * output, const_char_pointer input, character_count srclen)
154 ::wd32_character wd32ch = 0;
157 ::i8 extraBytesToRead = utf8_e(*input);
158 ::i32 len = extraBytesToRead + 1;
159 if (srclen < len)
return -1;
160 if (*input ==
'\0')
return -1;
161 switch (extraBytesToRead)
165 if (c ==
'\0')
return -1;
171 if (c ==
'\0')
return -1;
177 if (c ==
'\0')
return -1;
183 if (c ==
'\0')
return -1;
189 if (c ==
'\0')
return -1;
195 if (c ==
'\0')
return -1;
200 wd32ch -= (::wd32_character)utf8_o(extraBytesToRead);
208inline ::i64 _ansi_to_wd32_char(const_char_pointer *ppsz, character_count * psrclen)
211 ::wd32_character wd32ch = 0;
213 auto used_len = ansi_to_wd32_char(&wd32ch, *ppsz, *psrclen);
224 *psrclen -= used_len;
232#define UNI_REPLACEMENT_CHAR (::wd32_character)0x0000FFFD
233#define UNI_MAX_BMP (::wd32_character)0x0000FFFF
234#define UNI_MAX_UTF16 (::wd32_character)0x0010FFFF
235#define UNI_MAX_UTF32 (::wd32_character)0x7FFFFFFF
236#define UNI_MAX_LEGAL_UTF32 (::wd32_character)0x0010FFFF
237#define UNI_SUR_HIGH_START (::wd32_character)0xD800
238#define UNI_SUR_HIGH_END (::wd32_character)0xDBFF
239#define UNI_SUR_LOW_START (::wd32_character)0xDC00
240#define UNI_SUR_LOW_END (::wd32_character)0xDFFF
292inline character_count wd32_to_wd16_char(::wd16_character * target, ::wd32_character wd32ch)
295 const ::i32 halfShift = 10;
296 const ::wd32_character halfBase = 0x0010000UL;
297 const ::wd32_character halfMask = 0x3FFUL;
299 if (wd32ch <= UNI_MAX_BMP)
304 if (wd32ch >= UNI_SUR_HIGH_START && wd32ch <= UNI_SUR_LOW_END)
314 *target = (::wd16_character)wd32ch;
319 else if (wd32ch > UNI_MAX_LEGAL_UTF32)
328 *target++ = (::wd16_character)((wd32ch >> halfShift) + UNI_SUR_HIGH_START);
330 *target = (::wd16_character)((wd32ch & halfMask) + UNI_SUR_LOW_START);
337inline character_count wd16_to_ansi_char_len(const ::wd16_character ** ppu16a, character_count * plen)
340 ::wd32_character wd32ch;
342 auto used_len = wd16_to_wd32_char(&wd32ch, *ppu16a, *plen);
355 return wd32_to_ansi_char_len(wd32ch);
360inline character_count wd16_to_ansi_char(char_pointer psz, const ::wd16_character ** ppu16a, character_count * plen)
363 ::wd32_character wd32ch;
365 auto used_len = wd16_to_wd32_char(&wd32ch, *ppu16a, *plen);
378 return wd32_to_ansi_char(psz, wd32ch);
383inline character_count wd16_to_wd32_char_len(const ::wd16_character * input, character_count len)
393 auto _1stSurrogateCandidate = input[0];
395 if (_1stSurrogateCandidate == 0)
402 if (utf16_is_2nd_surrogate(_1stSurrogateCandidate))
410 else if (utf16_is_1st_surrogate(_1stSurrogateCandidate))
420 auto _2ndSurrogateCandidate = input[1];
422 if (utf16_is_2nd_surrogate(_2ndSurrogateCandidate))
446inline character_count wd32_to_ansi_char(char_pointer psz, ::wd32_character wch)
453 else if (wch <= 0x7F)
459 else if (wch <= 0x07FF)
462 psz[0] = (::i8)(((wch >> 6) & 0x1F) | 0xC0);
463 psz[1] = (::i8)(((wch >> 0) & 0x3F) | 0x80);
466 else if (wch <= 0xFFFF)
469 psz[0] = (::i8)(((wch >> 12) & 0x0F) | 0xE0);
470 psz[1] = (::i8)(((wch >> 6) & 0x3F) | 0x80);
471 psz[2] = (::i8)(((wch >> 0) & 0x3F) | 0x80);
474 else if (wch <= 0x10FFFF)
477 psz[0] = (::i8)(((wch >> 18) & 0x07) | 0xF0);
478 psz[1] = (::i8)(((wch >> 12) & 0x3F) | 0x80);
479 psz[2] = (::i8)(((wch >> 6) & 0x3F) | 0x80);
480 psz[3] = (::i8)(((wch >> 0) & 0x3F) | 0x80);
490#if WCHAR_T_SIZE == 16
493inline character_count utf8_to_unichar_len(const_char_pointer psz) {
return ansi_to_wd16_len(psz, string_safe_length(psz)); }
494inline character_count utf8_to_unichar_len(const_char_pointer psz, character_count srclen) {
return ansi_to_wd16_len(psz, srclen); }
495inline character_count utf8_to_unichar(::wd16_character * pwsz, const_char_pointer psz) {
return ansi_to_wd16(pwsz, psz, string_safe_length(psz)); }
496inline character_count utf8_to_unichar(::wd16_character * pwsz, const_char_pointer psz, character_count srclen) {
return ansi_to_wd16(pwsz, psz, srclen); }
499inline character_count unichar_to_utf8_len(const ::wd16_character * pwsz) {
return wd16_to_ansi_len(pwsz, string_safe_length(pwsz)); }
500inline character_count unichar_to_utf8_len(const ::wd16_character * pwsz, character_count srclen) {
return wd16_to_ansi_len(pwsz, srclen); }
501inline character_count unichar_to_utf8(char_pointer psz, const ::wd16_character * pwsz) {
return wd16_to_ansi(psz, pwsz, string_safe_length(pwsz)); }
502inline character_count unichar_to_utf8(char_pointer psz, const ::wd16_character * pwsz, character_count srclen) {
return wd16_to_ansi(psz, pwsz, srclen); }
508inline character_count utf8_to_unichar_len(const_char_pointer psz, character_count srclen) {
return ansi_to_wd32_len(psz, srclen); }
509inline character_count utf8_to_unichar(::wd32_character * pwsz, const_char_pointer psz, character_count srclen) {
return ansi_to_wd32(pwsz, psz, srclen); }
512inline character_count unichar_to_utf8_len(const ::wd32_character * pwsz, character_count srclen) {
return wd32_to_ansi_len(pwsz, srclen); }
513inline character_count unichar_to_utf8(char_pointer psz, const ::wd32_character * pwsz, character_count srclen) {
return wd32_to_ansi(psz, pwsz, srclen); }