aboutsummaryrefslogtreecommitdiff
path: root/include/cru/common/String.hpp
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-09-14 22:10:02 +0800
committercrupest <crupest@outlook.com>2021-09-14 22:10:02 +0800
commit46d4838ac8ff1bd8658b57cf4ebb4438e396fce8 (patch)
treef1e04c19630c7f42ad57618e9a2d7cf5ea4d31c1 /include/cru/common/String.hpp
parent9bc202a2e1664df3e3c148abfe90a90501bc1650 (diff)
downloadcru-46d4838ac8ff1bd8658b57cf4ebb4438e396fce8.tar.gz
cru-46d4838ac8ff1bd8658b57cf4ebb4438e396fce8.tar.bz2
cru-46d4838ac8ff1bd8658b57cf4ebb4438e396fce8.zip
...
Diffstat (limited to 'include/cru/common/String.hpp')
-rw-r--r--include/cru/common/String.hpp98
1 files changed, 91 insertions, 7 deletions
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