diff options
| author | Maxime Coste <frrrwww@gmail.com> | 2015-03-10 19:33:46 +0000 |
|---|---|---|
| committer | Maxime Coste <frrrwww@gmail.com> | 2015-03-10 19:50:22 +0000 |
| commit | 3c1a325b6f7c67c530d99aaaedf5f8c96f2b2de6 (patch) | |
| tree | f6cdaf2eec33dee178e3c888f5120ea43479b157 /src/string.hh | |
| parent | a0cf75ec39c679776b28b178a4299cf0ad204a1c (diff) | |
Refactor String, use a common StringOps interface, hide std::string
Diffstat (limited to 'src/string.hh')
| -rw-r--r-- | src/string.hh | 290 |
1 files changed, 127 insertions, 163 deletions
diff --git a/src/string.hh b/src/string.hh index 74df3fd7..4fb24c1e 100644 --- a/src/string.hh +++ b/src/string.hh @@ -14,56 +14,133 @@ namespace Kakoune class StringView; -using StringBase = std::basic_string<char, std::char_traits<char>, - Allocator<char, MemoryDomain::String>>; - -constexpr ByteCount strlen(const char* s) +template<typename Type, typename CharType> +class StringOps { - return *s == 0 ? 0 : strlen(s+1) + 1; -} +public: + using value_type = CharType; + + friend bool operator==(const Type& lhs, const Type& rhs) + { + return lhs.length() == rhs.length() and + std::equal(lhs.begin(), lhs.end(), rhs.begin()); + } + + friend bool operator!=(const Type& lhs, const Type& rhs) + { + return lhs.length() != rhs.length() or + not std::equal(lhs.begin(), lhs.end(), rhs.begin()); + } + + friend bool operator<(const Type& lhs, const Type& rhs) + { + return std::lexicographical_compare(lhs.begin(), lhs.end(), + rhs.begin(), rhs.end()); + } + + friend inline size_t hash_value(const Type& str) + { + return hash_data(str.data(), (int)str.length()); + } + + using iterator = CharType*; + using const_iterator = const CharType*; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + + [[gnu::always_inline]] + iterator begin() { return type().data(); } + + [[gnu::always_inline]] + const_iterator begin() const { return type().data(); } + + [[gnu::always_inline]] + iterator end() { return type().data() + (int)type().length(); } + + [[gnu::always_inline]] + const_iterator end() const { return type().data() + (int)type().length(); } + + reverse_iterator rbegin() { return reverse_iterator{end()}; } + const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; } + + reverse_iterator rend() { return reverse_iterator{begin()}; } + const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; } + + CharType& front() { return *type().data(); } + const CharType& front() const { return *type().data(); } + CharType& back() { return type().data()[(int)type().length() - 1]; } + const CharType& back() const { return type().data()[(int)type().length() - 1]; } + + [[gnu::always_inline]] + CharType& operator[](ByteCount pos) { return type().data()[(int)pos]; } + + [[gnu::always_inline]] + const CharType& operator[](ByteCount pos) const + { return type().data()[(int)pos]; } -class String : public StringBase + Codepoint operator[](CharCount pos) const + { return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); } + + CharCount char_length() const { return utf8::distance(begin(), end()); } + + [[gnu::always_inline]] + bool empty() const { return type().length() == 0_byte; } + + ByteCount byte_count_to(CharCount count) const + { return utf8::advance(begin(), end(), (int)count) - begin(); } + + CharCount char_count_to(ByteCount count) const + { return utf8::distance(begin(), begin() + (int)count); } + + StringView substr(ByteCount from, ByteCount length = INT_MAX) const; + StringView substr(CharCount from, CharCount length = INT_MAX) const; + +private: + Type& type() { return *static_cast<Type*>(this); } + const Type& type() const { return *static_cast<const Type*>(this); } +}; + +class String : public StringOps<String, char> { public: + using Content = std::basic_string<char, std::char_traits<char>, + Allocator<char, MemoryDomain::String>>; + String() {} - String(const char* content) : StringBase(content) {} - String(StringBase content) : StringBase(std::move(content)) {} - template<typename Char, typename Traits, typename Alloc> - String(const std::basic_string<Char, Traits, Alloc>& content) : StringBase(content.begin(), content.end()) {} - explicit String(char content, CharCount count = 1) : StringBase((size_t)(int)count, content) {} + String(const char* content) : m_data(content) {} + String(Content content) : m_data(std::move(content)) {} + explicit String(char content, CharCount count = 1) : m_data((size_t)(int)count, content) {} explicit String(Codepoint cp, CharCount count = 1) { while (count-- > 0) - utf8::dump(back_inserter(*this), cp); + utf8::dump(std::back_inserter(*this), cp); } template<typename Iterator> - String(Iterator begin, Iterator end) : StringBase(begin, end) {} + String(Iterator begin, Iterator end) : m_data(begin, end) {} - StringBase& stdstr() { return *this; } - const StringBase& stdstr() const { return *this; } + [[gnu::always_inline]] + char* data() { return &m_data[0]; } [[gnu::always_inline]] - char operator[](ByteCount pos) const { return StringBase::operator[]((int)pos); } + const char* data() const { return m_data.data(); } + [[gnu::always_inline]] - char& operator[](ByteCount pos) { return StringBase::operator[]((int)pos); } - Codepoint operator[](CharCount pos) { return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); } + ByteCount length() const { return ByteCount{(int)m_data.length()}; } [[gnu::always_inline]] - ByteCount length() const { return ByteCount{(int)StringBase::length()}; } - CharCount char_length() const { return utf8::distance(begin(), end()); } - ByteCount byte_count_to(CharCount count) const { return utf8::advance(begin(), end(), (int)count) - begin(); } - CharCount char_count_to(ByteCount count) const { return utf8::distance(begin(), begin() + (int)count); } + const char* c_str() const { return m_data.c_str(); } + + void append(const char* data, ByteCount count) { m_data.append(data, (size_t)(int)count); } - String& operator+=(const String& other) { StringBase::operator+=(other); return *this; } - String& operator+=(const char* other) { StringBase::operator+=(other); return *this; } - String& operator+=(char other) { StringBase::operator+=(other); return *this; } - String& operator+=(Codepoint cp) { utf8::dump(back_inserter(*this), cp); return *this; } + void push_back(char c) { m_data.push_back(c); } + void resize(ByteCount size) { m_data.resize((size_t)(int)size); } + void reserve(ByteCount size) { m_data.reserve((size_t)(int)size); } - StringView substr(ByteCount pos, ByteCount length = INT_MAX) const; - StringView substr(CharCount pos, CharCount length = INT_MAX) const; +private: + Content m_data; }; -class StringView +class StringView : public StringOps<StringView, const char> { public: constexpr StringView() : m_data{nullptr}, m_length{0} {} @@ -71,50 +148,17 @@ public: : m_data{data}, m_length{length} {} constexpr StringView(const char* data) : m_data{data}, m_length{strlen(data)} {} constexpr StringView(const char* begin, const char* end) : m_data{begin}, m_length{(int)(end - begin)} {} - template<typename Char, typename Traits, typename Alloc> - StringView(const std::basic_string<Char, Traits, Alloc>& str) : m_data{str.data()}, m_length{(int)str.length()} {} + StringView(const String& str) : m_data{str.data()}, m_length{(int)str.length()} {} StringView(const char& c) : m_data(&c), m_length(1) {} - friend bool operator==(StringView lhs, StringView rhs); - [[gnu::always_inline]] const char* data() const { return m_data; } - using iterator = const char*; - using reverse_iterator = std::reverse_iterator<const char*>; - - [[gnu::always_inline]] - iterator begin() const { return m_data; } - [[gnu::always_inline]] - iterator end() const { return m_data + (int)m_length; } - - reverse_iterator rbegin() const { return reverse_iterator{m_data + (int)m_length}; } - reverse_iterator rend() const { return reverse_iterator{m_data}; } - - char front() const { return *m_data; } - char back() const { return m_data[(int)m_length - 1]; } - - [[gnu::always_inline]] - char operator[](ByteCount pos) const { return m_data[(int)pos]; } - Codepoint operator[](CharCount pos) { return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); } - [[gnu::always_inline]] ByteCount length() const { return m_length; } - CharCount char_length() const { return utf8::distance(begin(), end()); } - - [[gnu::always_inline]] - bool empty() { return m_length == 0_byte; } - - ByteCount byte_count_to(CharCount count) const; - CharCount char_count_to(ByteCount count) const; - - StringView substr(ByteCount from, ByteCount length = INT_MAX) const; - StringView substr(CharCount from, CharCount length = INT_MAX) const; String str() const { return String{begin(), end()}; } - operator String() const { return str(); } // to remove - struct ZeroTerminatedString { ZeroTerminatedString(const char* begin, const char* end) @@ -122,53 +166,37 @@ public: if (*end == '\0') unowned = begin; else - owned = StringBase(begin, end); + owned = String::Content(begin, end); } operator const char*() const { return unowned ? unowned : owned.c_str(); } private: - StringBase owned; + String::Content owned; const char* unowned = nullptr; }; ZeroTerminatedString zstr() const { return ZeroTerminatedString{begin(), end()}; } private: + static constexpr ByteCount strlen(const char* s) + { + return *s == 0 ? 0 : strlen(s+1) + 1; + } + const char* m_data; ByteCount m_length; }; -inline bool operator==(StringView lhs, StringView rhs) -{ - return lhs.m_length == rhs.m_length and - std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -inline bool operator!=(StringView lhs, StringView rhs) -{ - return not (lhs == rhs); -} - -bool operator<(StringView lhs, StringView rhs); - -inline ByteCount StringView::byte_count_to(CharCount count) const -{ - return utf8::advance(begin(), end(), (int)count) - begin(); -} - -inline CharCount StringView::char_count_to(ByteCount count) const -{ - return utf8::distance(begin(), begin() + (int)count); -} - -inline StringView StringView::substr(ByteCount from, ByteCount length) const +template<typename Type, typename CharType> +inline StringView StringOps<Type, CharType>::substr(ByteCount from, ByteCount length) const { if (length < 0) length = INT_MAX; - return StringView{ m_data + (int)from, std::min(m_length - from, length) }; + return StringView{ type().data() + (int)from, std::min(type().length() - from, length) }; } -inline StringView StringView::substr(CharCount from, CharCount length) const +template<typename Type, typename CharType> +inline StringView StringOps<Type, CharType>::substr(CharCount from, CharCount length) const { if (length < 0) length = INT_MAX; @@ -176,70 +204,21 @@ inline StringView StringView::substr(CharCount from, CharCount length) const return StringView{ beg, utf8::advance(beg, end(), length) }; } -inline StringView String::substr(ByteCount pos, ByteCount length) const -{ - return StringView{*this}.substr(pos, length); -} - -inline StringView String::substr(CharCount pos, CharCount length) const -{ - return StringView{*this}.substr(pos, length); -} - inline String& operator+=(String& lhs, StringView rhs) { - lhs.append(rhs.data(), (size_t)(int)rhs.length()); + lhs.append(rhs.data(), rhs.length()); return lhs; } -inline String operator+(const String& lhs, const String& rhs) -{ - String res = lhs; - res += rhs; - return res; -} - inline String operator+(StringView lhs, StringView rhs) { - String res{lhs.begin(), lhs.end()}; - res += rhs; - return res; -} - -inline String operator+(const String& lhs, StringView rhs) -{ - String res = lhs; + String res; + res.reserve((int)(lhs.length() + rhs.length())); + res += lhs; res += rhs; return res; } -inline String operator+(StringView lhs, const String& rhs) -{ - String res{lhs.begin(), lhs.end()}; - res.append(rhs); - return res; -} - -inline String operator+(const char* lhs, StringView rhs) -{ - return StringView{lhs} + rhs; -} - -inline String operator+(StringView lhs, const char* rhs) -{ - return lhs + StringView{rhs}; -} - -inline String operator+(const char* lhs, const String& rhs) -{ - return StringView{lhs} + rhs; -} - -inline String operator+(const String& lhs, const char* rhs) -{ - return lhs + StringView{rhs}; -} - Vector<String> split(StringView str, char separator, char escape); Vector<StringView> split(StringView str, char separator); @@ -266,16 +245,11 @@ inline String operator"" _str(const char* str, size_t) return String(str); } -inline StringView operator"" _sv(const char* str, size_t len) -{ - return StringView(str, (int)len); -} - inline String codepoint_to_str(Codepoint cp) { - StringBase str; - utf8::dump(back_inserter(str), cp); - return String(str); + String str; + utf8::dump(std::back_inserter(str), cp); + return str; } int str_to_int(StringView str); @@ -301,16 +275,6 @@ String expand_tabs(StringView line, CharCount tabstop, CharCount col = 0); Vector<StringView> wrap_lines(StringView text, CharCount max_width); -inline size_t hash_value(const Kakoune::String& str) -{ - return hash_data(str.data(), (int)str.length()); -} - -inline size_t hash_value(const Kakoune::StringView& str) -{ - return hash_data(str.data(), (int)str.length()); -} - } #endif // string_hh_INCLUDED |
