Skip to content

Commit

Permalink
馃敤 Repair throw_handler
Browse files Browse the repository at this point in the history
- make a proper error_condition enumeration
- hook into the system_error work
  • Loading branch information
ThePhD committed Apr 10, 2021
1 parent 4178b82 commit 2971750
Show file tree
Hide file tree
Showing 10 changed files with 451 additions and 173 deletions.
66 changes: 66 additions & 0 deletions include/ztd/text/detail/encoding_name.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,72 @@ namespace ztd { namespace text {

namespace __txt_detail {

inline constexpr ::std::string_view __msvc_encoding_name_from_id(int __msc_id) noexcept {
switch (__msc_id) {
case 37:
return "IBM-037"; // EBCDIC US-Canada
case 437:
return "IMB-437"; // OEM United States
case 500:
return "IBM-500"; // EBCDIC Internatinal
case 708:
return "ASMO-708"; // Arabic
case 709:
return "ASMO-449"; // Arabic
case 710:
return "Arabic";
case 720:
return "DOS-720"; // Arabic
case 737:
return "IBM-737"; // Greek
case 775:
return "IBM 775";
case 850:
return "IBM-850";
case 874:
return "Windows-874"; // Thai, Windows
case 855:
return "CP-875"; // EBCDIC Greek, Modern
case 932:
return "SHIT-JIS";
case 1200:
return "UTF-16-LE";
case 1201:
return "UTF-16-BE";
case 1251:
return "Windows-1251"; // Cyrllic
case 1252:
return "Windows-1252"; // Latin-1, West Europe
case 12000:
return "UTF-32-LE";
case 12001:
return "UTF-32-BE";
case 20127:
return "ASCII";
case 50222:
return "ISO-2022-JP";
case 50225:
return "ISO-2022-KR";
case 51932:
return "EUC-JP";
case 51936:
return "EUC-CN";
case 51949:
return "EUC-KR";
case 51950:
return "EUC-CN-Traditional";
case 54936:
return "GB18030";
case 65000:
return "UTF-7";
case 65001:
return "UTF-8";
default:
break;
}
return "UTF-8";
}

inline constexpr bool __is_encoding_name_equal(
::std::string_view __left, ::std::string_view __right) noexcept {
constexpr ::std::string_view __readable_characters
Expand Down
59 changes: 59 additions & 0 deletions include/ztd/text/encoding_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <system_error>
#include <type_traits>
#include <string>
#include <string_view>
#include <exception>
#include <array>

Expand Down Expand Up @@ -97,6 +98,10 @@ namespace ztd { namespace text {
//////
insufficient_output_space = 0x03,
#if 0
/* These error types are not used because they are too specific to Unicode. I suspect that some people will
find them useful for error reporting cases, but it does result in more checking for higher-level APIs. It's
best to leave them off, for now. */

//////
/// Input contains overlong encoding sequence. This is specific to certain encodings, such as Unicode
/// Transformation Formats like UTF-8 where different sequences can end up encoding the same character but are
Expand Down Expand Up @@ -127,6 +132,41 @@ namespace ztd { namespace text {
return __translation[static_cast<::std::size_t>(__txt_detail::__to_underlying(__error_code))];
}

namespace __txt_detail {
//////
/// @brief The encoding category for system_error-style exceptions and errors.
///
/// @remarks This type is generally paired with a std::error_condition.
/////
class __encoding_category : public ::std::error_category {
virtual const char* name() const noexcept override {
return "encoding_error";
}
virtual ::std::string message(int __untyped_error_code) const override {
encoding_error __error_code = static_cast<encoding_error>(__untyped_error_code);
switch (__error_code) {
case encoding_error::ok:
case encoding_error::incomplete_sequence:
case encoding_error::insufficient_output_space:
case encoding_error::invalid_sequence: {
::std::string_view __name = ::ztd::text::to_name(__error_code);
return ::std::string(__name.data(), __name.size());
}
}
return "unrecognized untyped error code";
}

virtual ::std::error_condition default_error_condition(int __untyped_error_code) const noexcept {
return ::std::error_condition(__untyped_error_code, *this);
}
};
} // namespace __txt_detail

inline const ::std::error_category& encoding_category() {
static const __txt_detail::__encoding_category __category = __txt_detail::__encoding_category();
return __category;
}

//////
/// @}
//////
Expand All @@ -137,4 +177,23 @@ namespace ztd { namespace text {

#include <ztd/text/detail/epilogue.hpp>

namespace std {
template <>
struct is_error_condition_enum<::ztd::text::encoding_error> : public ::std::true_type { };

template <>
class hash<::ztd::text::encoding_error> {
private:
using _UnderlyingErrorType = ::std::underlying_type_t<::ztd::text::encoding_error>;

public:
::std::size_t operator()(::ztd::text::encoding_error __error_code) const noexcept(
noexcept(::std::hash<_UnderlyingErrorType> {}(static_cast<_UnderlyingErrorType>(__error_code)))) {
using _UnderlyingErrorType = ::std::underlying_type_t<::ztd::text::encoding_error>;
::std::hash<_UnderlyingErrorType> __hasher {};
return __hasher(static_cast<_UnderlyingErrorType>(__error_code));
}
};
} // namespace std

#endif // ZTD_TEXT_ENCODING_ERROR_HPP
15 changes: 8 additions & 7 deletions include/ztd/text/error_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#include <string_view>
#include <utility>
#include <array>
#include <system_error>

#include <ztd/text/detail/prologue.hpp>

Expand Down Expand Up @@ -305,9 +306,9 @@ namespace ztd { namespace text {
//////
template <typename _Encoding, typename _InputRange, typename _OutputRange, typename _State,
typename _Progress>
constexpr auto operator()(const _Encoding&, encode_result<_InputRange, _OutputRange, _State> __result,
const _Progress&) const noexcept(false) {
throw __result.error_code;
constexpr encode_result<_InputRange, _OutputRange, _State> operator()(const _Encoding&,
encode_result<_InputRange, _OutputRange, _State> __result, const _Progress&) const noexcept(false) {
throw ::std::system_error(static_cast<int>(__result.error_code), ::ztd::text::encoding_category());
}

//////
Expand All @@ -316,9 +317,9 @@ namespace ztd { namespace text {
//////
template <typename _Encoding, typename _InputRange, typename _OutputRange, typename _State,
typename _Progress>
constexpr auto operator()(const _Encoding&, decode_result<_InputRange, _OutputRange, _State> __result,
const _Progress&) const noexcept(false) {
throw __result.error_code;
constexpr decode_result<_InputRange, _OutputRange, _State> operator()(const _Encoding&,
decode_result<_InputRange, _OutputRange, _State> __result, const _Progress&) const noexcept(false) {
throw ::std::system_error(static_cast<int>(__result.error_code), ::ztd::text::encoding_category());
}
};

Expand Down Expand Up @@ -465,7 +466,7 @@ namespace ztd { namespace text {

//////
/// @brief The default error handler for the entire library. Can be configured to use different strategies at build
/// time. Without configuration, it defaults to the ztd::text::replacement_handler .
/// time. Without configuration, it defaults to the ztd::text::replacement_handler.
//////
class default_handler
#if ZTD_TEXT_IS_ON(ZTD_TEXT_DEFAULT_HANDLER_THROWS_I_)
Expand Down
43 changes: 29 additions & 14 deletions include/ztd/text/literal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ namespace ztd { namespace text {
} // namespace __txt_detail

//////
/// @brief The encoding of wide string literals ( e.g. @c "馃憤" ) at compile time.
/// @brief The encoding of string literals ( e.g. @c "馃憤" ) at compile time.
///
//////
class literal : private __txt_detail::__ebco<__txt_detail::__literal> {
Expand Down Expand Up @@ -94,15 +94,15 @@ namespace ztd { namespace text {
//////
/// @brief Whether or not the decode operation can process all forms of input into code point values.
///
/// @remarks The decode step is always injective because every encoding used for literals in C++ needs to be
/// capable of being represented by UCNs.
/// @remarks The decode step should always be injective because every encoding used for literals in C++
/// needs to be capable of being represented by UCNs. Whether or not a platform is a jerk, who knows?
//////
using is_decode_injective = ::std::integral_constant<bool, is_decode_injective_v<__underlying_t>>;
//////
/// @brief Whether or not the encode operation can process all forms of input into code unit values.
///
/// @remarks This is absolutely not guaranteed to be the case, and as such we must check the provided encoding
/// name for wide to be sure.
/// name for us to be sure.
//////
using is_encode_injective = ::std::integral_constant<bool, is_encode_injective_v<__underlying_t>>;

Expand Down Expand Up @@ -182,16 +182,24 @@ namespace ztd { namespace text {
"God's Speed.\n\n"

"This could mangle all of your compile time literal string conversions you are performing. To "
"prevent that from happening, this error is being printed out and to go ahead with the explicit "
"prevent that from happening, this error is being printed out, so that you have the explicit "
"understanding that your life may indeed suck after doing this.\n\n"

"Please add ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT to your command line to "
"ignore "
"this "
"error and we will get right on doing exactly that for you.");
"ignore this error and we will get right on doing exactly that for you.");
#endif
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT_I_)
static_assert(__txt_detail::__always_true_v<_Input> && !__txt_detail::__is_specialization_of_v<__base_t, basic_no_encoding>, "[[ Please read! ]] This text encoding (" ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() "), while recognized, is not supported because it hasn't yet been implemented! You can see all the encodings we have support for in our documentation (https://ztdtext.rtfd.io/en/latest/encodings.html).\n\nIf you need this to be implemented, please reach out at the repository or to the contact addresses in the repository. If you absolutely don't give a damn, specify please add ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT to your command line to ignore this error and we will get right on doing exactly that for you.");
static_assert(__txt_detail::__always_true_v<_Input>
&& !__txt_detail::__is_specialization_of_v<__base_t, basic_no_encoding>,
"[[ Please read! ]] This text encoding ("
ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "), while recognized, is not "
"supported because it hasn't yet been implemented! You can see all the encodings we have "
"support for in our documentation (https://ztdtext.rtfd.io/en/latest/encodings.html).\n\n"

"If you need this to be implemented, please reach out at the repository or to the contact "
"addresses in the repository. If you absolutely don't give a damn, specify please add "
"ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT to your command line to "
"ignore this error and we will get right on doing exactly that for you.");
#endif
__txt_detail::__forwarding_handler<const literal, __txt_detail::__remove_cvref_t<_ErrorHandler>>
__underlying_handler(*this, __error_handler);
Expand Down Expand Up @@ -238,16 +246,23 @@ namespace ztd { namespace text {
"God's Speed.\n\n"

"This could mangle all of your compile time literal string conversions you are performing. To "
"prevent that from happening, this error is being printed out and to go ahead with the explicit "
"prevent that from happening, this error is being printed out, so that you have the explicit "
"understanding that your life may indeed suck after doing this.\n\n"

"Please add ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT to your command line to "
"ignore "
"this "
"error and we will get right on doing exactly that for you.");
"ignore this error and we will get right on doing exactly that for you.");
#endif
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT_I_)
static_assert(__txt_detail::__always_true_v<_Input> && !__txt_detail::__is_specialization_of_v<__base_t, basic_no_encoding>, "[[Please read!]] This text encoding (" ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() "), while recognized, is not supported because it hasn't yet been implemented! You can see all the encodings we have support for in our documentation (https://ztdtext.rtfd.io/en/latest/encodings.html).\n\nIf you need this to be implemented, please reach out at the repository or to the contact addresses in the repository. If you absolutely don't give a damn, specify please add ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT to your command line to ignore this error and we will get right on doing exactly that for you.");
static_assert(__txt_detail::__always_true_v<_Input> && !__txt_detail::__is_specialization_of_v<__base_t, basic_no_encoding>,
"[[ Please read! ]] This text encoding ("
ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "), while recognized, is not "
"supported because it hasn't yet been implemented! You can see all the encodings we have "
"support for in our documentation (https://ztdtext.rtfd.io/en/latest/encodings.html).\n\n"

"If you need this to be implemented, please reach out at the repository or to the contact "
"addresses in the repository. If you absolutely don't give a damn, specify please add "
"ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT to your command line to "
"ignore this error and we will get right on doing exactly that for you.");
#endif
__txt_detail::__forwarding_handler<const literal, __txt_detail::__remove_cvref_t<_ErrorHandler>>
__underlying_handler(*this, __error_handler);
Expand Down
61 changes: 39 additions & 22 deletions include/ztd/text/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
#define ZTD_TEXT_HAS_INCLUDE_I_(...) 0
#endif

#define ZTD_TEXT_TOKEN_TO_STRING_I_(__TOK) #__TOK

#if ZTD_TEXT_HAS_INCLUDE_I_(<version>)
// Can check __has_include and we have the C++20 <version> header
#include <version>
Expand Down Expand Up @@ -498,40 +500,55 @@
#endif

#if defined(ZTD_TEXT_COMPILE_TIME_ENCODING_NAME)
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() ZTD_TEXT_COMPILE_TIME_ENCODING_NAME
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() ZTD_TEXT_COMPILE_TIME_ENCODING_NAME
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_TEXT_COMPILE_TIME_ENCODING_NAME"
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_STD_TEXT_ENCODING_ID_I_)
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() ::std::text_encoding::literal().name()
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME ZTD_TEXT_DEFAULT_ON
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() ::std::text_encoding::literal().name()
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "from std::text_encoding::literal().name()"
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME ZTD_TEXT_DEFAULT_ON
#elif defined(__MSC_EXECUTION_CHARSET_ID)
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() ::ztd::text::__txt_detail::__msvc_encoding_name_from_id(__MSC_EXECUTION_CHARSET_ID)
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "MSVC CodePage ID: " ZTD_TEXT_TOKEN_TO_STRING_I_(__MSC_EXECUTION_CHARSET_ID)
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#elif defined(__GNUC_EXECUTION_CHARSET_NAME)
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() __GNUC_EXECUTION_CHARSET_NAME
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() __GNUC_EXECUTION_CHARSET_NAME
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_()
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_CLANG_I_)
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() "UTF-8"
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() "UTF-8"
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_()
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#else
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() "UTF-8"
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_OFF
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() "UTF-8"
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_()
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_OFF
#endif

#if defined(ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME)
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_ON
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_()
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_ON
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_STD_TEXT_ENCODING_ID_I_)
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() ::std::text_encoding::wide_literal().name()
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() ::std::text_encoding::wide_literal().name()
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "from ::std::text_encoding::wide_literal().name()"
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#elif defined(__GNUC_WIDE_EXECUTION_CHARSET_NAME)
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() __GNUC_WIDE_EXECUTION_CHARSET_NAME
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() __GNUC_WIDE_EXECUTION_CHARSET_NAME
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_()
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_)
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-16"
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-16"
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_()
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#elif (WCHAR_MAX > 0x001FFFFF) && ZTD_TEXT_IS_ON(ZTD_TEXT_WCHAR_T_UTF32_COMPATIBLE_I_)
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-32"
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-32"
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_()
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON
#else
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-32"
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_OFF
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-32"
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_()
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_OFF
#endif

#if defined(ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT)
Expand Down

0 comments on commit 2971750

Please sign in to comment.