21 static constexpr size_t npos = -1;
24 constexpr string(
const char (&str)[N])
38 constexpr string(
const char* str,
const size_t n)
42 char*
begin{
new char[_capacity]};
43 memcpy(
begin, str, _size);
47 constexpr string(
const size_t n,
const char c)
51 char*
begin{
new char[_capacity]};
52 memset(
begin, c, _size);
56 constexpr string(
const string& str,
const size_t pos,
const size_t n)
65 clone(_size, _capacity, str.
data()+pos);
70 , _capacity{str._capacity}
73 _begin = std::get<const char*>(str._begin);
75 clone(str._size, str._capacity, str.
data());
80 , _capacity{str._capacity}
83 _begin = std::get<const char*>(str._begin);
85 _begin = std::move(std::get<uptr>(str._begin));
93 _capacity = str._capacity;
96 _begin = std::get<const char*>(str._begin);
98 clone(_size, _capacity, str.
data());
108 _capacity = str._capacity;
110 if (str.is_literal())
111 _begin = std::get<const char*>(str._begin);
113 _begin = std::move(std::get<uptr>(str._begin));
128 clone(_size, _capacity, std::get<const char*>(_begin));
129 return std::get<uptr>(_begin).get()[n];
133 return (is_literal()) ? std::get<const char*>(_begin)[n] : std::get<uptr>(_begin).get()[n];
136 char&
at(
const size_t n) {
141 const char at(
const size_t n)
const {
142 eosio::check(0 <= n && n < _size,
"eosio::string::at const");
171 static size_t prev_size{0};
172 char* raw_ptr{
nullptr};
175 return std::get<const char*>(_begin);
177 if (_size == prev_size)
178 return std::get<uptr>(_begin).get();
179 else if (_size < prev_size)
180 raw_ptr = std::get<uptr>(_begin).get();
182 uptr tmp = std::make_unique<char[]>(_size+1);
185 memcpy(raw_ptr, std::get<uptr>(_begin).get(), _size);
188 raw_ptr[_size+1] =
'\0';
195 clone(_size, _capacity, std::get<const char*>(_begin));
198 return std::get<uptr>(_begin).get();
202 return (is_literal()) ? std::get<const char*>(_begin) : std::get<uptr>(_begin).get();
206 return begin()+_size;
237 const char* tmp{(is_literal()) ? std::get<const char*>(_begin) : std::get<uptr>(_begin).get()};
238 clone(_size, _capacity, tmp);
252 clone(_size, _capacity, std::get<const char*>(_begin));
253 std::get<uptr>(_begin).get()[0] =
'\0';
258 clone(n, _capacity, std::get<const char*>(_begin));
262 memset(std::get<uptr>(_begin).get()+_size,
'\0', _capacity-_size);
265 clone(_size, _capacity, std::get<uptr>(_begin).get());
271 std::swap(*
this, str);
288 size_t copy(
char* s,
size_t len,
size_t pos = 0)
const {
292 const char* tmp{(is_literal()) ? std::get<const char*>(_begin) : std::get<uptr>(_begin).get()};
293 memcpy(s, tmp+pos,
len);
295 return (_size < pos+
len) ? _size-pos :
len;
298 string&
insert(
const size_t pos,
const char* str) {
299 return insert(pos, str, strlen(str));
302 string&
insert(
const size_t pos,
const char* str,
const size_t len) {
303 eosio::check((str !=
nullptr) && (0 <= pos && pos <= _size),
"eosio::string::insert");
305 if (_capacity < (_size+
len)) {
309 uptr
begin{std::make_unique<char[]>(_capacity)};
310 const char* tmp{(is_literal()) ? std::get<const char*>(_begin) : std::get<uptr>(_begin).get()};
312 memcpy(
begin.get(), tmp, pos);
314 memcpy(
begin.get()+
len+pos, tmp+pos, _size-
len-pos);
316 _begin = std::move(
begin);
320 clone(_size, _capacity, std::get<const char*>(_begin));
322 memmove(std::get<uptr>(_begin).get()+pos+
len, std::get<uptr>(_begin).get()+pos, _size-pos);
323 memcpy(std::get<uptr>(_begin).get()+pos, str,
len);
329 string&
insert(
const size_t pos,
const string& str) {
335 eosio::check(0 <= pos && pos <= _size,
"eosio::string::erase");
343 clone(_size, _capacity, std::get<const char*>(_begin));
344 memmove(std::get<uptr>(_begin).get()+pos+
len, std::get<uptr>(_begin).get(),
len);
363 if (_capacity == 0) {
366 clone(1, _capacity, &c);
368 else if (_size == _capacity) {
369 _capacity = ++_size*2;
371 const char* tmp{(is_literal()) ? std::get<const char*>(_begin) : std::get<uptr>(_begin).get()};
372 clone(_size, _capacity, tmp);
373 std::get<uptr>(_begin).get()[_size-1] = c;
376 std::get<uptr>(_begin).get()[_size++] = c;
392 const char* tmp{(is_literal()) ? std::get<const char*>(_begin) : std::get<uptr>(_begin).get()};
393 internal_use_do_not_use::prints_l(tmp, _size);
396 friend bool operator< (
const string& lhs,
const string& rhs);
397 friend bool operator> (
const string& lhs,
const string& rhs);
398 friend bool operator<=(
const string& lhs,
const string& rhs);
399 friend bool operator>=(
const string& lhs,
const string& rhs);
400 friend bool operator==(
const string& lhs,
const string& rhs);
401 friend bool operator!=(
const string& lhs,
const string& rhs);
403 friend string operator+ (
const string& lhs,
const string& rhs);
406 using uptr = std::unique_ptr<char[]>;
407 using sso_str = std::variant<const char*, uptr>;
410 size_t _capacity = 0;
411 sso_str _begin =
nullptr;
413 void clone(
size_t size,
size_t capacity,
const char* str) {
419 _begin = std::move(
begin);
422 constexpr bool is_literal()
const {
423 return (std::holds_alternative<const char*>(_begin)) ? true :
false;
427 inline bool operator< (
const string& lhs,
const string& rhs) {
428 const char* beg_lhs{lhs.
cbegin()};
const char* end_lhs{lhs.
cend()};
429 const char* beg_rhs{rhs.
cbegin()};
const char* end_rhs{rhs.
cend()};
431 for(; beg_lhs != end_lhs && beg_rhs != end_rhs; ++beg_lhs, ++beg_rhs) {
432 if (*beg_lhs < *beg_rhs)
434 if (*beg_rhs < *beg_lhs)
438 return beg_lhs == end_lhs && beg_rhs != end_rhs;
441 inline bool operator> (
const string& lhs,
const string& rhs) {
445 inline bool operator<=(
const string& lhs,
const string& rhs) {
449 inline bool operator>=(
const string& lhs,
const string& rhs) {
453 inline bool operator==(
const string& lhs,
const string& rhs) {
454 return !(lhs < rhs) && !(rhs < lhs);
457 inline bool operator!=(
const string& lhs,
const string& rhs) {
458 return !(lhs == rhs);
461 inline string operator+(
const string& lhs,
const string& rhs) {
467 template<
typename DataStream>
475 template<
typename DataStream>
477 std::vector<char> tmp;
479 str = (tmp.size()) ?
string(tmp.data(), tmp.size()) :
string();