aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/ErrnoException.cpp2
-rw-r--r--src/common/Format.cpp111
-rw-r--r--src/common/String.cpp50
-rw-r--r--src/common/StringUtil.cpp2
-rw-r--r--src/common/io/UnixFileStream.cpp1
-rw-r--r--src/osx/graphics/quartz/Brush.cpp1
-rw-r--r--src/osx/graphics/quartz/TextLayout.cpp1
-rw-r--r--src/parse/Grammar.cpp1
-rw-r--r--src/win/Exception.cpp1
-rw-r--r--src/win/graphics/direct/Font.cpp1
11 files changed, 122 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>
diff --git a/src/osx/graphics/quartz/Brush.cpp b/src/osx/graphics/quartz/Brush.cpp
index 83ac20a2..637ce34f 100644
--- a/src/osx/graphics/quartz/Brush.cpp
+++ b/src/osx/graphics/quartz/Brush.cpp
@@ -1,5 +1,6 @@
#include "cru/osx/graphics/quartz/Brush.hpp"
#include "cru/common/String.hpp"
+#include "cru/common/Format.hpp"
namespace cru::platform::graphics::osx::quartz {
QuartzSolidColorBrush::QuartzSolidColorBrush(IGraphicsFactory* graphics_factory,
diff --git a/src/osx/graphics/quartz/TextLayout.cpp b/src/osx/graphics/quartz/TextLayout.cpp
index de14816d..3f33acdb 100644
--- a/src/osx/graphics/quartz/TextLayout.cpp
+++ b/src/osx/graphics/quartz/TextLayout.cpp
@@ -6,6 +6,7 @@
#include "cru/osx/graphics/quartz/Resource.hpp"
#include "cru/platform/Check.hpp"
#include "cru/platform/graphics/Base.hpp"
+#include "cru/common/Format.hpp"
#include <algorithm>
#include <limits>
diff --git a/src/parse/Grammar.cpp b/src/parse/Grammar.cpp
index 19095150..52933f91 100644
--- a/src/parse/Grammar.cpp
+++ b/src/parse/Grammar.cpp
@@ -1,6 +1,7 @@
#include "cru/parse/Grammar.hpp"
#include "cru/common/String.hpp"
#include "cru/parse/Symbol.hpp"
+#include "cru/common/Format.hpp"
#include <algorithm>
#include <iterator>
diff --git a/src/win/Exception.cpp b/src/win/Exception.cpp
index 2664b092..fb46f184 100644
--- a/src/win/Exception.cpp
+++ b/src/win/Exception.cpp
@@ -1,4 +1,5 @@
#include "cru/win/Exception.hpp"
+#include "cru/common/Format.hpp"
#include <optional>
diff --git a/src/win/graphics/direct/Font.cpp b/src/win/graphics/direct/Font.cpp
index 413c998b..ffc16214 100644
--- a/src/win/graphics/direct/Font.cpp
+++ b/src/win/graphics/direct/Font.cpp
@@ -1,5 +1,6 @@
#include "cru/win/graphics/direct/Font.hpp"
+#include "cru/common/Format.hpp"
#include "cru/win/graphics/direct/Exception.hpp"
#include "cru/win/graphics/direct/Factory.hpp"