#include #include #include #include #include #include #include #include #include using namespace ::std::literals::string_literals; int main() { int unsigned error_count = 0x0u; auto const log_unit = [](::std::string const& identifier) noexcept -> void { ::std::cerr <<"\n\x1B[38;5;75mtesting\x1B[0m " << identifier <<"\n\n"; }; auto const check = [&error_count](long const line, auto const& left_value, auto const& right_value) { ::std::cerr << " " << ::std::setbase(0xA) << line << ". "; auto const okay = [](auto const& left_reference, auto const& right_reference) -> bool { auto const get_value = [](auto const& reference) -> auto { using T = ::std::remove_cv_t<::std::remove_reference_t>; if constexpr (::std::is_same_v) { return static_cast<::std::uintmax_t>(static_cast(reference)); } else if constexpr (::std::is_signed_v) { return static_cast<::std::intmax_t>(reference); } else if constexpr (::std::is_unsigned_v) { return static_cast<::std::uintmax_t>(reference); } else { return static_cast(reference); } }; auto const left_value = get_value(left_reference); auto const right_value = get_value(right_reference); ::std::cerr << "" << ::std::setbase(0x10) << left_value << " equals " << right_value << "... "; return left_value == right_value; }(left_value, right_value); if (!okay) { ::std::cerr << "\x1B[38;5;161mfalse\x1B[0m\n"; ++error_count; } else { ::std::cerr <<"\x1B[38;5;77mtrue\x1B[0m\n"; } }; #define check(left_value, right_value) (check(__LINE__, (left_value), (right_value))) ::std::cerr << "u8c-check " << u8c_VERSION << "\n"; [&] { log_unit("UTF-8"); ::std::uint_least32_t const source[] { UINT32_C(0x0026), UINT32_C(0x00F0), UINT32_C(0x218A), UINT32_C(0x0001F480), UINT32_C(0xD800), UINT32_C(0x0010FFFF), UINT32_C(0x00110000), }; auto const source_length = sizeof (source) / sizeof (source[0x0]); size_t const utf8_buffer_length = ::u8c_encode_utf8_length(source, source_length); check(utf8_buffer_length, 0x14u); auto const utf8_buffer = new char[utf8_buffer_length]; ::u8c_encode_utf8(utf8_buffer, source, source_length); check(utf8_buffer[0x00], '\x26'); check(utf8_buffer[0x01], '\xC3'); check(utf8_buffer[0x02], '\xB0'); check(utf8_buffer[0x03], '\xE2'); check(utf8_buffer[0x04], '\x86'); check(utf8_buffer[0x05], '\x8A'); check(utf8_buffer[0x06], '\xF0'); check(utf8_buffer[0x07], '\x9F'); check(utf8_buffer[0x08], '\x92'); check(utf8_buffer[0x09], '\x80'); check(utf8_buffer[0x0A], '\xEF'); check(utf8_buffer[0x0B], '\xBF'); check(utf8_buffer[0x0C], '\xBD'); check(utf8_buffer[0x0D], '\xF4'); check(utf8_buffer[0x0E], '\x8F'); check(utf8_buffer[0x0F], '\xBF'); check(utf8_buffer[0x10], '\xBF'); check(utf8_buffer[0x11], '\xEF'); check(utf8_buffer[0x12], '\xBF'); check(utf8_buffer[0x13], '\xBD'); auto const utf32_buffer_length = ::u8c_decode_utf8_length(utf8_buffer, utf8_buffer_length); check(utf32_buffer_length, 0x7u); auto const utf32_buffer = new ::std::uint_least32_t[utf32_buffer_length]; ::u8c_decode_utf8(utf32_buffer, utf8_buffer, utf8_buffer_length); check(utf32_buffer[0x0], UINT32_C(0x0026)); check(utf32_buffer[0x1], UINT32_C(0x00F0)); check(utf32_buffer[0x2], UINT32_C(0x218A)); check(utf32_buffer[0x3], UINT32_C(0x0001F480)); check(utf32_buffer[0x4], UINT32_C(0xFFFD)); delete[] utf8_buffer; delete[] utf32_buffer; }(); [&] { log_unit("UTF-16"); ::std::uint_least32_t const source[] { UINT32_C(0x0026), UINT32_C(0x00F0), UINT32_C(0x218A), UINT32_C(0x0001F480), UINT32_C(0xD800), UINT32_C(0x0010FFFF), UINT32_C(0x00110000), }; auto const source_length = sizeof (source) / sizeof (source[0x0]); auto const utf16_buffer_length = ::u8c_encode_utf16_length(source, source_length); check(utf16_buffer_length, 0x9u); auto const utf16_buffer = new ::std::uint_least16_t[utf16_buffer_length]; ::u8c_encode_utf16(utf16_buffer, source, source_length); check(utf16_buffer[0x0], UINT16_C(0x0026)); check(utf16_buffer[0x1], UINT16_C(0x00F0)); check(utf16_buffer[0x2], UINT16_C(0x218A)); check(utf16_buffer[0x3], UINT16_C(0xD83D)); check(utf16_buffer[0x4], UINT16_C(0xDC80)); check(utf16_buffer[0x5], UINT16_C(0xFFFD)); check(utf16_buffer[0x6], UINT16_C(0xDBFF)); check(utf16_buffer[0x7], UINT16_C(0xDFFF)); check(utf16_buffer[0x8], UINT16_C(0xFFFD)); auto const utf32_buffer_length = ::u8c_decode_utf16_length(utf16_buffer, utf16_buffer_length); check(utf32_buffer_length, 0x7u); auto const utf32_buffer = new ::std::uint_least32_t[utf32_buffer_length]; ::u8c_decode_utf16(utf32_buffer, utf16_buffer, utf16_buffer_length); check(utf32_buffer[0x0], UINT32_C(0x0026)); check(utf32_buffer[0x1], UINT32_C(0x00F0)); check(utf32_buffer[0x2], UINT32_C(0x218A)); check(utf32_buffer[0x3], UINT32_C(0x0001F480)); check(utf32_buffer[0x4], UINT32_C(0xFFFD)); check(utf32_buffer[0x5], UINT32_C(0x0010FFFF)); check(utf32_buffer[0x6], UINT32_C(0xFFFD)); delete[] utf16_buffer; delete[] utf32_buffer; }(); ::std::cerr << "\ndone - " << error_count << " error(s)\n"; return error_count != 0x0u ? EXIT_FAILURE : EXIT_SUCCESS; }