diff --git a/tstl/include/string.hpp b/tstl/include/string.hpp index f03ca142..3813bbd5 100644 --- a/tstl/include/string.hpp +++ b/tstl/include/string.hpp @@ -23,6 +23,42 @@ inline uint64_t str_len(const char* a){ return length; } +static constexpr const size_t SSO_SIZE = 16; + +template +struct base_small { + CharT data[SSO_SIZE]; +}; + +template +struct base_big { + size_t capacity; + unique_ptr data; + + base_big(size_t capacity, CharT* array) : capacity(capacity), data(array){ + //Nothing to do + } +}; + +template +union base_storage { + base_small small; + base_big big; + + base_storage(){ + //Default construction: Nothing to do + } + + base_storage(size_t capacity, CharT* array) : big(capacity, array) { + //Default construction: Nothing to do + } + + ~base_storage() {} +}; + +static_assert(SSO_SIZE == sizeof(base_small), "base_small must be the correct SSO size"); +static_assert(SSO_SIZE == sizeof(base_big), "base_big must be the correct SSO size"); + template struct basic_string { public: @@ -33,18 +69,30 @@ public: private: size_t _size; - size_t _capacity; - unique_ptr _data; + + base_storage storage; + + bool is_small() const { + return _size < 16; + } public: //Constructors - basic_string() : _size(0), _capacity(1), _data(new CharT[1]) { - _data[0] = '\0'; + basic_string() : _size(0){ + storage.small.data[0] = '\0'; } - basic_string(const CharT* s) : _size(str_len(s)), _capacity(_size + 1), _data(new CharT[_capacity]) { - std::copy_n(_data.get(), s, _capacity); + basic_string(const CharT* s) : _size(str_len(s)) { + auto capacity = _size + 1; + + if(is_small()){ + std::copy_n(&storage.small.data[0], s, capacity); + } else { + storage.big.capacity = capacity; + storage.big.data.reset(new CharT[capacity]); + std::copy_n(storage.big.data.get(), s, capacity); + } } explicit basic_string(size_t __capacity) : _size(0), _capacity(__capacity), _data(new CharT[_capacity]) { @@ -97,7 +145,11 @@ public: //Destructors - ~basic_string() = default; + ~basic_string(){ + if(!is_small()){ + storage.big.~base_big(); + } + } //Modifiers @@ -296,6 +348,8 @@ basic_string operator+(const basic_string& lhs, const C* rhs){ typedef basic_string string; +static_assert(sizeof(string) == 24, "The size of a string must always be 24 bytes"); + inline uint64_t parse(const char* it, const char* end){ int i = end - it - 1;