diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/common/ErrnoException.cpp | 2 | ||||
-rw-r--r-- | src/common/Format.cpp | 111 | ||||
-rw-r--r-- | src/common/String.cpp | 50 | ||||
-rw-r--r-- | src/common/StringUtil.cpp | 2 | ||||
-rw-r--r-- | src/common/io/UnixFileStream.cpp | 1 |
6 files changed, 117 insertions, 50 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 300fa03e..40c85ef0 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(cru_base SHARED Base.cpp Exception.cpp + Format.cpp Logger.cpp PropertyTree.cpp String.cpp diff --git a/src/common/ErrnoException.cpp b/src/common/ErrnoException.cpp index 15d298b3..731ae3e5 100644 --- a/src/common/ErrnoException.cpp +++ b/src/common/ErrnoException.cpp @@ -1,5 +1,7 @@ #include "cru/common/ErrnoException.hpp" +#include "cru/common/Format.hpp" + #include <errno.h> namespace cru { diff --git a/src/common/Format.cpp b/src/common/Format.cpp new file mode 100644 index 00000000..2d3b50eb --- /dev/null +++ b/src/common/Format.cpp @@ -0,0 +1,111 @@ +#include "cru/common/Format.hpp" + +namespace cru { +namespace details { +FormatToken ParsePlaceHolder(String place_holder_string) { + if (place_holder_string.empty()) { + return FormatToken::NonePlaceHolder({}); + } + + if (place_holder_string.StartWith(u":")) { + if (place_holder_string.Find(u':', 1) != -1) { + throw Exception(u"Two ':' inside placeholder."); + } + + return FormatToken::NonePlaceHolder(place_holder_string.substr(1)); + } + if (IsDigit(place_holder_string[0])) { + int position = 0; + int index = 0; + while (index < place_holder_string.size() && + IsDigit(place_holder_string[index])) { + position = position * 10 + place_holder_string[index] - '0'; + index++; + } + + String option; + + if (index != place_holder_string.size()) { + if (place_holder_string[index] != ':') { + throw Exception(u"Invalid placeholder in format."); + } + + option = place_holder_string.substr(index + 1); + } + + return FormatToken::PositionedPlaceHolder(position, std::move(option)); + } + + auto separator_index = place_holder_string.Find(':'); + if (separator_index == -1) { + return FormatToken::NamedPlaceHolder(place_holder_string, {}); + } else { + return FormatToken::NamedPlaceHolder( + place_holder_string.substr(0, separator_index), + place_holder_string.substr(separator_index + 1)); + } +} + +std::vector<FormatToken> ParseToFormatTokenList(const String& str) { + std::vector<FormatToken> result; + + auto push_char = [&result](char16_t c) { + if (result.empty() || result.back().type == FormatTokenType::PlaceHolder) { + result.push_back(FormatToken::Text()); + } + result.back().data.append(c); + }; + + bool try_to_escape = false; + bool is_in_place_holder = false; + String place_holder_string; + + for (auto c : str) { + if (c == u'{') { + if (try_to_escape) { + push_char(u'{'); + try_to_escape = false; + is_in_place_holder = false; + } else { + if (is_in_place_holder) { + throw Exception(u"Invalid format string: '{' inside placeholder."); + } + + try_to_escape = true; + is_in_place_holder = true; + } + } else if (c == u'}') { + if (is_in_place_holder) { + is_in_place_holder = false; + result.push_back(ParsePlaceHolder(std::move(place_holder_string))); + place_holder_string.clear(); + } else { + push_char(u'}'); + } + try_to_escape = false; + } else { + if (is_in_place_holder) { + place_holder_string.push_back(c); + } else { + push_char(c); + } + try_to_escape = false; + } + } + return result; +} + +void FormatAppendFromFormatTokenList( + String& current, const std::vector<FormatToken>& format_token_list, + Index index) { + for (Index i = index; i < static_cast<Index>(format_token_list.size()); i++) { + const auto& token = format_token_list[i]; + if (token.type == FormatTokenType::PlaceHolder) { + throw Exception(u"More placeholder than args."); + } else { + current += token.data; + } + } +} +} // namespace details +} // namespace cru diff --git a/src/common/String.cpp b/src/common/String.cpp index 21f3f235..9366abeb 100644 --- a/src/common/String.cpp +++ b/src/common/String.cpp @@ -394,56 +394,6 @@ int String::Compare(const String& other) const { } } -namespace details { -std::vector<FormatToken> ParseToFormatTokenList(const String& str) { - std::vector<FormatToken> result; - - auto push_char = [&result](char16_t c) { - if (result.empty() || result.back().type == FormatTokenType::PlaceHolder) { - result.push_back(FormatToken{FormatTokenType::Text, String{}}); - } - result.back().data.append(c); - }; - - bool last_is_left_bracket = false; - for (auto c : str) { - if (c == u'{') { - if (last_is_left_bracket) { - push_char(u'{'); - last_is_left_bracket = false; - } else { - last_is_left_bracket = true; - } - } else if (c == u'}') { - if (last_is_left_bracket) { - result.push_back(FormatToken{FormatTokenType::PlaceHolder, String{}}); - } - last_is_left_bracket = false; - } else { - if (last_is_left_bracket) { - push_char(u'{'); - } - push_char(c); - last_is_left_bracket = false; - } - } - return result; -} - -void FormatAppendFromFormatTokenList( - String& current, const std::vector<FormatToken>& format_token_list, - Index index) { - for (Index i = index; i < static_cast<Index>(format_token_list.size()); i++) { - const auto& token = format_token_list[i]; - if (token.type == FormatTokenType::PlaceHolder) { - current += u"{}"; - } else { - current += token.data; - } - } -} -} // namespace details - int StringView::Compare(const StringView& other) const { const_iterator i1 = cbegin(); const_iterator i2 = other.cbegin(); diff --git a/src/common/StringUtil.cpp b/src/common/StringUtil.cpp index 04435a0a..1f5f6150 100644 --- a/src/common/StringUtil.cpp +++ b/src/common/StringUtil.cpp @@ -258,6 +258,8 @@ bool IsWhitespace(char16_t c) { return c == u' ' || c == u'\t' || c == u'\n' || c == u'\r'; } +bool IsDigit(char16_t c) { return c >= u'0' && c <= u'9'; } + Utf8CodePointIterator CreateUtf8Iterator(const std::byte* buffer, Index size) { return Utf8CodePointIterator(reinterpret_cast<const char*>(buffer), size); } diff --git a/src/common/io/UnixFileStream.cpp b/src/common/io/UnixFileStream.cpp index 9c9abba5..615c36f1 100644 --- a/src/common/io/UnixFileStream.cpp +++ b/src/common/io/UnixFileStream.cpp @@ -1,6 +1,7 @@ #include "cru/common/io/UnixFileStream.hpp" #include "cru/common/ErrnoException.hpp" #include "cru/common/io/OpenFileFlag.hpp" +#include "cru/common/Format.hpp" #include <fcntl.h> #include <sys/_types/_s_ifmt.h> |