aboutsummaryrefslogtreecommitdiff
path: root/include/cru/common
diff options
context:
space:
mode:
Diffstat (limited to 'include/cru/common')
-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
4 files changed, 106 insertions, 21 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