aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/common/Exception.hpp2
-rw-r--r--include/cru/common/HandlerRegistry.hpp1
-rw-r--r--include/cru/common/Logger.hpp26
-rw-r--r--include/cru/common/String.hpp98
-rw-r--r--include/cru/platform/Check.hpp15
-rw-r--r--include/cru/platform/GraphBase.hpp11
-rw-r--r--include/cru/platform/gui/InputMethod.hpp51
-rw-r--r--include/cru/ui/render/MeasureRequirement.hpp14
-rw-r--r--src/common/CMakeLists.txt3
-rw-r--r--src/common/Logger.cpp21
-rw-r--r--src/common/String.cpp56
-rw-r--r--src/osx/graphics/quartz/CMakeLists.txt2
-rw-r--r--src/parse/Grammar.cpp20
-rw-r--r--src/platform/Color.cpp1
-rw-r--r--test/common/CMakeLists.txt2
-rw-r--r--test/common/StringTest.cpp9
-rw-r--r--vcpkg.json1
17 files changed, 241 insertions, 92 deletions
diff --git a/include/cru/common/Exception.hpp b/include/cru/common/Exception.hpp
index 8864f4df..4e5d3a16 100644
--- a/include/cru/common/Exception.hpp
+++ b/include/cru/common/Exception.hpp
@@ -5,7 +5,7 @@ namespace cru {
class CRU_BASE_API Exception {
public:
Exception() = default;
- Exception(String message) : message_(std::move(message)) {}
+ explicit Exception(String message) : message_(std::move(message)) {}
CRU_DEFAULT_COPY(Exception)
CRU_DEFAULT_MOVE(Exception)
diff --git a/include/cru/common/HandlerRegistry.hpp b/include/cru/common/HandlerRegistry.hpp
index bd74a9e0..0af97968 100644
--- a/include/cru/common/HandlerRegistry.hpp
+++ b/include/cru/common/HandlerRegistry.hpp
@@ -59,6 +59,7 @@ class HandlerRegistry final {
int AddHandler(std::function<T> handler) {
auto id = current_id_++;
handler_list_.push_back({id, std::move(handler)});
+ return id;
}
void RemoveHandler(int id) {
diff --git a/include/cru/common/Logger.hpp b/include/cru/common/Logger.hpp
index 239a25cd..5aea5126 100644
--- a/include/cru/common/Logger.hpp
+++ b/include/cru/common/Logger.hpp
@@ -1,10 +1,10 @@
#pragma once
#include "Base.hpp"
-#include <fmt/format.h>
+#include "String.hpp"
+
#include <list>
#include <memory>
-#include <string_view>
namespace cru::log {
@@ -13,7 +13,7 @@ enum class LogLevel { Debug, Info, Warn, Error };
struct CRU_BASE_API ILogSource : virtual Interface {
// Write the string s. LogLevel is just a helper. It has no effect on the
// content to write.
- virtual void Write(LogLevel level, const std::u16string& s) = 0;
+ virtual void Write(LogLevel level, const String& s) = 0;
};
class CRU_BASE_API Logger : public Object {
@@ -33,8 +33,8 @@ class CRU_BASE_API Logger : public Object {
void RemoveSource(ILogSource* source);
public:
- void Log(LogLevel level, std::u16string_view s);
- void Log(LogLevel level, std::u16string_view tag, std::u16string_view s);
+ void Log(LogLevel level, const String& message);
+ void Log(LogLevel level, const String& tag, const String& message);
private:
std::list<std::unique_ptr<ILogSource>> sources_;
@@ -45,26 +45,26 @@ template <typename... TArgs>
void Debug([[maybe_unused]] TArgs&&... args) {
#ifdef CRU_DEBUG
Logger::GetInstance()->Log(LogLevel::Debug,
- fmt::format(std::forward<TArgs>(args)...));
+ Format(std::forward<TArgs>(args)...));
#endif
}
template <typename... TArgs>
void Info(TArgs&&... args) {
Logger::GetInstance()->Log(LogLevel::Info,
- fmt::format(std::forward<TArgs>(args)...));
+ Format(std::forward<TArgs>(args)...));
}
template <typename... TArgs>
void Warn(TArgs&&... args) {
Logger::GetInstance()->Log(LogLevel::Warn,
- fmt::format(std::forward<TArgs>(args)...));
+ Format(std::forward<TArgs>(args)...));
}
template <typename... TArgs>
void Error(TArgs&&... args) {
Logger::GetInstance()->Log(LogLevel::Error,
- fmt::format(std::forward<TArgs>(args)...));
+ Format(std::forward<TArgs>(args)...));
}
// TODO: Remove argument evaluation in Debug.
@@ -73,25 +73,25 @@ void TagDebug([[maybe_unused]] std::u16string_view tag,
[[maybe_unused]] TArgs&&... args) {
#ifdef CRU_DEBUG
Logger::GetInstance()->Log(LogLevel::Debug, tag,
- fmt::format(std::forward<TArgs>(args)...));
+ Format(std::forward<TArgs>(args)...));
#endif
}
template <typename... TArgs>
void TagInfo(std::u16string_view tag, TArgs&&... args) {
Logger::GetInstance()->Log(LogLevel::Info, tag,
- fmt::format(std::forward<TArgs>(args)...));
+ Format(std::forward<TArgs>(args)...));
}
template <typename... TArgs>
void TagWarn(std::u16string_view tag, TArgs&&... args) {
Logger::GetInstance()->Log(LogLevel::Warn, tag,
- fmt::format(std::forward<TArgs>(args)...));
+ Format(std::forward<TArgs>(args)...));
}
template <typename... TArgs>
void TagError(std::u16string_view tag, TArgs&&... args) {
Logger::GetInstance()->Log(LogLevel::Error, tag,
- fmt::format(std::forward<TArgs>(args)...));
+ Format(std::forward<TArgs>(args)...));
}
} // namespace cru::log
diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp
index 42143c9d..9443417f 100644
--- a/include/cru/common/String.hpp
+++ b/include/cru/common/String.hpp
@@ -4,8 +4,14 @@
#include "Range.hpp"
#include "StringUtil.hpp"
-#include <cstdint>
+#include <algorithm>
+#include <array>
+#include <charconv>
#include <iterator>
+#include <stdexcept>
+#include <system_error>
+#include <type_traits>
+#include <vector>
namespace cru {
class CRU_BASE_API String {
@@ -25,6 +31,11 @@ class CRU_BASE_API String {
return String(str, size);
}
+ // Never use this if you don't know what this mean!
+ static String FromBuffer(std::uint16_t* buffer, Index size, Index capacity) {
+ return String{from_buffer_tag{}, buffer, size, capacity};
+ }
+
#ifdef CRU_PLATFORM_WINDOWS
static String FromUtf16(wchar_t* str) { return String(str); }
static String FromUtf16(wchar_t* str, Index size) {
@@ -69,6 +80,10 @@ class CRU_BASE_API String {
~String();
+ private:
+ struct from_buffer_tag {};
+ String(from_buffer_tag, std::uint16_t* buffer, Index size, Index capacity);
+
public:
bool empty() const { return this->size_ == 0; }
Index size() const { return this->size_; }
@@ -136,12 +151,6 @@ class CRU_BASE_API String {
return *this;
}
- String operator+(const String& other) const {
- String result(*this);
- result += other;
- return result;
- }
-
public:
Utf16CodePointIterator CodePointIterator() const {
return Utf16CodePointIterator(
@@ -163,6 +172,9 @@ class CRU_BASE_API String {
}
#endif
+ template <typename... T>
+ String Format(T&&... args) const;
+
std::string ToUtf8() const;
int Compare(const String& other) const;
@@ -178,4 +190,76 @@ class CRU_BASE_API String {
CRU_DEFINE_COMPARE_OPERATORS(String)
+inline String operator+(const String& left, const String& right) {
+ String result(left);
+ result += right;
+ return result;
+}
+
+template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
+String ToString(T value) {
+ std::array<char, 50> buffer;
+ auto result =
+ std::to_chars(buffer.data(), buffer.data() + buffer.size(), value);
+
+ auto size = result.ptr - buffer.data();
+ auto b = new std::uint16_t[size + 1];
+ b[size] = 0;
+ std::copy(buffer.data(), result.ptr, b);
+ return String::FromBuffer(b, size, size);
+
+ if (result.ec == std::errc{}) {
+ } else {
+ throw std::invalid_argument("Failed to convert value to chars.");
+ }
+}
+
+inline String ToString(String value) { return std::move(value); }
+
+namespace details {
+enum class FormatTokenType { PlaceHolder, Text };
+
+struct FormatToken {
+ FormatTokenType type;
+ String data;
+};
+
+std::vector<FormatToken> ParseToFormatTokenList(const String& str);
+
+void FormatAppendFromFormatTokenList(
+ String& current, const std::vector<FormatToken>& format_token_list,
+ Index index);
+
+template <typename TA, typename... T>
+void FormatAppendFromFormatTokenList(
+ String& current, const std::vector<FormatToken>& format_token_list,
+ Index index, TA&& args0, T&&... args) {
+ for (Index i = index; i < format_token_list.size(); i++) {
+ const auto& token = format_token_list[i];
+ if (token.type == FormatTokenType::PlaceHolder) {
+ current += ToString(std::forward<TA>(args0));
+ FormatAppendFromFormatTokenList(current, format_token_list, i + 1,
+ std::forward<T>(args)...);
+ } else {
+ current += token.data;
+ }
+ }
+}
+} // namespace details
+
+template <typename... T>
+String Format(const String& format, T&&... args) {
+ String result;
+
+ details::FormatAppendFromFormatTokenList(
+ result, details::ParseToFormatTokenList(format), 0,
+ std::forward<T>(args)...);
+
+ return result;
+}
+
+template <typename... T>
+String String::Format(T&&... args) const {
+ return cru::Format(*this, std::forward<T>(args)...);
+}
} // namespace cru
diff --git a/include/cru/platform/Check.hpp b/include/cru/platform/Check.hpp
index 9ecd2d1d..5d99aa9c 100644
--- a/include/cru/platform/Check.hpp
+++ b/include/cru/platform/Check.hpp
@@ -2,9 +2,8 @@
#include "Exception.hpp"
#include "Resource.hpp"
-#include "cru/common/StringUtil.hpp"
+#include "cru/common/String.hpp"
-#include <fmt/format.h>
#include <memory>
#include <type_traits>
@@ -15,10 +14,10 @@ TTarget* CheckPlatform(IPlatformResource* resource,
Expects(resource);
const auto result = dynamic_cast<TTarget*>(resource);
if (result == nullptr) {
- throw UnsupportPlatformException(String::FromUtf8(fmt::format(
- "Try to convert resource to target platform failed. Platform id of "
+ throw UnsupportPlatformException(Format(
+ u"Try to convert resource to target platform failed. Platform id of "
"resource to convert: {} . Target platform id: {} .",
- resource->GetPlatformId().ToUtf8(), target_platform.ToUtf8())));
+ resource->GetPlatformId(), target_platform));
}
return result;
}
@@ -31,10 +30,10 @@ std::shared_ptr<TTarget> CheckPlatform(const std::shared_ptr<TSource>& resource,
Expects(resource);
const auto result = std::dynamic_pointer_cast<TTarget>(resource);
if (result == nullptr) {
- throw UnsupportPlatformException(String::FromUtf8(fmt::format(
- "Try to convert resource to target platform failed. Platform id of "
+ throw UnsupportPlatformException(Format(
+ u"Try to convert resource to target platform failed. Platform id of "
"resource to convert: {} . Target platform id: {} .",
- resource->GetPlatformId().ToUtf8(), target_platform.ToUtf8())));
+ resource->GetPlatformId(), target_platform));
}
return result;
}
diff --git a/include/cru/platform/GraphBase.hpp b/include/cru/platform/GraphBase.hpp
index cc0ffcc7..2cfc9cc4 100644
--- a/include/cru/platform/GraphBase.hpp
+++ b/include/cru/platform/GraphBase.hpp
@@ -4,8 +4,8 @@
#include "Color.hpp"
#include "cru/common/Format.hpp"
#include "cru/common/Range.hpp"
+#include "cru/common/String.hpp"
-#include <fmt/core.h>
#include <cstdint>
#include <limits>
#include <optional>
@@ -20,8 +20,8 @@ struct Point final {
constexpr Point(const float x, const float y) : x(x), y(y) {}
explicit constexpr Point(const Size& size);
- std::u16string ToDebugString() const {
- return fmt::format(u"({}, {})", ToUtf16String(x), ToUtf16String(y));
+ String ToDebugString() const {
+ return Format(u"({}, {})", ToUtf16String(x), ToUtf16String(y));
}
constexpr Point& operator+=(const Point& other) {
@@ -62,9 +62,8 @@ struct Size final {
std::numeric_limits<float>::max()};
}
- std::u16string ToDebugString() const {
- return fmt::format(u"({}, {})", ToUtf16String(width),
- ToUtf16String(height));
+ String ToDebugString() const {
+ return Format(u"({}, {})", ToUtf16String(width), ToUtf16String(height));
}
float width = 0;
diff --git a/include/cru/platform/gui/InputMethod.hpp b/include/cru/platform/gui/InputMethod.hpp
index 9b07959c..c259e63c 100644
--- a/include/cru/platform/gui/InputMethod.hpp
+++ b/include/cru/platform/gui/InputMethod.hpp
@@ -3,7 +3,6 @@
#include "cru/common/Event.hpp"
-#include <fmt/format.h>
#include <memory>
#include <vector>
@@ -54,28 +53,28 @@ struct IInputMethodContext : virtual IPlatformResource {
};
} // namespace cru::platform::gui
-template <>
-struct fmt::formatter<cru::platform::gui::CompositionText, char16_t>
- : fmt::formatter<std::u16string_view, char16_t> {
- auto parse(fmt::basic_format_parse_context<char16_t>& ctx) {
- return fmt::formatter<std::u16string_view, char16_t>::parse(ctx);
- }
-
- template <typename FormatContext>
- auto format(const cru::platform::gui::CompositionText& ct,
- FormatContext& ctx) {
- auto output = ctx.out();
- output = format_to(output, u"text: {}\n", ct.text);
- output = format_to(output, u"clauses:\n");
- for (gsl::index i = 0; i < static_cast<gsl::index>(ct.clauses.size());
- i++) {
- const auto& clause = ct.clauses[i];
- output =
- format_to(output, u"\t{}. start: {} end: {}{}\n", i, clause.start,
- clause.end, clause.target ? u" target" : u"");
- }
- output = format_to(output, u"selection: position: {} count: {}",
- ct.selection.position, ct.selection.count);
- return output;
- }
-};
+// template <>
+// struct fmt::formatter<cru::platform::gui::CompositionText, char16_t>
+// : fmt::formatter<std::u16string_view, char16_t> {
+// auto parse(fmt::basic_format_parse_context<char16_t>& ctx) {
+// return fmt::formatter<std::u16string_view, char16_t>::parse(ctx);
+// }
+
+// template <typename FormatContext>
+// auto format(const cru::platform::gui::CompositionText& ct,
+// FormatContext& ctx) {
+// auto output = ctx.out();
+// output = format_to(output, u"text: {}\n", ct.text);
+// output = format_to(output, u"clauses:\n");
+// for (gsl::index i = 0; i < static_cast<gsl::index>(ct.clauses.size());
+// i++) {
+// const auto& clause = ct.clauses[i];
+// output =
+// format_to(output, u"\t{}. start: {} end: {}{}\n", i, clause.start,
+// clause.end, clause.target ? u" target" : u"");
+// }
+// output = format_to(output, u"selection: position: {} count: {}",
+// ct.selection.position, ct.selection.count);
+// return output;
+// }
+// };
diff --git a/include/cru/ui/render/MeasureRequirement.hpp b/include/cru/ui/render/MeasureRequirement.hpp
index 6a0c6952..ff9dd6e3 100644
--- a/include/cru/ui/render/MeasureRequirement.hpp
+++ b/include/cru/ui/render/MeasureRequirement.hpp
@@ -1,9 +1,8 @@
#pragma once
#include "Base.hpp"
-#include "cru/common/Format.hpp"
+#include "cru/common/String.hpp"
-#include <fmt/core.h>
#include <algorithm>
#include <limits>
#include <string>
@@ -169,9 +168,8 @@ struct MeasureSize {
};
}
- std::u16string ToDebugString() const {
- return fmt::format(u"({}, {})", width.ToDebugString(),
- height.ToDebugString());
+ String ToDebugString() const {
+ return Format(u"({}, {})", width.ToDebugString(), height.ToDebugString());
}
constexpr static MeasureSize NotSpecified() {
@@ -240,9 +238,9 @@ struct MeasureRequirement {
return result;
}
- std::u16string ToDebugString() const {
- return fmt::format(u"{{min: {}, max: {}}}", min.ToDebugString(),
- max.ToDebugString());
+ String ToDebugString() const {
+ return Format(u"{{min: {}, max: {}}}", min.ToDebugString(),
+ max.ToDebugString());
}
constexpr static MeasureRequirement Merge(const MeasureRequirement& left,
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 1056a763..e1642da2 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -30,5 +30,4 @@ else()
endif()
find_package(Microsoft.GSL CONFIG REQUIRED)
-find_package(fmt CONFIG REQUIRED)
-target_link_libraries(cru_base PUBLIC Microsoft.GSL::GSL fmt::fmt)
+target_link_libraries(cru_base PUBLIC Microsoft.GSL::GSL)
diff --git a/src/common/Logger.cpp b/src/common/Logger.cpp
index af1dd692..e77e8a85 100644
--- a/src/common/Logger.cpp
+++ b/src/common/Logger.cpp
@@ -30,7 +30,7 @@ void Logger::RemoveSource(ILogSource *source) {
}
namespace {
-std::u16string_view LogLevelToString(LogLevel level) {
+String LogLevelToString(LogLevel level) {
switch (level) {
case LogLevel::Debug:
return u"DEBUG";
@@ -45,36 +45,35 @@ std::u16string_view LogLevelToString(LogLevel level) {
}
}
-std::u16string GetLogTime() {
+String GetLogTime() {
auto time = std::time(nullptr);
auto calendar = std::localtime(&time);
- return fmt::format(u"{}:{}:{}", calendar->tm_hour, calendar->tm_min,
- calendar->tm_sec);
+ return Format(u"{}:{}:{}", calendar->tm_hour, calendar->tm_min,
+ calendar->tm_sec);
}
} // namespace
-void Logger::Log(LogLevel level, std::u16string_view s) {
+void Logger::Log(LogLevel level, const String &message) {
#ifndef CRU_DEBUG
if (level == LogLevel::Debug) {
return;
}
#endif
for (const auto &source : sources_) {
- source->Write(level, fmt::format(u"[{}] {}: {}\n", GetLogTime(),
- LogLevelToString(level), s));
+ source->Write(level, Format(u"[{}] {}: {}\n", GetLogTime(),
+ LogLevelToString(level), message));
}
}
-void Logger::Log(LogLevel level, std::u16string_view tag,
- std::u16string_view s) {
+void Logger::Log(LogLevel level, const String &tag, const String &message) {
#ifndef CRU_DEBUG
if (level == LogLevel::Debug) {
return;
}
#endif
for (const auto &source : sources_) {
- source->Write(level, fmt::format(u"[{}] {} {}: {}\n", GetLogTime(),
- LogLevelToString(level), tag, s));
+ source->Write(level, Format(u"[{}] {} {}: {}\n", GetLogTime(),
+ LogLevelToString(level), tag, message));
}
}
} // namespace cru::log
diff --git a/src/common/String.cpp b/src/common/String.cpp
index e9acf984..94eb8f27 100644
--- a/src/common/String.cpp
+++ b/src/common/String.cpp
@@ -101,6 +101,10 @@ String::~String() {
}
}
+String::String(from_buffer_tag, std::uint16_t* buffer, Index size,
+ Index capacity)
+ : buffer_(buffer), size_(size), capacity_(capacity) {}
+
void String::resize(Index new_size) {
Expects(new_size >= 0);
@@ -137,7 +141,7 @@ void String::reserve(Index new_capacity) {
}
}
-String::iterator String::insert(const_iterator pos, std::uint16_t* str,
+String::iterator String::insert(const_iterator pos, const std::uint16_t* str,
Index size) {
Index new_size = size_ + size;
if (new_size > capacity_) {
@@ -239,4 +243,54 @@ int String::Compare(const String& other) const {
}
}
+namespace details {
+std::vector<FormatToken> ParseToFormatTokenList(const String& str) {
+ std::vector<FormatToken> result;
+
+ auto push_char = [&result](std::uint16_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 < 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
+
} // namespace cru
diff --git a/src/osx/graphics/quartz/CMakeLists.txt b/src/osx/graphics/quartz/CMakeLists.txt
index c6bb29cb..868a3ee2 100644
--- a/src/osx/graphics/quartz/CMakeLists.txt
+++ b/src/osx/graphics/quartz/CMakeLists.txt
@@ -20,6 +20,6 @@ target_sources(cru_osx_graphics_quartz PUBLIC
${CRU_OSX_GRAPHICS_NATIVE_INCLUDE_DIR}/Resource.hpp
${CRU_OSX_GRAPHICS_NATIVE_INCLUDE_DIR}/TextLayout.hpp
)
-target_link_libraries(cru_osx_graphics_quartz PUBLIC cocoa)
+target_link_libraries(cru_osx_graphics_quartz PUBLIC quartz)
target_link_libraries(cru_osx_graphics_quartz PUBLIC cru_osx_base cru_platform_graphics)
diff --git a/src/parse/Grammar.cpp b/src/parse/Grammar.cpp
index 95c65e99..34eb2dd4 100644
--- a/src/parse/Grammar.cpp
+++ b/src/parse/Grammar.cpp
@@ -122,8 +122,6 @@ Grammar::GenerateLeftProductionMap() const {
}
void Grammar::EliminateLeftRecursions() {
- // TODO: Use a better name.
-
auto nonterminals = nonterminals_;
for (int i = 0; i < nonterminals.size(); i++) {
auto ni = nonterminals[i];
@@ -148,6 +146,7 @@ void Grammar::EliminateLeftRecursions() {
auto new_right = right;
new_right.insert(new_right.cbegin(), jp->GetRight().cbegin(),
jp->GetRight().cend());
+ // TODO: What should this name be.
CreateProduction(u"", ni, std::move(new_right));
}
}
@@ -167,22 +166,29 @@ void Grammar::EliminateLeftRecursions() {
}
}
- auto ni_h = CreateNonterminal(u"");
+ auto ni_h = CreateNonterminal(ni->GetName() +
+ u" (Eliminate Left Recursion Helper)");
for (auto p : i_nr_ps) {
auto right = p->GetRight();
right.push_back(ni_h);
- CreateProduction(u"", ni, std::move(right));
+ CreateProduction(p->GetName() + u" (Eliminate Left Recursion Of " +
+ ni->GetName() + u")",
+ ni, std::move(right));
}
for (auto p : i_r_ps) {
auto right = p->GetRight();
right.erase(right.cbegin());
right.push_back(ni_h);
- CreateProduction(u"", ni_h, std::move(right));
+ CreateProduction(p->GetName() + u" (Eliminate Left Recursion Of " +
+ ni->GetName() + u")",
+ ni_h, std::move(right));
}
- CreateProduction(u"", ni_h, std::vector<Symbol*>{});
+ CreateProduction(u"Empty Production (Eliminate Left Recursion Of " +
+ ni->GetName() + u")",
+ ni_h, std::vector<Symbol*>{});
for (auto p : i_r_ps) {
RemoveProduction(p);
@@ -193,4 +199,6 @@ void Grammar::EliminateLeftRecursions() {
}
}
}
+
+void Grammar::LeftFactor() {}
} // namespace cru::parse
diff --git a/src/platform/Color.cpp b/src/platform/Color.cpp
index fe512715..c4cc511b 100644
--- a/src/platform/Color.cpp
+++ b/src/platform/Color.cpp
@@ -6,7 +6,6 @@
#include <stdexcept>
#include <string>
#include <string_view>
-#include "fmt/core.h"
namespace cru::platform {
std::string Color::ToUtf8String() const {
diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt
index c1fd078d..730607d2 100644
--- a/test/common/CMakeLists.txt
+++ b/test/common/CMakeLists.txt
@@ -1,4 +1,6 @@
add_executable(cru_base_test
+ HandlerRegistryTest.cpp
+ StringTest.cpp
StringUtilTest.cpp
)
target_link_libraries(cru_base_test PRIVATE cru_base cru_test_base)
diff --git a/test/common/StringTest.cpp b/test/common/StringTest.cpp
new file mode 100644
index 00000000..1200a60b
--- /dev/null
+++ b/test/common/StringTest.cpp
@@ -0,0 +1,9 @@
+#include "cru/common/String.hpp"
+
+#include <gtest/gtest.h>
+
+TEST(String, Format) {
+ using cru::Format;
+
+ ASSERT_EQ(Format(u"{} + {} = {}", 123, 321, 444), u"123 + 321 = 444");
+}
diff --git a/vcpkg.json b/vcpkg.json
index 4d97e3fb..cd113520 100644
--- a/vcpkg.json
+++ b/vcpkg.json
@@ -4,7 +4,6 @@
"version": "0.0.1",
"dependencies": [
"ms-gsl",
- "fmt",
"gtest",
"boost-property-tree",
"boost-functional"