From 2f9cab7e54216a9f7fceb0d870a98da92db90e43 Mon Sep 17 00:00:00 2001 From: mniip Date: Thu, 3 May 2018 00:34:47 +0300 Subject: [PATCH] Move "big" methods out of the header. Also fix Partition --- src/common/String.cpp | 140 ++++++++++++++++++++++++++++++++-- src/common/String.h | 171 +++++++++++++++++------------------------- 2 files changed, 202 insertions(+), 109 deletions(-) diff --git a/src/common/String.cpp b/src/common/String.cpp index 87f1333275..efa4fea490 100644 --- a/src/common/String.cpp +++ b/src/common/String.cpp @@ -16,19 +16,84 @@ ByteString ConversionError::formatError(ByteString::value_type const *at, ByteSt } -std::codecvt_utf8 convert(1); +static std::codecvt_utf8 convert(1); + +std::vector ByteString::PartitionBy(value_type ch, bool includeEmpty) const +{ + std::vector result; + size_t at = 0; + while(true) + { + Split split = SplitBy(ch, at); + ByteString part = split.Before(); + if(includeEmpty || part.size()) + result.push_back(part); + at = split.PositionAfter(); + if(!split) + break; + } + return result; +} + +std::vector ByteString::PartitionBy(ByteString const &str, bool includeEmpty) const +{ + std::vector result; + size_t at = 0; + while(true) + { + Split split = SplitBy(str, at); + ByteString part = split.Before(); + if(includeEmpty || part.size()) + result.push_back(part); + at = split.PositionAfter(); + if(!split) + break; + } + return result; +} + +std::vector ByteString::PartitionByAny(ByteString const &str, bool includeEmpty) const +{ + std::vector result; + size_t at = 0; + while(true) + { + Split split = SplitByAny(str, at); + ByteString part = split.Before(); + if(includeEmpty || part.size()) + result.push_back(part); + at = split.PositionAfter(); + if(!split) + break; + } + return result; +} + +ByteString &ByteString::Substitute(ByteString const &needle, ByteString const &replacement) +{ + size_t needleSize = needle.size(); + size_t replacementSize = replacement.size(); + size_t at = super::find(needle); + while(at != npos) + { + super::replace(at, needleSize, replacement); + at += replacementSize + !needleSize; + at = super::find(needle, at); + } + return *this; +} String ByteString::FromUtf8(bool ignoreError) const { std::vector destination = std::vector(size(), String::value_type()); - std::codecvt_utf8::state_type state; + std::codecvt_utf8::state_type state; ByteString::value_type const *from = data(), *from_next; String::value_type *to = destination.data(), *to_next; while(true) { - std::codecvt_utf8::result result = convert.in(state, from, data() + size(), from_next, to, destination.data() + destination.size(), to_next); + std::codecvt_utf8::result result = convert.in(state, from, data() + size(), from_next, to, destination.data() + destination.size(), to_next); from = from_next; to = to_next; if(result == std::codecvt_base::ok || result == std::codecvt_base::noconv) @@ -58,17 +123,82 @@ String ByteString::FromUtf8(bool ignoreError) const } } +std::vector String::PartitionBy(value_type ch, bool includeEmpty) const +{ + std::vector result; + size_t at = 0; + while(true) + { + Split split = SplitBy(ch, at); + String part = split.Before(); + if(includeEmpty || part.size()) + result.push_back(part); + at = split.PositionAfter(); + if(!split) + break; + } + return result; +} + +std::vector String::PartitionBy(String const &str, bool includeEmpty) const +{ + std::vector result; + size_t at = 0; + while(true) + { + Split split = SplitBy(str, at); + String part = split.Before(); + if(includeEmpty || part.size()) + result.push_back(part); + at = split.PositionAfter(); + if(!split) + break; + } + return result; +} + +std::vector String::PartitionByAny(String const &str, bool includeEmpty) const +{ + std::vector result; + size_t at = 0; + while(true) + { + Split split = SplitByAny(str, at); + String part = split.Before(); + if(includeEmpty || part.size()) + result.push_back(part); + at = split.PositionAfter(); + if(!split) + break; + } + return result; +} + +String &String::Substitute(String const &needle, String const &replacement) +{ + size_t needleSize = needle.size(); + size_t replacementSize = replacement.size(); + size_t at = super::find(needle); + while(at != npos) + { + super::replace(at, needleSize, replacement); + at += replacementSize + !needleSize; + at = super::find(needle, at); + } + return *this; +} + ByteString String::ToUtf8() const { std::vector destination = std::vector(size(), ByteString::value_type()); - std::codecvt_utf8::state_type state; + std::codecvt_utf8::state_type state; String::value_type const *from = data(), *from_next; ByteString::value_type *to = destination.data(), *to_next; while(true) { - std::codecvt_utf8::result result = convert.out(state, from, data() + size(), from_next, to, destination.data() + destination.size(), to_next); + std::codecvt_utf8::result result = convert.out(state, from, data() + size(), from_next, to, destination.data() + destination.size(), to_next); from = from_next; to = to_next; if(result == std::codecvt_base::ok || result == std::codecvt_base::noconv) diff --git a/src/common/String.h b/src/common/String.h index ee3206b8bb..663eb03aed 100644 --- a/src/common/String.h +++ b/src/common/String.h @@ -13,12 +13,14 @@ class StringBuilder; template class SplitBase { T const &parent; + size_t posFrom; size_t posBefore; size_t posAfter; bool reverse; - inline SplitBase(T const &_parent, size_t _posBefore, size_t offset, bool _reverse): + inline SplitBase(T const &_parent, size_t _posFrom, size_t _posBefore, size_t offset, bool _reverse): parent(_parent), + posFrom(_posFrom), posBefore(_posBefore), posAfter(_posBefore == T::npos ? T::npos : _posBefore + offset), reverse(_reverse) @@ -27,16 +29,17 @@ template class SplitBase inline T Before(bool includeSeparator = false) const { if(posBefore == T::npos) - return reverse ? T() : parent; - return parent.Substr(0, includeSeparator ? posAfter : posBefore); + return reverse ? T() : parent.Substr(posFrom); + return parent.Substr(reverse ? 0 : posFrom, includeSeparator ? posAfter : posBefore); } inline T After(bool includeSeparator = false) const { if(posBefore == T::npos) - return reverse ? parent : T(); - return parent.Substr(includeSeparator ? posBefore : posAfter); + return reverse ? parent.Substr(0, posFrom) : T(); + return parent.Substr(includeSeparator ? posBefore : posAfter, reverse ? posFrom : T::npos); } + inline size_t PositionFrom() const { return posFrom; } inline size_t PositionBefore() const { return posBefore; } inline size_t PositionAfter() const { return posAfter; } @@ -77,30 +80,24 @@ class ByteString : public std::basic_string inline bool EndsWith(ByteString const &other) const { return super::compare(size() - other.size(), other.size(), other); } using Split = SplitBase; - inline Split SplitBy(value_type ch, size_t pos = 0) const { return Split(*this, super::find(ch, pos), 1, false); } - inline Split SplitBy(ByteString const &str, size_t pos = 0) const { return Split(*this, super::find(str, pos), str.size(), false); } - inline Split SplitByAny(ByteString const &str, size_t pos = 0) const { return Split(*this, super::find_first_of(str, pos), 1, false); } - inline Split SplitByNot(ByteString const &str, size_t pos = 0) const { return Split(*this, super::find_first_not_of(str, pos), 1, false); } - inline Split SplitFromEndBy(value_type ch, size_t pos = npos) const { return Split(*this, super::rfind(ch, pos), 1, true); } - inline Split SplitFromEndBy(ByteString const &str, size_t pos = npos) const { return Split(*this, super::find(str, pos), str.size(), true); } - inline Split SplitFromEndByAny(ByteString const &str, size_t pos = npos) const { return Split(*this, super::find_last_of(str, pos), 1, true); } - inline Split SplitFromEndByNot(ByteString const &str, size_t pos = npos) const { return Split(*this, super::find_last_not_of(str, pos), 1, true); } - - inline ByteString &Substitute(ByteString const &needle, ByteString const &replacement) - { - size_t needleSize = needle.size(); - size_t replacementSize = replacement.size(); - size_t at = super::find(needle); - while(at != npos) - { - super::replace(at, needleSize, replacement); - at += replacementSize + !needleSize; - at = super::find(needle, at); - } - return *this; - } + inline Split SplitBy(value_type ch, size_t pos = 0) const { return Split(*this, pos, super::find(ch, pos), 1, false); } + inline Split SplitBy(ByteString const &str, size_t pos = 0) const { return Split(*this, pos, super::find(str, pos), str.size(), false); } + inline Split SplitByAny(ByteString const &str, size_t pos = 0) const { return Split(*this, pos, super::find_first_of(str, pos), 1, false); } + inline Split SplitByNot(ByteString const &str, size_t pos = 0) const { return Split(*this, pos, super::find_first_not_of(str, pos), 1, false); } + inline Split SplitFromEndBy(value_type ch, size_t pos = npos) const { return Split(*this, pos, super::rfind(ch, pos), 1, true); } + inline Split SplitFromEndBy(ByteString const &str, size_t pos = npos) const { return Split(*this, pos, super::find(str, pos), str.size(), true); } + inline Split SplitFromEndByAny(ByteString const &str, size_t pos = npos) const { return Split(*this, pos, super::find_last_of(str, pos), 1, true); } + inline Split SplitFromEndByNot(ByteString const &str, size_t pos = npos) const { return Split(*this, pos, super::find_last_not_of(str, pos), 1, true); } -public: + std::vector PartitionBy(value_type ch, bool includeEmpty = false) const; + std::vector PartitionBy(ByteString const &str, bool includeEmpty = false) const; + std::vector PartitionByAny(ByteString const &str, bool includeEmpty = false) const; + + ByteString &Substitute(ByteString const &needle, ByteString const &replacement); + + inline ByteString &Insert(size_t pos, ByteString const &str) { super::insert(pos, str); return *this; } + inline ByteString &Erase(size_t pos, size_t count) { super::erase(pos, count); return *this; } + inline ByteString &EraseBetween(size_t from, size_t to) { if(from < to) super::erase(from, to - from); return *this; } String FromUtf8(bool ignoreError = true) const; inline String FromAscii() const; @@ -129,6 +126,18 @@ inline ByteString operator+(ByteString::value_type lhs, ByteString &&rhs) { retu inline ByteString operator+(ByteString::value_type const *lhs, ByteString const &rhs) { return lhs + static_cast const &>(rhs); } inline ByteString operator+(ByteString::value_type const *lhs, ByteString &&rhs) { return lhs + static_cast &&>(rhs); } +inline bool operator==(ByteString const &lhs, ByteString const &rhs) { return static_cast const &>(lhs) == static_cast const &>(rhs); } +inline bool operator==(ByteString const &lhs, std::basic_string const &rhs) { return static_cast const &>(lhs) == rhs; } +inline bool operator==(ByteString const &lhs, ByteString::value_type const *rhs) { return static_cast const &>(lhs) == rhs; } +inline bool operator==(std::basic_string const &lhs, ByteString const &rhs) { return lhs == static_cast const &>(rhs); } +inline bool operator==(ByteString::value_type const *lhs, ByteString const &rhs) { return lhs == static_cast const &>(rhs); } + +inline bool operator!=(ByteString const &lhs, ByteString const &rhs) { return static_cast const &>(lhs) != static_cast const &>(rhs); } +inline bool operator!=(ByteString const &lhs, std::basic_string const &rhs) { return static_cast const &>(lhs) != rhs; } +inline bool operator!=(ByteString const &lhs, ByteString::value_type const *rhs) { return static_cast const &>(lhs) != rhs; } +inline bool operator!=(std::basic_string const &lhs, ByteString const &rhs) { return lhs != static_cast const &>(rhs); } +inline bool operator!=(ByteString::value_type const *lhs, ByteString const &rhs) { return lhs != static_cast const &>(rhs); } + class String : public std::basic_string { using super = std::basic_string; @@ -162,87 +171,25 @@ class String : public std::basic_string inline bool EndsWith(String const &other) const { return super::compare(size() - other.size(), other.size(), other); } using Split = SplitBase; - inline Split SplitBy(value_type ch, size_t pos = 0) const { return Split(*this, super::find(ch, pos), 1, false); } - inline Split SplitBy(String const &str, size_t pos = 0) const { return Split(*this, super::find(str, pos), str.size(), false); } - inline Split SplitByAny(String const &str, size_t pos = 0) const { return Split(*this, super::find_first_of(str, pos), 1, false); } - inline Split SplitByNot(String const &str, size_t pos = 0) const { return Split(*this, super::find_first_not_of(str, pos), 1, false); } - inline Split SplitFromEndBy(value_type ch, size_t pos = npos) const { return Split(*this, super::rfind(ch, pos), 1, true); } - inline Split SplitFromEndBy(String const &str, size_t pos = npos) const { return Split(*this, super::find(str, pos), str.size(), true); } - inline Split SplitFromEndByAny(String const &str, size_t pos = npos) const { return Split(*this, super::find_last_of(str, pos), 1, true); } - inline Split SplitFromEndByNot(String const &str, size_t pos = npos) const { return Split(*this, super::find_last_not_of(str, pos), 1, true); } - - inline std::vector PartitionBy(value_type ch, bool includeEmpty = false) const - { - std::vector result; - size_t at = 0; - while(true) - { - Split split = SplitBy(ch, at); - String part = split.Before(); - if(includeEmpty || part.size()) - result.push_back(part); - at = split.PositionAfter(); - if(!split) - break; - } - return result; - } - - inline std::vector PartitionBy(String const &str, bool includeEmpty = false) const - { - std::vector result; - size_t at = 0; - while(true) - { - Split split = SplitBy(str, at); - String part = split.Before(); - if(includeEmpty || part.size()) - result.push_back(part); - at = split.PositionAfter(); - if(!split) - break; - } - return result; - } - - inline std::vector PartitionByAny(String const &str, bool includeEmpty = false) const - { - std::vector result; - size_t at = 0; - while(true) - { - Split split = SplitByAny(str, at); - String part = split.Before(); - if(includeEmpty || part.size()) - result.push_back(part); - at = split.PositionAfter(); - if(!split) - break; - } - return result; - } - - inline String &Substitute(String const &needle, String const &replacement) - { - size_t needleSize = needle.size(); - size_t replacementSize = replacement.size(); - size_t at = super::find(needle); - while(at != npos) - { - super::replace(at, needleSize, replacement); - at += replacementSize + !needleSize; - at = super::find(needle, at); - } - return *this; - } + inline Split SplitBy(value_type ch, size_t pos = 0) const { return Split(*this, pos, super::find(ch, pos), 1, false); } + inline Split SplitBy(String const &str, size_t pos = 0) const { return Split(*this, pos, super::find(str, pos), str.size(), false); } + inline Split SplitByAny(String const &str, size_t pos = 0) const { return Split(*this, pos, super::find_first_of(str, pos), 1, false); } + inline Split SplitByNot(String const &str, size_t pos = 0) const { return Split(*this, pos, super::find_first_not_of(str, pos), 1, false); } + inline Split SplitFromEndBy(value_type ch, size_t pos = npos) const { return Split(*this, pos, super::rfind(ch, pos), 1, true); } + inline Split SplitFromEndBy(String const &str, size_t pos = npos) const { return Split(*this, pos,super::find(str, pos), str.size(), true); } + inline Split SplitFromEndByAny(String const &str, size_t pos = npos) const { return Split(*this, pos, super::find_last_of(str, pos), 1, true); } + inline Split SplitFromEndByNot(String const &str, size_t pos = npos) const { return Split(*this, pos, super::find_last_not_of(str, pos), 1, true); } + + std::vector PartitionBy(value_type ch, bool includeEmpty = false) const; + std::vector PartitionBy(String const &str, bool includeEmpty = false) const; + std::vector PartitionByAny(String const &str, bool includeEmpty = false) const; + + String &Substitute(String const &needle, String const &replacement); inline String &Insert(size_t pos, String const &str) { super::insert(pos, str); return *this; } inline String &Erase(size_t pos, size_t count) { super::erase(pos, count); return *this; } inline String &EraseBetween(size_t from, size_t to) { if(from < to) super::erase(from, to - from); return *this; } - inline bool operator==(String const &other) { return std::basic_string(*this) == other; } - inline bool operator!=(String const &other) { return std::basic_string(*this) != other; } - ByteString ToUtf8() const; ByteString ToAscii() const; template static String Build(Ts&&... args); @@ -275,6 +222,22 @@ inline String operator+(String::value_type const *lhs, String &&rhs) { return lh template inline String operator+(ByteString::value_type const (&lhs)[N], String const &rhs) { return std::move(ByteString(lhs).FromAscii()) + static_cast const &>(rhs); } template inline String operator+(ByteString::value_type const (&lhs)[N], String &&rhs) { return std::move(ByteString(lhs).FromAscii()) + static_cast &&>(rhs); } +inline bool operator==(String const &lhs, String const &rhs) { return static_cast const &>(lhs) == static_cast const &>(rhs); } +inline bool operator==(String const &lhs, std::basic_string const &rhs) { return static_cast const &>(lhs) == rhs; } +inline bool operator==(String const &lhs, String::value_type const *rhs) { return static_cast const &>(lhs) == rhs; } +template inline bool operator==(String const &lhs, ByteString::value_type const (&rhs)[N]) { return static_cast const &>(lhs) == std::move(ByteString(rhs).FromAscii()); } +inline bool operator==(std::basic_string const &lhs, String const &rhs) { return lhs == static_cast const &>(rhs); } +inline bool operator==(String::value_type const *lhs, String const &rhs) { return lhs == static_cast const &>(rhs); } +template inline bool operator==(ByteString::value_type const (&lhs)[N], String const &rhs) { return std::move(ByteString(lhs).FromAscii()) == static_cast const &>(rhs); } + +inline bool operator!=(String const &lhs, String const &rhs) { return static_cast const &>(lhs) != static_cast const &>(rhs); } +inline bool operator!=(String const &lhs, std::basic_string const &rhs) { return static_cast const &>(lhs) != rhs; } +inline bool operator!=(String const &lhs, String::value_type const *rhs) { return static_cast const &>(lhs) != rhs; } +template inline bool operator!=(String const &lhs, ByteString::value_type const (&rhs)[N]) { return static_cast const &>(lhs) != std::move(ByteString(rhs).FromAscii()); } +inline bool operator!=(std::basic_string const &lhs, String const &rhs) { return lhs != static_cast const &>(rhs); } +inline bool operator!=(String::value_type const *lhs, String const &rhs) { return lhs != static_cast const &>(rhs); } +template inline bool operator!=(ByteString::value_type const (&lhs)[N], String const &rhs) { return std::move(ByteString(lhs).FromAscii()) != static_cast const &>(rhs); } + inline String ByteString::FromAscii() const { String destination = String(size(), String::value_type());