summaryrefslogtreecommitdiff
path: root/src/string.cc
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2016-02-05 09:27:22 +0000
committerMaxime Coste <frrrwww@gmail.com>2016-02-10 09:44:42 +0000
commit8d37a716fbf83cd58a026d70a293cb30f972ecaa (patch)
tree050dbb7e18abcfcf711cf64700611353337c2eda /src/string.cc
parent87769c9b03b516053249f86355a4e503a529c659 (diff)
Use a custom SSO aware string backend
Diffstat (limited to 'src/string.cc')
-rw-r--r--src/string.cc119
1 files changed, 119 insertions, 0 deletions
diff --git a/src/string.cc b/src/string.cc
index 9395a26e..2734042b 100644
--- a/src/string.cc
+++ b/src/string.cc
@@ -10,6 +10,125 @@
namespace Kakoune
{
+String::Data::Data(const char* data, size_t size, size_t capacity)
+{
+ if (capacity > Short::capacity)
+ {
+ if (capacity & 1)
+ ++capacity;
+
+ l.ptr = Alloc{}.allocate(capacity+1);
+ l.size = size;
+ l.capacity = capacity;
+
+ memcpy(l.ptr, data, size);
+ l.ptr[size] = 0;
+ }
+ else
+ set_short(data, size);
+}
+
+String::Data::Data(Data&& other) noexcept
+{
+ if (other.is_long())
+ {
+ l = other.l;
+ other.s.size = 1;
+ }
+ else
+ s = other.s;
+}
+
+String::Data& String::Data::operator=(const Data& other)
+{
+ const size_t new_size = other.size();
+ reserve<false>(new_size);
+ memcpy(data(), other.data(), new_size+1);
+ set_size(new_size);
+
+ return *this;
+}
+
+String::Data& String::Data::operator=(Data&& other) noexcept
+{
+ if (other.is_long())
+ {
+ l = other.l;
+ other.set_empty();
+ }
+ else
+ s = other.s;
+
+ return *this;
+}
+
+template<bool copy>
+void String::Data::reserve(size_t new_capacity)
+{
+ if (new_capacity <= capacity())
+ return;
+
+ if (is_long())
+ new_capacity = std::max(l.capacity * 2, new_capacity);
+
+ char* new_ptr = Alloc{}.allocate(new_capacity+1);
+ if (copy)
+ {
+ memcpy(new_ptr, data(), size()+1);
+ l.size = size();
+ }
+ release();
+
+ l.ptr = new_ptr;
+ l.capacity = new_capacity;
+}
+
+template void String::Data::reserve<true>(size_t);
+template void String::Data::reserve<false>(size_t);
+
+void String::Data::force_size(size_t new_size)
+{
+ reserve<false>(new_size);
+ set_size(new_size);
+}
+
+void String::Data::append(const char* str, size_t len)
+{
+ const size_t new_size = size() + len;
+ reserve(new_size);
+
+ memcpy(data() + size(), str, len);
+ set_size(new_size);
+ data()[new_size] = 0;
+}
+
+void String::Data::clear()
+{
+ release();
+ set_empty();
+}
+
+void String::Data::release()
+{
+ if (is_long())
+ Alloc{}.deallocate(l.ptr, l.capacity+1);
+}
+
+void String::Data::set_size(size_t size)
+{
+ if (is_long())
+ l.size = size;
+ else
+ s.size = (size << 1) | 1;
+}
+
+void String::Data::set_short(const char* data, size_t size)
+{
+ s.size = (size << 1) | 1;
+ memcpy(s.string, data, size);
+ s.string[size] = 0;
+}
+
const String String::ms_empty;
Vector<String> split(StringView str, char separator, char escape)