From bc37fdb4b746ce0f5f5c49ad9779464acb488284 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 18 Jan 2022 22:40:39 +0800 Subject: ... --- include/cru/common/Format.hpp | 140 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 include/cru/common/Format.hpp (limited to 'include/cru/common/Format.hpp') diff --git a/include/cru/common/Format.hpp b/include/cru/common/Format.hpp new file mode 100644 index 00000000..d53a5720 --- /dev/null +++ b/include/cru/common/Format.hpp @@ -0,0 +1,140 @@ +#pragma once + +#include "Exception.hpp" +#include "String.hpp" + +namespace cru { +inline String ToString(bool value) { + return value ? String(u"true") : String(u"false"); +} + +template +std::enable_if_t, String> ToString(T value) { + std::array buffer; + auto result = + std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); + + if (result.ec == std::errc{}) { + } else { + throw std::invalid_argument("Failed to convert value to chars."); + } + + auto size = result.ptr - buffer.data(); + auto b = new char16_t[size + 1]; + b[size] = 0; + std::copy(buffer.data(), result.ptr, b); + return String::FromBuffer(b, size, size); +} + +template +std::enable_if_t, String> ToString(T value) { + auto str = std::to_string(value); + return String(str.cbegin(), str.cend()); +} + +template +std::enable_if_t< + std::is_convertible_v)), String>, + String> +ToString(const T& value, StringView option) { + return ToString(value); +} + +inline String ToString(String value) { return value; } + +namespace details { +enum class FormatTokenType { PlaceHolder, Text }; +enum class FormatPlaceHolderType { None, Positioned, Named }; + +struct FormatToken { + static FormatToken Text() { + return FormatToken{FormatTokenType::Text, {}, {}, 0, {}, {}}; + } + + static FormatToken NonePlaceHolder(String option) { + return FormatToken(FormatTokenType::PlaceHolder, {}, + FormatPlaceHolderType::None, 0, {}, std::move(option)); + } + + static FormatToken PositionedPlaceHolder(int position, String option) { + return FormatToken(FormatTokenType::PlaceHolder, {}, + FormatPlaceHolderType::Positioned, position, {}, + std::move(option)); + } + + static FormatToken NamedPlaceHolder(String name, String option) { + return FormatToken(FormatTokenType::PlaceHolder, {}, + FormatPlaceHolderType::Named, 0, std::move(name), + std::move(option)); + } + + FormatToken(FormatTokenType type, String data, + FormatPlaceHolderType place_holder_type, + int place_holder_position, String place_holder_name, + String place_holder_option) + : type(type), + data(std::move(data)), + place_holder_type(place_holder_type), + place_holder_position(place_holder_position), + place_holder_name(std::move(place_holder_name)), + place_holder_option(std::move(place_holder_option)) {} + + CRU_DEFAULT_COPY(FormatToken) + CRU_DEFAULT_MOVE(FormatToken) + + CRU_DEFAULT_DESTRUCTOR(FormatToken) + + FormatTokenType type; + String data; + FormatPlaceHolderType place_holder_type; + int place_holder_position; + String place_holder_name; + String place_holder_option; +}; + +std::vector CRU_BASE_API ParseToFormatTokenList(const String& str); + +void CRU_BASE_API FormatAppendFromFormatTokenList( + String& current, const std::vector& format_token_list, + Index index); + +template +void FormatAppendFromFormatTokenList( + String& current, const std::vector& format_token_list, + Index index, TA&& args0, T&&... args) { + for (Index i = index; i < static_cast(format_token_list.size()); i++) { + const auto& token = format_token_list[i]; + if (token.type == FormatTokenType::PlaceHolder) { + if (token.place_holder_type == FormatPlaceHolderType::None) { + current += ToString(std::forward(args0), token.place_holder_option); + FormatAppendFromFormatTokenList(current, format_token_list, i + 1, + std::forward(args)...); + + return; + } else { + throw Exception( + u"Currently do not support positional or named place holder."); + } + } else { + current += token.data; + } + } +} +} // namespace details + +template +String Format(const String& format, T&&... args) { + String result; + + details::FormatAppendFromFormatTokenList( + result, details::ParseToFormatTokenList(format), 0, + std::forward(args)...); + + return result; +} + +template +String String::Format(T&&... args) const { + return cru::Format(*this, std::forward(args)...); +} +} // namespace cru -- cgit v1.2.3 From eecd4e5ba96244be15e3be9a9a4d404c36a533c7 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 18 Jan 2022 23:25:48 +0800 Subject: ... --- .github/workflows/ci.yml | 17 +++++++++-------- include/cru/common/Format.hpp | 13 ++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'include/cru/common/Format.hpp') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e54bbcf2..e99fc8b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: - name: Build run: | - cmake -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/clang -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/clang++ -H. -B./build -G Ninja + cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -H. -B./build -G Ninja cmake --build ./build --config Debug --target all - name: Test @@ -59,11 +59,12 @@ jobs: with: version: 1.10.2 - - name: Run build script - shell: pwsh + - name: Build run: | - . ./tools/Use-VC.ps1 - Use-VC - mkdir build && cd build - cmake .. -G Ninja -DCMAKE_BUILD_TYPE:STRING=Debug - ninja all + cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -H. -B./build -G Ninja + cmake --build ./build --config Debug --target all + + - name: Test + working-directory: build + run: | + ctest -C Debug -T test --output-on-failure diff --git a/include/cru/common/Format.hpp b/include/cru/common/Format.hpp index d53a5720..c093c9e6 100644 --- a/include/cru/common/Format.hpp +++ b/include/cru/common/Format.hpp @@ -2,6 +2,7 @@ #include "Exception.hpp" #include "String.hpp" +#include "cru/common/Base.hpp" namespace cru { inline String ToString(bool value) { @@ -32,16 +33,14 @@ std::enable_if_t, String> ToString(T value) { return String(str.cbegin(), str.cend()); } +inline String ToString(String value) { return value; } + template -std::enable_if_t< - std::is_convertible_v)), String>, - String> -ToString(const T& value, StringView option) { - return ToString(value); +String ToString(T&& value, StringView option) { + CRU_UNUSED(option) + return ToString(std::forward(value)); } -inline String ToString(String value) { return value; } - namespace details { enum class FormatTokenType { PlaceHolder, Text }; enum class FormatPlaceHolderType { None, Positioned, Named }; -- cgit v1.2.3 From 46ced88c30eeb5f84b7fe78a36d18428babe4fcf Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 18 Jan 2022 23:27:37 +0800 Subject: ... --- include/cru/common/Format.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'include/cru/common/Format.hpp') diff --git a/include/cru/common/Format.hpp b/include/cru/common/Format.hpp index c093c9e6..c2fd2e09 100644 --- a/include/cru/common/Format.hpp +++ b/include/cru/common/Format.hpp @@ -33,14 +33,17 @@ std::enable_if_t, String> ToString(T value) { return String(str.cbegin(), str.cend()); } -inline String ToString(String value) { return value; } - template -String ToString(T&& value, StringView option) { +std::enable_if_t< + std::is_convertible_v)), String>, + String> +ToString(const T& value, StringView option) { CRU_UNUSED(option) - return ToString(std::forward(value)); + return ToString(value); } +inline String ToString(String value) { return value; } + namespace details { enum class FormatTokenType { PlaceHolder, Text }; enum class FormatPlaceHolderType { None, Positioned, Named }; -- cgit v1.2.3