From cf762f2a9de26ffc2e222d518e627d7ec548c6ff Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 29 Nov 2022 06:22:36 +0100 Subject: [PATCH] lib/icu/Error: std::system_error with UErrorCode --- src/lib/icu/Collate.cxx | 5 ++- src/lib/icu/Converter.cxx | 12 +++---- src/lib/icu/Error.hxx | 57 ++++++++++++++++++++++++++++++++++ src/lib/icu/Init.cxx | 4 +-- src/lib/icu/Transliterator.cxx | 3 +- src/lib/icu/Util.cxx | 8 +++-- 6 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 src/lib/icu/Error.hxx diff --git a/src/lib/icu/Collate.cxx b/src/lib/icu/Collate.cxx index 84f54fe61..0a329f4de 100644 --- a/src/lib/icu/Collate.cxx +++ b/src/lib/icu/Collate.cxx @@ -22,8 +22,8 @@ #include "config.h" #ifdef HAVE_ICU +#include "Error.hxx" #include "Util.hxx" -#include "util/RuntimeError.hxx" #include #include @@ -62,8 +62,7 @@ IcuCollateInit() UErrorCode code = U_ZERO_ERROR; collator = ucol_open("", &code); if (collator == nullptr) - throw FormatRuntimeError("ucol_open() failed: %s", - u_errorName(code)); + throw ICU::MakeError(code, "ucol_open() failed"); } void diff --git a/src/lib/icu/Converter.cxx b/src/lib/icu/Converter.cxx index 03cdb5611..93d38de4b 100644 --- a/src/lib/icu/Converter.cxx +++ b/src/lib/icu/Converter.cxx @@ -30,6 +30,7 @@ #include #ifdef HAVE_ICU +#include "Error.hxx" #include "Util.hxx" #include "util/AllocatedArray.hxx" #include @@ -55,8 +56,9 @@ IcuConverter::Create(const char *charset) UErrorCode code = U_ZERO_ERROR; UConverter *converter = ucnv_open(charset, &code); if (converter == nullptr) - throw std::runtime_error(FmtBuffer<256>(FMT_STRING("Failed to initialize charset '{}': {}"), - charset, u_errorName(code))); + throw ICU::MakeError(code, + FmtBuffer<256>(FMT_STRING("Failed to initialize charset '{}'"), + charset)); return std::unique_ptr(new IcuConverter(converter)); #elif defined(HAVE_ICONV) @@ -120,8 +122,7 @@ IcuConverter::ToUTF8(std::string_view s) const &source, source + s.size(), nullptr, true, &code); if (code != U_ZERO_ERROR) - throw std::runtime_error(FmtBuffer<256>(FMT_STRING("Failed to convert to Unicode: {}"), - u_errorName(code))); + throw ICU::MakeError(code, "Failed to convert to Unicode"); const size_t target_length = target - buffer; return UCharToUTF8({buffer, target_length}); @@ -150,8 +151,7 @@ IcuConverter::FromUTF8(std::string_view s) const nullptr, true, &code); if (code != U_ZERO_ERROR) - throw std::runtime_error(FmtBuffer<256>(FMT_STRING("Failed to convert from Unicode: {}"), - u_errorName(code))); + throw ICU::MakeError(code, "Failed to convert from Unicode"); return {{buffer, size_t(target - buffer)}}; diff --git a/src/lib/icu/Error.hxx b/src/lib/icu/Error.hxx new file mode 100644 index 000000000..5b7b95097 --- /dev/null +++ b/src/lib/icu/Error.hxx @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +#include + +namespace ICU { + +class ErrorCategory final : public std::error_category { +public: + const char *name() const noexcept override { + return "icu"; + } + + std::string message(int condition) const override { + return u_errorName(static_cast(condition)); + } +}; + +inline ErrorCategory error_category; + +inline std::system_error +MakeError(UErrorCode code, const char *msg) noexcept +{ + return std::system_error(static_cast(code), error_category, msg); +} + +} // namespace Curl diff --git a/src/lib/icu/Init.cxx b/src/lib/icu/Init.cxx index dda779597..78bec369c 100644 --- a/src/lib/icu/Init.cxx +++ b/src/lib/icu/Init.cxx @@ -20,6 +20,7 @@ #include "Init.hxx" #include "Collate.hxx" #include "Canonicalize.hxx" +#include "Error.hxx" #include "util/RuntimeError.hxx" #include @@ -30,8 +31,7 @@ IcuInit() UErrorCode code = U_ZERO_ERROR; u_init(&code); if (U_FAILURE(code)) - throw FormatRuntimeError("u_init() failed: %s", - u_errorName(code)); + throw ICU::MakeError(code, "u_init() failed"); IcuCollateInit(); IcuCanonicalizeInit(); diff --git a/src/lib/icu/Transliterator.cxx b/src/lib/icu/Transliterator.cxx index 71121dca2..954d1a828 100644 --- a/src/lib/icu/Transliterator.cxx +++ b/src/lib/icu/Transliterator.cxx @@ -18,6 +18,7 @@ */ #include "Transliterator.hxx" +#include "Error.hxx" #include "util/AllocatedArray.hxx" #include // for std::copy() @@ -34,7 +35,7 @@ OpenTransliterator(std::basic_string_view id, rules.data(), rules.size(), nullptr, &error_code); if (t == nullptr) - throw std::runtime_error(u_errorName(error_code)); + throw ICU::MakeError(error_code, "utrans_openU() failed"); return t; } diff --git a/src/lib/icu/Util.cxx b/src/lib/icu/Util.cxx index e748ef262..5e8eb70ab 100644 --- a/src/lib/icu/Util.cxx +++ b/src/lib/icu/Util.cxx @@ -18,6 +18,7 @@ */ #include "Util.hxx" +#include "Error.hxx" #include "util/AllocatedString.hxx" #include "util/AllocatedArray.hxx" @@ -25,7 +26,6 @@ #include #include -#include #include @@ -41,7 +41,8 @@ UCharFromUTF8(std::string_view src) src.data(), src.size(), &error_code); if (U_FAILURE(error_code)) - throw std::runtime_error(u_errorName(error_code)); + throw ICU::MakeError(error_code, + "Conversion from UTF-8 failed"); dest.SetSize(dest_length); return dest; @@ -61,7 +62,8 @@ UCharToUTF8(std::basic_string_view src) src.data(), src.size(), &error_code); if (U_FAILURE(error_code)) - throw std::runtime_error(u_errorName(error_code)); + throw ICU::MakeError(error_code, + "Conversion to UTF-8 failed"); dest[dest_length] = 0; return AllocatedString::Donate(dest.release());