refactor: finish Windows encoding namespace.
- finish Windows encoding namespace. - add std::expected polyfill for help.
This commit is contained in:
@ -65,6 +65,7 @@ FILES
|
||||
yycc/patch/path.hpp
|
||||
yycc/patch/contains.hpp
|
||||
yycc/patch/starts_ends_with.hpp
|
||||
yycc/patch/expected.hpp
|
||||
yycc/encoding/utf.hpp
|
||||
yycc/encoding/windows.hpp
|
||||
yycc/encoding/iconv.hpp
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "utf.hpp"
|
||||
#include "../macro/feature_probe.hpp"
|
||||
#include <locale>
|
||||
|
||||
#define NS_YYCC_STRING ::yycc::string
|
||||
#define NS_YYCC_PATCH_EXPECTED ::yycc::patch::expected
|
||||
|
||||
namespace yycc::encoding::utf {
|
||||
|
||||
@ -125,14 +125,13 @@ namespace yycc::encoding::utf {
|
||||
#pragma region Help Macros
|
||||
|
||||
#define CONVFN_TYPE1(fct_name, src_char_type, dst_char_type) \
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED; \
|
||||
auto rv = priv_##fct_name(src); \
|
||||
if (const auto* ptr = std::get_if<std::basic_string<dst_char_type>>(&rv)) { \
|
||||
dst = std::move(*ptr); \
|
||||
if (expected::is_value(rv)) { \
|
||||
dst = std::move(expected::get_value(rv)); \
|
||||
return true; \
|
||||
} else if (const auto* ptr = std::get_if<ConvError>(&rv)) { \
|
||||
return false; \
|
||||
} else { \
|
||||
throw std::runtime_error("unreachable code"); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CONVFN_TYPE2(fct_name, src_char_type, dst_char_type) \
|
||||
|
@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
#include <yycc/string.hpp>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
#include "../string.hpp"
|
||||
#include "../patch/expected.hpp"
|
||||
|
||||
#define NS_YYCC_STRING ::yycc::string
|
||||
#define NS_YYCC_PATCH_EXPECTED ::yycc::patch::expected
|
||||
|
||||
namespace yycc::encoding::utf {
|
||||
|
||||
@ -11,8 +11,8 @@ namespace yycc::encoding::utf {
|
||||
struct ConvError {};
|
||||
|
||||
/// @private
|
||||
template<typename T, std::enable_if_t<!std::is_same_v<T, ConvError>, int> = 0>
|
||||
using ConvResult = std::variant<T, ConvError>;
|
||||
template<typename T>
|
||||
using ConvResult = NS_YYCC_PATCH_EXPECTED::Expected<T, ConvError>;
|
||||
|
||||
// UTF8 -> UTF16
|
||||
|
||||
@ -40,4 +40,5 @@ namespace yycc::encoding::utf {
|
||||
|
||||
}
|
||||
|
||||
#undef NS_YYCC_PATCH_EXPECTED
|
||||
#undef NS_YYCC_STRING
|
||||
|
@ -0,0 +1,252 @@
|
||||
#include "windows.hpp"
|
||||
|
||||
#if YYCC_OS == YYCC_OS_WINDOWS
|
||||
|
||||
#include "../string/reinterpret.hpp"
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../windows/import_guard_head.hpp"
|
||||
#include "../windows/import_guard_tail.hpp"
|
||||
#include <Windows.h>
|
||||
|
||||
#define NS_YYCC_STRING ::yycc::string
|
||||
#define NS_YYCC_STRING_REINTERPRET ::yycc::string::reinterpret
|
||||
#define NS_YYCC_PATCH_EXPECTED ::yycc::patch::expected
|
||||
|
||||
namespace yycc::encoding::windows {
|
||||
|
||||
#pragma region Help Macros
|
||||
|
||||
#define CONVFN_TYPE1(fct_name, src_char_type, dst_char_type, ...) \
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED; \
|
||||
auto rv = priv_##fct_name(src, ##__VA_ARGS__); \
|
||||
if (expected::is_value(rv)) { \
|
||||
dst = std::move(expected::get_value(rv)); \
|
||||
return true; \
|
||||
} else { \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CONVFN_TYPE2(fct_name, src_char_type, dst_char_type, ...) \
|
||||
std::basic_string<dst_char_type> rv; \
|
||||
if (fct_name(src, rv, ##__VA_ARGS__)) return rv; \
|
||||
else throw std::runtime_error("fail to convert string in Win32 function");
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region WChar -> Char
|
||||
|
||||
ConvResult<std::string> priv_to_char(const std::wstring_view& src, CodePage code_page) {
|
||||
// prepare result
|
||||
std::string dst;
|
||||
|
||||
// if src is empty, direct output
|
||||
if (src.empty()) {
|
||||
return dst;
|
||||
}
|
||||
|
||||
// init WideCharToMultiByte used variables
|
||||
// setup src pointer
|
||||
LPCWCH lpWideCharStr = reinterpret_cast<LPCWCH>(src.data());
|
||||
// check whether source string is too large.
|
||||
size_t cSrcSize = src.size();
|
||||
if (cSrcSize > std::numeric_limits<int>::max()) return ConvError::TooLargeLength;
|
||||
int cchWideChar = static_cast<int>(src.size());
|
||||
|
||||
// do convertion
|
||||
// do a dry-run first to fetch desired size.
|
||||
int desired_size
|
||||
= WideCharToMultiByte(code_page, 0, lpWideCharStr, cchWideChar, NULL, 0, NULL, NULL);
|
||||
if (desired_size <= 0) return ConvError::NoDesiredSize;
|
||||
// resize dest for receiving result
|
||||
dst.resize(static_cast<size_t>(desired_size));
|
||||
// do real convertion
|
||||
int write_result = WideCharToMultiByte(code_page,
|
||||
0,
|
||||
lpWideCharStr,
|
||||
cchWideChar,
|
||||
reinterpret_cast<LPSTR>(dst.data()),
|
||||
desired_size,
|
||||
NULL,
|
||||
NULL);
|
||||
if (write_result <= 0) return ConvError::BadWrittenSize;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
bool to_char(const std::wstring_view& src, std::string& dst, CodePage code_page) {
|
||||
CONVFN_TYPE1(to_char, wchar_t, char, code_page);
|
||||
}
|
||||
|
||||
std::string to_char(const std::wstring_view& src, CodePage code_page) {
|
||||
CONVFN_TYPE2(to_char, wchar_t, char, code_page);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Char -> WChar
|
||||
|
||||
ConvResult<std::wstring> priv_to_wchar(const std::string_view& src, CodePage code_page) {
|
||||
// prepare result
|
||||
std::wstring dst;
|
||||
|
||||
// if src is empty, direct output
|
||||
if (src.empty()) {
|
||||
return dst;
|
||||
}
|
||||
|
||||
// init WideCharToMultiByte used variables
|
||||
// setup src pointer
|
||||
LPCCH lpMultiByteStr = reinterpret_cast<LPCCH>(src.data());
|
||||
// check whether source string is too large.
|
||||
size_t cSrcSize = src.size();
|
||||
if (cSrcSize > std::numeric_limits<int>::max()) return ConvError::TooLargeLength;
|
||||
int cbMultiByte = static_cast<int>(src.size());
|
||||
|
||||
// do convertion
|
||||
// do a dry-run first to fetch desired size.
|
||||
int desired_size = MultiByteToWideChar(code_page, 0, lpMultiByteStr, cbMultiByte, NULL, 0);
|
||||
if (desired_size <= 0) return ConvError::NoDesiredSize;
|
||||
// resize dest for receiving result
|
||||
dst.resize(static_cast<size_t>(desired_size));
|
||||
// do real convertion
|
||||
int write_result = MultiByteToWideChar(code_page,
|
||||
0,
|
||||
lpMultiByteStr,
|
||||
cbMultiByte,
|
||||
reinterpret_cast<LPWSTR>(dst.data()),
|
||||
desired_size);
|
||||
if (write_result <= 0) return ConvError::BadWrittenSize;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
bool to_wchar(const std::string_view& src, std::wstring& dst, CodePage code_page) {
|
||||
CONVFN_TYPE1(to_wchar, char, wchar_t, code_page);
|
||||
}
|
||||
|
||||
std::wstring to_wchar(const std::string_view& src, CodePage code_page) {
|
||||
CONVFN_TYPE2(to_wchar, char, wchar_t, code_page);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Char -> Char
|
||||
|
||||
ConvResult<std::string> priv_to_char(const std::string_view& src,
|
||||
CodePage src_code_page,
|
||||
CodePage dst_code_page) {
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED;
|
||||
|
||||
// Perform first convertion
|
||||
auto first_rv = priv_to_wchar(src, src_code_page);
|
||||
if (expected::is_error(first_rv)) {
|
||||
return expected::get_error(first_rv);
|
||||
}
|
||||
// Perform second convertion
|
||||
auto second_rv = to_char(std::get<std::wstring>(first_rv), dst_code_page);
|
||||
return second_rv;
|
||||
}
|
||||
|
||||
bool to_char(const std::string_view& src,
|
||||
std::string& dst,
|
||||
CodePage src_code_page,
|
||||
CodePage dst_code_page) {
|
||||
CONVFN_TYPE1(to_char, char, char, src_code_page, dst_code_page);
|
||||
}
|
||||
|
||||
std::string to_char(const std::string_view& src,
|
||||
CodePage src_code_page,
|
||||
CodePage dst_code_page) {
|
||||
CONVFN_TYPE2(to_char, char, char, src_code_page, dst_code_page);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region WChar -> UTF8
|
||||
|
||||
ConvResult<NS_YYCC_STRING::u8string> priv_to_utf8(const std::wstring_view& src) {
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED;
|
||||
|
||||
auto rv = priv_to_char(src, CP_UTF8);
|
||||
if (expected::is_value(rv)) {
|
||||
return NS_YYCC_STRING_REINTERPRET::as_utf8(expected::get_value(rv));
|
||||
} else {
|
||||
return expected::get_error(rv);
|
||||
}
|
||||
}
|
||||
|
||||
bool to_utf8(const std::wstring_view& src, NS_YYCC_STRING::u8string& dst) {
|
||||
CONVFN_TYPE1(to_utf8, wchar_t, NS_YYCC_STRING::u8char);
|
||||
}
|
||||
|
||||
NS_YYCC_STRING::u8string to_utf8(const std::wstring_view& src) {
|
||||
CONVFN_TYPE2(to_utf8, wchar_t, NS_YYCC_STRING::u8char);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region UTF8 -> WChar
|
||||
|
||||
ConvResult<std::wstring> priv_to_wchar(const NS_YYCC_STRING::u8string_view& src) {
|
||||
return priv_to_wchar(NS_YYCC_STRING_REINTERPRET::as_ordinary_view(src), CP_UTF8);
|
||||
}
|
||||
|
||||
bool to_wchar(const NS_YYCC_STRING::u8string_view& src, std::wstring& dst) {
|
||||
CONVFN_TYPE1(to_wchar, NS_YYCC_STRING::u8char, wchar_t);
|
||||
}
|
||||
|
||||
std::wstring to_wchar(const NS_YYCC_STRING::u8string_view& src) {
|
||||
CONVFN_TYPE2(to_wchar, NS_YYCC_STRING::u8char, wchar_t);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Char -> UTF8
|
||||
|
||||
ConvResult<NS_YYCC_STRING::u8string> priv_to_utf8(const std::string_view& src,
|
||||
CodePage code_page) {
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED;
|
||||
|
||||
auto rv = priv_to_char(src, code_page, CP_UTF8);
|
||||
if (expected::is_value(rv)) {
|
||||
return NS_YYCC_STRING_REINTERPRET::as_utf8(expected::get_value(rv));
|
||||
} else {
|
||||
return expected::get_error(rv);
|
||||
}
|
||||
}
|
||||
|
||||
bool to_utf8(const std::string_view& src, NS_YYCC_STRING::u8string& dst, CodePage code_page) {
|
||||
CONVFN_TYPE1(to_utf8, char, NS_YYCC_STRING::u8char, code_page);
|
||||
}
|
||||
|
||||
NS_YYCC_STRING::u8string to_utf8(const std::string_view& src, CodePage code_page) {
|
||||
CONVFN_TYPE2(to_utf8, char, NS_YYCC_STRING::u8char, code_page);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region UTF8 -> Char
|
||||
ConvResult<std::string> priv_to_char(const NS_YYCC_STRING::u8string_view& src,
|
||||
CodePage code_page) {
|
||||
return priv_to_char(NS_YYCC_STRING_REINTERPRET::as_ordinary_view(src), CP_UTF8, code_page);
|
||||
}
|
||||
|
||||
bool to_char(const NS_YYCC_STRING::u8string_view& src, std::string& dst, CodePage code_page) {
|
||||
CONVFN_TYPE1(to_char, NS_YYCC_STRING::u8char, char, code_page);
|
||||
}
|
||||
|
||||
std::string to_char(const NS_YYCC_STRING::u8string_view& src, CodePage code_page) {
|
||||
CONVFN_TYPE2(to_char, NS_YYCC_STRING::u8char, char, code_page);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#undef CONVFN_TYPE1
|
||||
#undef CONVFN_TYPE2
|
||||
#undef CONVFCT_TYPE4
|
||||
|
||||
} // namespace yycc::encoding::windows
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
#include "../macro/os_detector.hpp"
|
||||
#include "../string.hpp"
|
||||
#include "../patch/expected.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
#define NS_YYCC_STRING ::yycc::string
|
||||
#define NS_YYCC_PATCH_EXPECTED ::yycc::patch::expected
|
||||
|
||||
namespace yycc::encoding::windows {
|
||||
|
||||
#if YYCC_OS == YYCC_OS_WINDOWS
|
||||
|
||||
using CodePage = uint32_t;
|
||||
|
||||
/// @private
|
||||
enum class ConvError {
|
||||
TooLargeLength, ///< The length of given string is too large exceeding the maximum capacity of Win32 function.
|
||||
NoDesiredSize, ///< Can not compute the desired size of result string.
|
||||
BadWrittenSize, ///< The size of written data is not matched with expected size.
|
||||
};
|
||||
|
||||
/// @private
|
||||
template<typename T>
|
||||
using ConvResult = NS_YYCC_PATCH_EXPECTED::Expected<T, ConvError>;
|
||||
|
||||
// WChar -> Char
|
||||
ConvResult<std::string> priv_to_char(const std::wstring_view& src, CodePage code_page);
|
||||
bool to_char(const std::wstring_view& src, std::string& dst, CodePage code_page);
|
||||
std::string to_char(const std::wstring_view& src, CodePage code_page);
|
||||
|
||||
// Char -> WChar
|
||||
ConvResult<std::wstring> priv_to_wchar(const std::string_view& src, CodePage code_page);
|
||||
bool to_wchar(const std::string_view& src, std::wstring& dst, CodePage code_page);
|
||||
std::wstring to_wchar(const std::string_view& src, CodePage code_page);
|
||||
|
||||
// YYC MARK:
|
||||
// Following functions are basically the alias of above functions.
|
||||
|
||||
// Char -> Char
|
||||
ConvResult<std::string> priv_to_char(const std::string_view& src,
|
||||
CodePage src_code_page,
|
||||
CodePage dst_code_page);
|
||||
bool to_char(const std::string_view& src,
|
||||
std::string& dst,
|
||||
CodePage src_code_page,
|
||||
CodePage dst_code_page);
|
||||
std::string to_char(const std::string_view& src, CodePage src_code_page, CodePage dst_code_page);
|
||||
|
||||
// YYC MARK:
|
||||
// Following functions are basically the specialized UTF8 functions.
|
||||
|
||||
// WChar -> UTF8
|
||||
ConvResult<NS_YYCC_STRING::u8string> priv_to_utf8(const std::wstring_view& src);
|
||||
bool to_utf8(const std::wstring_view& src, NS_YYCC_STRING::u8string& dst);
|
||||
NS_YYCC_STRING::u8string to_utf8(const std::wstring_view& src);
|
||||
|
||||
// UTF8 -> WChar
|
||||
ConvResult<std::wstring> priv_to_wchar(const NS_YYCC_STRING::u8string_view& src);
|
||||
bool to_wchar(const NS_YYCC_STRING::u8string_view& src, std::wstring& dst);
|
||||
std::wstring to_wchar(const NS_YYCC_STRING::u8string_view& src);
|
||||
|
||||
// Char -> UTF8
|
||||
ConvResult<NS_YYCC_STRING::u8string> priv_to_utf8(const std::string_view& src,
|
||||
CodePage code_page);
|
||||
bool to_utf8(const std::string_view& src, NS_YYCC_STRING::u8string& dst, CodePage code_page);
|
||||
NS_YYCC_STRING::u8string to_utf8(const std::string_view& src, CodePage code_page);
|
||||
|
||||
// UTF8 -> Char
|
||||
ConvResult<std::string> priv_to_char(const NS_YYCC_STRING::u8string_view& src,
|
||||
CodePage code_page);
|
||||
bool to_char(const NS_YYCC_STRING::u8string_view& src, std::string& dst, CodePage code_page);
|
||||
std::string to_char(const NS_YYCC_STRING::u8string_view& src, CodePage code_page);
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace yycc::encoding::windows
|
||||
|
||||
#undef NS_YYCC_PATCH_EXPECTED
|
||||
#undef NS_YYCC_STRING
|
||||
|
@ -1,15 +1,15 @@
|
||||
#pragma once
|
||||
#include "../patch/expected.hpp"
|
||||
#include "../string.hpp"
|
||||
#include "../string/op.hpp"
|
||||
#include "../string/reinterpret.hpp"
|
||||
#include <charconv>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
|
||||
#define NS_YYCC_STRING ::yycc::string
|
||||
#define NS_YYCC_STRING_REINTERPRET ::yycc::string::reinterpret
|
||||
#define NS_YYCC_STRING_OP ::yycc::string::op
|
||||
#define NS_YYCC_PATCH_EXPECTED ::yycc::patch::expected
|
||||
|
||||
/**
|
||||
* @brief Provides string parsing utilities for converting strings to numeric and boolean values.
|
||||
@ -30,8 +30,8 @@ namespace yycc::num::parse {
|
||||
|
||||
/// @private
|
||||
/// @brief The return value of internal parse function which ape `std::expected`.
|
||||
template<typename T, std::enable_if_t<!std::is_same_v<T, ParseError>, int> = 0>
|
||||
using ParseResult = std::variant<T, ParseError>;
|
||||
template<typename T>
|
||||
using ParseResult = NS_YYCC_PATCH_EXPECTED::Expected<T, ParseError>;
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -132,15 +132,14 @@ namespace yycc::num::parse {
|
||||
bool try_parse(const NS_YYCC_STRING::u8string_view& strl,
|
||||
T& num,
|
||||
std::chars_format fmt = std::chars_format::general) {
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED;
|
||||
|
||||
auto rv = priv_parse<T>(strl, fmt);
|
||||
if (const auto* ptr = std::get_if<T>(&rv)) {
|
||||
num = *ptr;
|
||||
if (expected::is_value(rv)) {
|
||||
num = expected::get_value(rv);
|
||||
return true;
|
||||
} else if (const auto* ptr = std::get_if<ParseError>(&rv)) {
|
||||
return false;
|
||||
} else {
|
||||
// Unreachable
|
||||
throw std::runtime_error("unreachable code.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -155,15 +154,14 @@ namespace yycc::num::parse {
|
||||
*/
|
||||
template<typename T, std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, bool>, int> = 0>
|
||||
bool try_parse(const NS_YYCC_STRING::u8string_view& strl, T& num, int base = 10) {
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED;
|
||||
|
||||
auto rv = priv_parse<T>(strl, base);
|
||||
if (const auto* ptr = std::get_if<T>(&rv)) {
|
||||
num = *ptr;
|
||||
if (expected::is_value(rv)) {
|
||||
num = expected::get_value(rv);
|
||||
return true;
|
||||
} else if (const auto* ptr = std::get_if<ParseError>(&rv)) {
|
||||
return false;
|
||||
} else {
|
||||
// Unreachable
|
||||
throw std::runtime_error("unreachable code.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -177,15 +175,14 @@ namespace yycc::num::parse {
|
||||
*/
|
||||
template<typename T, std::enable_if_t<std::is_same_v<T, bool>, int> = 0>
|
||||
bool try_parse(const NS_YYCC_STRING::u8string_view& strl, T& num) {
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED;
|
||||
|
||||
auto rv = priv_parse<T>(strl);
|
||||
if (const auto* ptr = std::get_if<T>(&rv)) {
|
||||
num = *ptr;
|
||||
if (expected::is_value(rv)) {
|
||||
num = expected::get_value(rv);
|
||||
return true;
|
||||
} else if (const auto* ptr = std::get_if<ParseError>(&rv)) {
|
||||
return false;
|
||||
} else {
|
||||
// Unreachable
|
||||
throw std::runtime_error("unreachable code.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,8 +238,9 @@ namespace yycc::num::parse {
|
||||
else throw std::invalid_argument("can not parse given string");
|
||||
}
|
||||
|
||||
} // namespace yycc::string::parse
|
||||
} // namespace yycc::num::parse
|
||||
|
||||
#undef NS_YYCC_PATCH_EXPECTED
|
||||
#undef NS_YYCC_STRING_OP
|
||||
#undef NS_YYCC_STRING_REINTERPRET
|
||||
#undef NS_YYCC_STRING
|
||||
|
40
src/yycc/patch/expected.hpp
Normal file
40
src/yycc/patch/expected.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
|
||||
/**
|
||||
* @brief A stupid polyfill for std::expected,
|
||||
*
|
||||
* For those C++ standard which do not support std::expected,
|
||||
* we provide this namespace with a pretty bad but at least working std::expected pplyfill.
|
||||
*
|
||||
* The polyfill was done by std::variant.
|
||||
*
|
||||
* This namespace is used by this project because this framework must support C++ 17.
|
||||
*/
|
||||
namespace yycc::patch::expected {
|
||||
|
||||
template<typename TValue, typename TError, std::enable_if_t<!std::is_same_v<TValue, TError>, int> = 0>
|
||||
using Expected = std::variant<TValue, TError>;
|
||||
|
||||
template<typename TValue, typename TError>
|
||||
bool is_value(const Expected<TValue, TError>& exp) {
|
||||
return exp.index() == 0u;
|
||||
}
|
||||
|
||||
template<typename TValue, typename TError>
|
||||
bool is_error(const Expected<TValue, TError>& exp) {
|
||||
return exp.index() == 1u;
|
||||
}
|
||||
|
||||
template<typename TValue, typename TError>
|
||||
const TValue& get_value(const Expected<TValue, TError>& exp) {
|
||||
return std::get<0>(exp);
|
||||
}
|
||||
|
||||
template<typename TValue, typename TError>
|
||||
const TError& get_error(const Expected<TValue, TError>& exp) {
|
||||
return std::get<1>(exp);
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
#include "../../macro/feature_probe.hpp"
|
||||
#include "../../num/parse.hpp"
|
||||
#include "../panic.hpp"
|
||||
#include "../result.hpp"
|
||||
|
||||
#define NS_YYCC_STRING ::yycc::string
|
||||
#define NS_YYCC_NUM_PARSE ::yycc::num::parse
|
||||
#define NS_YYCC_RUST_RESULT ::yycc::rust::result
|
||||
#define NS_YYCC_PATCH_EXPECTED ::yycc::patch::expected
|
||||
|
||||
/**
|
||||
* @namespace yycc::rust::parse
|
||||
@ -37,15 +37,14 @@ namespace yycc::rust::num::parse {
|
||||
template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
|
||||
Result<T> parse(const NS_YYCC_STRING::u8string_view& strl,
|
||||
std::chars_format fmt = std::chars_format::general) {
|
||||
auto rv = NS_YYCC_NUM_PARSE::priv_parse<T>(strl, fmt);
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED;
|
||||
namespace result = NS_YYCC_RUST_RESULT;
|
||||
|
||||
if (const auto* ptr = std::get_if<T>(&rv)) {
|
||||
return NS_YYCC_RUST_RESULT::Ok<Result<T>>(*ptr);
|
||||
} else if (const auto* ptr = std::get_if<Error>(&rv)) {
|
||||
return NS_YYCC_RUST_RESULT::Err<Result<T>>(*ptr);
|
||||
auto rv = NS_YYCC_NUM_PARSE::priv_parse<T>(strl, fmt);
|
||||
if (expected::is_value(rv)) {
|
||||
return result::Ok<Result<T>>(expected::get_value(rv));
|
||||
} else {
|
||||
// Unreachable
|
||||
RS_PANIC("unreachable code.");
|
||||
return result::Err<Result<T>>(expected::get_error(rv));
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,15 +57,14 @@ namespace yycc::rust::num::parse {
|
||||
*/
|
||||
template<typename T, std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, bool>, int> = 0>
|
||||
Result<T> parse(const NS_YYCC_STRING::u8string_view& strl, int base = 10) {
|
||||
auto rv = NS_YYCC_NUM_PARSE::priv_parse<T>(strl, base);
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED;
|
||||
namespace result = NS_YYCC_RUST_RESULT;
|
||||
|
||||
if (const auto* ptr = std::get_if<T>(&rv)) {
|
||||
return NS_YYCC_RUST_RESULT::Ok<Result<T>>(*ptr);
|
||||
} else if (const auto* ptr = std::get_if<Error>(&rv)) {
|
||||
return NS_YYCC_RUST_RESULT::Err<Result<T>>(*ptr);
|
||||
auto rv = NS_YYCC_NUM_PARSE::priv_parse<T>(strl, base);
|
||||
if (expected::is_value(rv)) {
|
||||
return result::Ok<Result<T>>(expected::get_value(rv));
|
||||
} else {
|
||||
// Unreachable
|
||||
RS_PANIC("unreachable code.");
|
||||
return result::Err<Result<T>>(expected::get_error(rv));
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,15 +76,14 @@ namespace yycc::rust::num::parse {
|
||||
*/
|
||||
template<typename T, std::enable_if_t<std::is_same_v<T, bool>, int> = 0>
|
||||
Result<T> parse(const NS_YYCC_STRING::u8string_view& strl) {
|
||||
auto rv = NS_YYCC_NUM_PARSE::priv_parse<T>(strl);
|
||||
namespace expected = NS_YYCC_PATCH_EXPECTED;
|
||||
namespace result = NS_YYCC_RUST_RESULT;
|
||||
|
||||
if (const auto* ptr = std::get_if<T>(&rv)) {
|
||||
return NS_YYCC_RUST_RESULT::Ok<Result<T>>(*ptr);
|
||||
} else if (const auto* ptr = std::get_if<Error>(&rv)) {
|
||||
return NS_YYCC_RUST_RESULT::Err<Result<T>>(*ptr);
|
||||
auto rv = NS_YYCC_NUM_PARSE::priv_parse<T>(strl);
|
||||
if (expected::is_value(rv)) {
|
||||
return result::Ok<Result<T>>(expected::get_value(rv));
|
||||
} else {
|
||||
// Unreachable
|
||||
RS_PANIC("unreachable code.");
|
||||
return result::Err<Result<T>>(expected::get_error(rv));
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +91,7 @@ namespace yycc::rust::num::parse {
|
||||
|
||||
}
|
||||
|
||||
#undef NS_YYCC_PATCH_EXPECTED
|
||||
#undef NS_YYCC_RUST_RESULT
|
||||
#undef NS_YYCC_NUM_PARSE
|
||||
#undef NS_YYCC_STRING
|
||||
|
Reference in New Issue
Block a user