summaryrefslogtreecommitdiff
path: root/src/string.hh
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2015-03-10 19:33:46 +0000
committerMaxime Coste <frrrwww@gmail.com>2015-03-10 19:50:22 +0000
commit3c1a325b6f7c67c530d99aaaedf5f8c96f2b2de6 (patch)
treef6cdaf2eec33dee178e3c888f5120ea43479b157 /src/string.hh
parenta0cf75ec39c679776b28b178a4299cf0ad204a1c (diff)
Refactor String, use a common StringOps interface, hide std::string
Diffstat (limited to 'src/string.hh')
-rw-r--r--src/string.hh290
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