summaryrefslogtreecommitdiff
path: root/src/string.hh
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2014-04-18 13:45:33 +0100
committerMaxime Coste <frrrwww@gmail.com>2014-04-18 13:47:39 +0100
commitaf2d82dfc17ccd0c32b0955b1588e3bca379ccab (patch)
tree8d7eb1b2f3ad6015b415646a4491250466df0635 /src/string.hh
parenta7e6e5b9362e961cd3c6a3ad29b2bd061a41b0d9 (diff)
Add StringView class for non owning string
Diffstat (limited to 'src/string.hh')
-rw-r--r--src/string.hh146
1 files changed, 144 insertions, 2 deletions
diff --git a/src/string.hh b/src/string.hh
index 57a2666a..8dd51404 100644
--- a/src/string.hh
+++ b/src/string.hh
@@ -61,6 +61,114 @@ public:
}
};
+class StringView
+{
+public:
+ constexpr StringView() : m_data{nullptr}, m_length{0} {}
+ constexpr StringView(const char* data, ByteCount length)
+ : m_data{data}, m_length{length} {}
+ constexpr StringView(const char* data) : m_data{data}, m_length{(int)strlen(data)} {}
+ constexpr StringView(const char* begin, const char* end) : m_data{begin}, m_length{(int)(end - begin)} {}
+ StringView(const String& str) : m_data{str.data().pointer()}, m_length{str.length()} {}
+
+ bool operator==(StringView other) const;
+ bool operator!=(StringView other) const;
+
+ const char* data() const { return m_data; }
+
+ using iterator = const char*;
+ using reverse_iterator = std::reverse_iterator<const char*>;
+
+ iterator begin() const { return m_data; }
+ 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]; }
+
+ char operator[](ByteCount pos) const { return m_data[(int)pos]; }
+
+ ByteCount length() const { return m_length; }
+ CharCount char_length() const { return utf8::distance(begin(), end()); }
+ 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
+
+private:
+ const char* m_data;
+ ByteCount m_length;
+};
+
+inline bool StringView::operator==(StringView other) const
+{
+ return m_length == other.m_length and memcmp(m_data, other.m_data, (int)m_length) == 0;
+}
+
+inline bool StringView::operator!=(StringView other) const
+{
+ return !this->operator==(other);
+}
+
+inline bool operator==(const char* lhs, StringView rhs)
+{
+ return StringView{lhs} == rhs;
+}
+
+inline bool operator!=(const char* lhs, StringView rhs)
+{
+ return StringView{lhs} != rhs;
+}
+
+inline bool operator==(const std::string& lhs, StringView rhs)
+{
+ return StringView{lhs} == rhs;
+}
+
+inline bool operator!=(const std::string& lhs, StringView rhs)
+{
+ return StringView{lhs} != 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
+{
+ return StringView{ m_data + (int)from, std::min(m_length - from, length) };
+}
+
+inline StringView StringView::substr(CharCount from, CharCount length) const
+{
+ auto beg = utf8::advance(begin(), end(), (int)from);
+ return StringView{ beg, utf8::advance(beg, end(), length) };
+}
+
+inline const char* begin(StringView str)
+{
+ return str.begin();
+}
+
+inline const char* end(StringView str)
+{
+ return str.end();
+}
+
inline String operator+(const char* lhs, const String& rhs)
{
return String(lhs) + rhs;
@@ -76,6 +184,40 @@ inline String operator+(const String& lhs, const std::string& rhs)
return lhs + String(rhs);
}
+inline String& operator+=(String& lhs, StringView rhs)
+{
+ lhs.append(rhs.data(), (size_t)(int)rhs.length());
+ return lhs;
+}
+
+inline String operator+(const char* lhs, StringView rhs)
+{
+ String res = lhs;
+ res += rhs;
+ return res;
+}
+
+inline String operator+(const String& lhs, StringView rhs)
+{
+ String 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+(StringView lhs, const char* rhs)
+{
+ String res{lhs.begin(), lhs.end()};
+ res.append(rhs);
+ return res;
+}
+
inline String operator+(char lhs, const String& rhs)
{
return String(lhs) + rhs;
@@ -114,8 +256,8 @@ String to_string(const StronglyTypedNumber<RealType, ValueType>& val)
return to_string((ValueType)val);
}
-bool prefix_match(const String& str, const String& prefix);
-bool subsequence_match(const String& str, const String& subseq);
+bool prefix_match(StringView str, StringView prefix);
+bool subsequence_match(StringView str, StringView subseq);
}