diff options
-rw-r--r-- | include/cru/common/String.hpp | 9 | ||||
-rw-r--r-- | src/common/String.cpp | 39 | ||||
-rw-r--r-- | test/common/StringTest.cpp | 14 |
3 files changed, 59 insertions, 3 deletions
diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp index 8db012cb..e7688555 100644 --- a/include/cru/common/String.hpp +++ b/include/cru/common/String.hpp @@ -4,6 +4,7 @@ #include "Range.hpp" #include "StringUtil.hpp" +#include <double-conversion/double-conversion.h> #include <algorithm> #include <array> #include <charconv> @@ -23,6 +24,9 @@ class StringView; class CRU_BASE_API String { public: + static double_conversion::StringToDoubleConverter + kDefaultStringToDoubleConverter; + using value_type = char16_t; using size_type = Index; using difference_type = Index; @@ -195,6 +199,8 @@ class CRU_BASE_API String { String& TrimEnd(); String& Trim(); + std::vector<String> Split(value_type separator, + bool remove_space_line = false) const; std::vector<String> SplitToLines(bool remove_space_line = false) const; bool StartWith(StringView str) const; @@ -225,6 +231,9 @@ class CRU_BASE_API String { int Compare(const String& other) const; + float ParseToFloat(Index* processed_characters_count = nullptr) const; + double ParseToDouble(Index* processed_characters_count = nullptr) const; + private: static char16_t kEmptyBuffer[1]; diff --git a/src/common/String.cpp b/src/common/String.cpp index 9366abeb..48705d3b 100644 --- a/src/common/String.cpp +++ b/src/common/String.cpp @@ -2,6 +2,7 @@ #include "cru/common/Exception.hpp" #include "cru/common/StringUtil.hpp" +#include <cmath> #include <gsl/gsl> #include <algorithm> @@ -10,6 +11,15 @@ #include <string_view> namespace cru { +double_conversion::StringToDoubleConverter + String::kDefaultStringToDoubleConverter( + double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK | + double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES | + double_conversion::StringToDoubleConverter::ALLOW_TRAILING_SPACES | + double_conversion::StringToDoubleConverter:: + ALLOW_CASE_INSENSIBILITY, + 0.0, NAN, "infinity", "nan"); + template <typename C> Index GetStrSize(const C* str) { Index i = 0; @@ -261,7 +271,8 @@ String& String::Trim() { return *this; } -std::vector<String> String::SplitToLines(bool remove_space_line) const { +std::vector<String> String::Split(value_type separator, + bool remove_space_line) const { std::vector<String> result; if (size_ == 0) return result; @@ -269,7 +280,7 @@ std::vector<String> String::SplitToLines(bool remove_space_line) const { Index line_start = 0; Index line_end = 0; while (line_end < size_) { - if (buffer_[line_end] == '\n') { + if (buffer_[line_end] == separator) { if (remove_space_line) { bool add = false; for (Index i = line_start; i < line_end; i++) { @@ -305,6 +316,10 @@ std::vector<String> String::SplitToLines(bool remove_space_line) const { return result; } +std::vector<String> String::SplitToLines(bool remove_space_line) const { + return Split(u'\n', remove_space_line); +} + bool String::StartWith(StringView str) const { if (str.size() > size_) return false; return std::memcmp(str.data(), buffer_, str.size()) == 0; @@ -419,6 +434,26 @@ int StringView::Compare(const StringView& other) const { } } +float String::ParseToFloat(Index* processed_characters_count) const { + int pcc; + auto result = kDefaultStringToDoubleConverter.StringToFloat( + reinterpret_cast<const uc16*>(buffer_), static_cast<int>(size_), &pcc); + if (processed_characters_count != nullptr) { + *processed_characters_count = pcc; + } + return result; +} + +double String::ParseToDouble(Index* processed_characters_count) const { + int pcc; + auto result = kDefaultStringToDoubleConverter.StringToDouble( + reinterpret_cast<const uc16*>(buffer_), static_cast<int>(size_), &pcc); + if (processed_characters_count != nullptr) { + *processed_characters_count = pcc; + } + return result; +} + StringView StringView::substr(Index pos) { Expects(pos >= 0 && pos < size_); return StringView(ptr_ + pos, size_ - pos); diff --git a/test/common/StringTest.cpp b/test/common/StringTest.cpp index 7198f47b..737a93ad 100644 --- a/test/common/StringTest.cpp +++ b/test/common/StringTest.cpp @@ -1,5 +1,5 @@ -#include "cru/common/String.hpp" #include "cru/common/Format.hpp" +#include "cru/common/String.hpp" #include <gtest/gtest.h> @@ -69,3 +69,15 @@ TEST(String, SplitToLinesRemoveSpaceLine) { ASSERT_EQ(lines[1], String(u"def")); ASSERT_EQ(lines[2], String(u"ghi")); } + +TEST(String, ParseToFloat) { + using cru::String; + ASSERT_EQ(String(u"3.14159").ParseToDouble(), 3.14159); + ASSERT_EQ(String(u" 3.14159").ParseToDouble(), 3.14159); + ASSERT_EQ(String(u" 3.14159 ").ParseToDouble(), 3.14159); + + cru::Index processed_char_count = 0; + ASSERT_EQ(String(u" 3.14159 garbege").ParseToDouble(&processed_char_count), + 3.14159); + ASSERT_EQ(processed_char_count, 9); +} |