From 2dcf244531b4cd0b5df418e3725978f32fa02e99 Mon Sep 17 00:00:00 2001 From: liwei Date: Fri, 24 Apr 2026 06:48:46 -0700 Subject: [PATCH] Refactor IO exceptions: remove ios_defs::failure and introduce io_error base class - Removed ios_defs::failure from include/io/io_base.h - Introduced IOv2::io_error as a base class for all IO exceptions in include/common/defs.h - Updated device_error, cvt_error, stream_error, and eof_error to inherit from io_error - Corrected exception types thrown in io_state_and_exp::clear() - Updated tests to reflect the new exception hierarchy --- include/common/defs.h | 31 +++- include/io/io_base.h | 36 +---- test/io/io_base/test_io_base.cpp | 14 -- test/io/io_base/test_io_base_failure.cpp | 146 ------------------ .../test_io_state_and_exp.cpp | 2 +- 5 files changed, 32 insertions(+), 197 deletions(-) delete mode 100755 test/io/io_base/test_io_base_failure.cpp diff --git a/include/common/defs.h b/include/common/defs.h index c00e7fa7..38045875 100755 --- a/include/common/defs.h +++ b/include/common/defs.h @@ -32,6 +32,20 @@ namespace IOv2 */ static constexpr size_t SIMD_PADDING_BYTES = 32; + /** + * @lang{ZH} + * IO 相关异常的基类。 + * @endif + * + * @lang{EN} + * Base class for IO-related exceptions. + * @endif + */ + struct io_error : std::runtime_error + { + using std::runtime_error::runtime_error; + }; + /** * @lang{ZH} * 设备相关错误的异常类。 @@ -41,9 +55,9 @@ namespace IOv2 * Exception class for device-related errors. * @endif */ - struct device_error : std::runtime_error + struct device_error : io_error { - using std::runtime_error::runtime_error; + using io_error::io_error; }; /** @@ -55,9 +69,9 @@ namespace IOv2 * Exception class for errors during conversion processes (e.g., code conversion, compression, encryption). * @endif */ - struct cvt_error : std::runtime_error + struct cvt_error : io_error { - using std::runtime_error::runtime_error; + using io_error::io_error; }; /** @@ -69,9 +83,10 @@ namespace IOv2 * Exception class for End-Of-File (EOF). * @endif */ - struct eof_error : std::exception + struct eof_error : io_error { - using std::exception::exception; + eof_error() : io_error("end of file") {} + using io_error::io_error; }; /** @@ -83,8 +98,8 @@ namespace IOv2 * Exception class for stream operation errors. * @endif */ - struct stream_error : std::runtime_error + struct stream_error : io_error { - using std::runtime_error::runtime_error; + using io_error::io_error; }; } diff --git a/include/io/io_base.h b/include/io/io_base.h index 423b29e7..30724589 100755 --- a/include/io/io_base.h +++ b/include/io/io_base.h @@ -44,26 +44,6 @@ namespace ios_defs constexpr static iostate cvtfailbit = 1L << 2; constexpr static iostate strfailbit = 1L << 3; constexpr static iostate otherfailbit = 1L << 4; - - class failure : public std::runtime_error - { - public: - explicit failure(const std::string& msg, const std::error_code& ec = std::io_errc::stream) - : std::runtime_error(msg) - , m_ec(ec) {} - - explicit failure(const char* msg, const std::error_code& ec = std::io_errc::stream) - : std::runtime_error(msg) - , m_ec(ec) {} - - virtual const std::error_code& code() const noexcept - { - return m_ec; - } - - private: - std::error_code m_ec; - }; }; struct io_state_and_exp @@ -79,39 +59,39 @@ struct io_state_and_exp if ((m_stream_state & ios_defs::otherfailbit) == ios_defs::goodbit) m_exp_other_fail = std::exception_ptr{}; ios_defs::iostate state_in_exp = m_exception & m_stream_state; - bool need_throw_exp = false; if (state_in_exp & ios_defs::devfailbit) { - need_throw_exp = true; if (m_exp_dev_fail) std::rethrow_exception(std::exchange(m_exp_dev_fail, nullptr)); + else + throw device_error("device failure bit has been set"); } else if (state_in_exp & ios_defs::cvtfailbit) { - need_throw_exp = true; if (m_exp_cvt_fail) std::rethrow_exception(std::exchange(m_exp_cvt_fail, nullptr)); + else + throw cvt_error("converter failure bit has been set"); } else if (state_in_exp & ios_defs::strfailbit) { - need_throw_exp = true; if (m_exp_str_fail) std::rethrow_exception(std::exchange(m_exp_str_fail, nullptr)); + else + throw stream_error("stream failure bit has been set"); } else if (state_in_exp & ios_defs::otherfailbit) { - need_throw_exp = true; if (m_exp_other_fail) std::rethrow_exception(std::exchange(m_exp_other_fail, nullptr)); + else + throw stream_error("other failure bit has been set"); } else if (state_in_exp & ios_defs::eofbit) { if (!std::current_exception()) throw eof_error{}; } - - if (need_throw_exp) - throw ios_defs::failure("failure bit has been set"); } void setstate(ios_defs::iostate s) { clear(rdstate() | s); } diff --git a/test/io/io_base/test_io_base.cpp b/test/io/io_base/test_io_base.cpp index 35d964f6..3710806d 100755 --- a/test/io/io_base/test_io_base.cpp +++ b/test/io/io_base/test_io_base.cpp @@ -1,10 +1,3 @@ -void test_io_base_failure_1(); -void test_io_base_failure_2(); -void test_io_base_failure_what_1(); -void test_io_base_failure_what_2(); -void test_io_base_failure_what_3(); -void test_io_base_failure_what_4(); - void test_io_base_char_fill_1(); void test_io_base_wchar_t_fill_1(); @@ -18,13 +11,6 @@ void test_io_base_manipulators(); void test_io_base() { - test_io_base_failure_1(); - test_io_base_failure_2(); - test_io_base_failure_what_1(); - test_io_base_failure_what_2(); - test_io_base_failure_what_3(); - test_io_base_failure_what_4(); - test_io_base_char_fill_1(); test_io_base_wchar_t_fill_1(); diff --git a/test/io/io_base/test_io_base_failure.cpp b/test/io/io_base/test_io_base_failure.cpp deleted file mode 100755 index af661b84..00000000 --- a/test/io/io_base/test_io_base_failure.cpp +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include -#include -#include -#include -#include -namespace -{ -struct E : IOv2::ios_defs::failure -{ - E(const char* s) - : IOv2::ios_defs::failure(s, std::make_error_code(std::io_errc::stream)) { } -}; -} - -void test_io_base_failure_1() -{ - dump_info("Test ios_base::failure case 1..."); - - { - IOv2::ios_defs::failure e("io error"); - if (std::string(e.what()).find("io error") == std::string::npos) - throw std::runtime_error("ios_base::failure check fail"); - } - { - E e("io error"); - if (std::string(e.what()).find("io error") == std::string::npos) - throw std::runtime_error("ios_base::failure check fail"); - } - - dump_info("Done\n"); -} - -void test_io_base_failure_2() -{ - dump_info("Test ios_base::failure case 2..."); - - std::error_code ec, def_ec; - ec = std::make_error_code(std::errc::executable_format_error); - def_ec = std::io_errc::stream; - IOv2::ios_defs::failure e1("string literal"); - if (e1.code() != def_ec) throw std::runtime_error("ios_base::failure check fail"); - IOv2::ios_defs::failure e2(std::string("std::string")); - if (e2.code() != def_ec) throw std::runtime_error("ios_base::failure check fail"); - IOv2::ios_defs::failure e3("string literal", ec); - if (e3.code() != ec) throw std::runtime_error("ios_base::failure check fail"); - IOv2::ios_defs::failure e4(std::string("std::string"), ec); - if (e4.code() != ec) throw std::runtime_error("ios_base::failure check fail"); - - dump_info("Done\n"); -} - -void test_io_base_failure_what_1() -{ - dump_info("Test ios_base::failure::what case 1..."); - - std::string s("lack of sunlight, no water error"); - - // 1 - IOv2::ios_defs::failure obj1 = IOv2::ios_defs::failure(s); - - // 2 - IOv2::ios_defs::failure obj2(s); - - if (obj1.what() != s) throw std::runtime_error("ios_base::failure check fail"); - if (obj2.what() != s) throw std::runtime_error("ios_base::failure check fail"); - - dump_info("Done\n"); -} - -namespace -{ -class fuzzy_logic : public IOv2::ios_defs::failure -{ -public: - fuzzy_logic() : IOv2::ios_defs::failure("whoa") { } -}; -} - -void test_io_base_failure_what_2() -{ - dump_info("Test ios_base::failure::what case 2..."); - - try - { - throw fuzzy_logic(); - } - catch(const fuzzy_logic& obj) - { - if (obj.what() != std::string("whoa")) - throw std::runtime_error("ios_base::failure check fail"); - } - - dump_info("Done\n"); -} - -namespace -{ - void allocate_on_stack(void) - { - const size_t num = 512; - char array[num]; - for (size_t i = 0; i < num; i++) - array[i]=0; - for (size_t i = 0; i < num; i++) - array[i]=array[i]; // Suppress unused warning. - } -} -void test_io_base_failure_what_3() -{ - dump_info("Test ios_base::failure::what case 3..."); - const std::string s("CA ISO emergency once again:immediate power down"); - const char* strlit1 = "wish I lived in Palo Alto"; - const char* strlit2 = "...or Santa Barbara"; - IOv2::ios_defs::failure obj1(s); - - { - const std::string s2(strlit1); - IOv2::ios_defs::failure obj2(s2); - obj1 = obj2; - } - allocate_on_stack(); - if (std::strcmp(strlit1, obj1.what()) != 0) throw std::runtime_error("ios_base::failure check fail"); - - { - const std::string s3(strlit2); - IOv2::ios_defs::failure obj3 = IOv2::ios_defs::failure(s3); - obj1 = obj3; - } - if (std::strcmp(strlit2, obj1.what()) != 0) throw std::runtime_error("ios_base::failure check fail"); - - dump_info("Done\n"); -} - -void test_io_base_failure_what_4() -{ - dump_info("Test ios_base::failure::what case 4..."); - - typedef IOv2::ios_defs::failure test_type; - - const std::string xxx(10000, 'x'); - test_type t(xxx); - if (std::strcmp(t.what(), xxx.c_str()) != 0) throw std::runtime_error("ios_base::failure check fail"); - - dump_info("Done\n"); -} \ No newline at end of file diff --git a/test/io/io_state_and_exp/test_io_state_and_exp.cpp b/test/io/io_state_and_exp/test_io_state_and_exp.cpp index c9367aa6..c3a429d0 100755 --- a/test/io/io_state_and_exp/test_io_state_and_exp.cpp +++ b/test/io/io_state_and_exp/test_io_state_and_exp.cpp @@ -34,7 +34,7 @@ void test_io_state_and_exp_1() dump_info("Unreachable code\n"); std::abort(); } - catch (IOv2::ios_defs::failure&) + catch (IOv2::cvt_error&) { iostate02 = ios_01.exceptions(); }