diff options
| author | Maxime Coste <frrrwww@gmail.com> | 2016-02-05 09:27:22 +0000 |
|---|---|---|
| committer | Maxime Coste <frrrwww@gmail.com> | 2016-02-10 09:44:42 +0000 |
| commit | 8d37a716fbf83cd58a026d70a293cb30f972ecaa (patch) | |
| tree | 050dbb7e18abcfcf711cf64700611353337c2eda /src/string.cc | |
| parent | 87769c9b03b516053249f86355a4e503a529c659 (diff) | |
Use a custom SSO aware string backend
Diffstat (limited to 'src/string.cc')
| -rw-r--r-- | src/string.cc | 119 |
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) |
