Turi Create  4.0
gl_string.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_GL_STRING_H_
7 #define TURI_GL_STRING_H_
8 
9 #include <core/generics/vector_internals.hpp>
10 #include <core/generics/string_internals.hpp>
11 #include <core/util/cityhash_tc.hpp>
12 #include <core/generics/is_memmovable.hpp>
13 #include <algorithm>
14 
15 namespace turi {
16 
17 class gl_string {
18  public:
19  typedef char value_type;
20 
21  typedef value_type& reference;
22  typedef const value_type& const_reference;
23 
24  typedef value_type* pointer;
25  typedef const value_type* const_pointer;
26 
27  typedef value_type* iterator;
28  typedef const value_type* const_iterator;
29 
30  typedef std::reverse_iterator<value_type*> reverse_iterator;
31  typedef std::reverse_iterator<const value_type*> const_reverse_iterator;
32 
33  typedef ptrdiff_t difference_type;
34  typedef size_t size_type;
35 
36  static constexpr size_t npos = gl_string_internal::npos;
37 
38  private:
39 
40  /// The structur holding all the information
41  gl_vector_internal::_vstruct<value_type> *info;
42 
43  public:
44 
45  template <class InputIterator>
46  gl_string (InputIterator first, InputIterator last, _VEC_ENABLE_IF_ITERATOR(InputIterator, value_type))
47  : info(gl_vector_internal::construct<value_type, InputIterator>(first, last) )
48  {}
49 
50  gl_string ()
51  : info(nullptr)
52  {}
53 
54  explicit gl_string (size_t n)
55  : info(gl_vector_internal::construct<value_type>(n))
56  {}
57 
58  gl_string (size_t n, const value_type& val)
59  : info(gl_vector_internal::construct<value_type>(n, val))
60  {}
61 
62  gl_string(const gl_string& v)
63  : info(gl_vector_internal::construct<value_type>(v.begin(), v.end()))
64  {}
65 
66  gl_string (gl_string&& x) noexcept {
67  if(&x != this) {
68  info = x.info;
69  x.info = nullptr;
70  }
71  }
72 
73  explicit gl_string (const std::string& v)
74  : info(gl_vector_internal::construct<value_type>(v.begin(), v.end()))
75  {}
76 
77  gl_string (const char* d)
78  : info(gl_vector_internal::construct<value_type>(d, d + strlen(d)))
79  {}
80 
81  gl_string (const char* d, size_t n)
82  : info(gl_vector_internal::construct<value_type>(d, d + n))
83  {}
84 
85  gl_string (std::initializer_list<value_type> il)
86  : info(gl_vector_internal::construct<value_type>(il.begin(), il.end()) )
87  {}
88 
89  template <typename T1>
90  gl_string (std::initializer_list<T1> il, _VEC_ENABLE_IF_CONVERTABLE(T1, value_type))
91  : info(gl_vector_internal::construct<value_type>(il.begin(), il.end()) )
92  {}
93 
94  gl_string(const gl_string& str, size_t pos, size_t n = npos) {
95  info = gl_vector_internal::construct<value_type>(str._iter_at(pos), str._iter_at(pos, n));
96  }
97 
98  ~gl_string() {
99  if(info != nullptr) {
100  gl_vector_internal::destroy(info);
101  info = nullptr;
102  }
103  }
104 
105  ////////////////////////////////////////////////////////////////////////////////
106  // Properties and Sizing
107 
108  size_type size() const noexcept { return gl_vector_internal::size(info); }
109  size_type length() const noexcept { return size(); }
110 
111  size_type max_size() const noexcept { return std::numeric_limits<size_t>::max() / sizeof(value_type); }
112 
113  inline void resize (size_type n) {
114  if(gl_vector_internal::size(info) != n)
115  gl_vector_internal::resize(info, n);
116  DASSERT_EQ(gl_vector_internal::size(info), n);
117  }
118 
119  void resize (size_type n, const value_type& val) {
120  gl_vector_internal::resize(info, n, val);
121  }
122 
123  size_type capacity() const noexcept { return gl_vector_internal::capacity(info); }
124 
125  bool empty() const noexcept {
126  return size() == 0;
127  }
128 
129  void reserve (size_type n) {
130  gl_vector_internal::reserve(info, n);
131  }
132 
133  void shrink_to_fit() {
134  if(gl_vector_internal::has_excess_storage(info)) {
135  this->swap(gl_string(this->begin(), this->end()));
136  }
137  }
138 
139  ////////////////////////////////////////////////////////////////////////////////
140  // Element access
141 
142  reference operator[] (size_type idx) _VEC_NDEBUG_NOEXCEPT {
143  return gl_vector_internal::get_element(info, idx);
144  }
145 
146  const_reference operator[] (size_type idx) const _VEC_NDEBUG_NOEXCEPT {
147  return gl_vector_internal::get_element(info, idx);
148  }
149 
150  reference at (size_type idx) _VEC_NDEBUG_NOEXCEPT {
151  return gl_vector_internal::get_element(info, idx);
152  }
153 
154  const_reference at (size_type idx) const _VEC_NDEBUG_NOEXCEPT {
155  return gl_vector_internal::get_element(info, idx);
156  }
157 
158  reference front() _VEC_NDEBUG_NOEXCEPT {
159  DASSERT_NE(gl_vector_internal::size(info), 0);
160  return gl_vector_internal::get_element(info, 0);
161  }
162 
163  const_reference front() const _VEC_NDEBUG_NOEXCEPT {
164  DASSERT_NE(gl_vector_internal::size(info), 0);
165  return gl_vector_internal::get_element(info, 0);
166  }
167 
168  reference back() _VEC_NDEBUG_NOEXCEPT {
169  DASSERT_NE(gl_vector_internal::size(info), 0);
170  return gl_vector_internal::get_element(info, info->size - 1);
171  }
172 
173  const_reference back() const _VEC_NDEBUG_NOEXCEPT {
174  DASSERT_NE(gl_vector_internal::size(info), 0);
175  return gl_vector_internal::get_element(info, info->size - 1);
176  }
177 
178  ////////////////////////////////////////////////////////////////////////////////
179  // Assignment
180 
181  const gl_string& operator=(const gl_string& v) {
182  if(&v != this)
183  gl_vector_internal::assign(info, v.begin(), v.end());
184  return *this;
185  }
186 
187  const gl_string& operator=(gl_string&& v) {
188  assign(std::move(v));
189  return *this;
190  }
191 
192  const gl_string& operator=(std::initializer_list<value_type> il) {
193  gl_vector_internal::assign(info, il.begin(), il.end());
194  return *this;
195  }
196 
197  const gl_string& operator=(const std::string& v) {
198  gl_vector_internal::assign(info, v.begin(), v.end());
199  return *this;
200  }
201 
202  const gl_string& operator=(const char* v) {
203  gl_vector_internal::assign(info, v, v + std::strlen(v));
204  return *this;
205  }
206 
207  const gl_string& operator=(value_type c) {
208  gl_vector_internal::assign(info, 1, c);
209  return *this;
210  }
211 
212  template <class InputIterator>
213  void assign (const InputIterator& first, const InputIterator& last,
214  _VEC_ENABLE_IF_ITERATOR(InputIterator, value_type)) {
215  gl_vector_internal::assign(info, first, last);
216  }
217 
218  void assign(size_t n, const value_type& val) {
219  gl_vector_internal::assign(info, n, val);
220  }
221 
222  void assign(std::initializer_list<value_type> il) {
223  gl_vector_internal::assign(info, il);
224  }
225 
226  gl_string& assign(const gl_string& str) {
227  gl_vector_internal::assign(info, str.begin(), str.end());
228  return *this;
229  }
230 
231  gl_string& assign(gl_string&& str) {
232  gl_vector_internal::assign_move(info, str.info);
233  return *this;
234  }
235 
236  gl_string& assign(const gl_string& str, size_t pos, size_t n = npos) {
237  gl_vector_internal::assign<value_type>(info, str._iter_at(pos), str._iter_at(pos, n));
238  return *this;
239  }
240 
241  gl_string& assign(const value_type* s) {
242  gl_vector_internal::assign<value_type>(info, s, s + std::strlen(s));
243  return *this;
244  }
245 
246  gl_string& assign(const value_type* s, size_t n) {
247  gl_vector_internal::assign<value_type>(info, s, s + n);
248  return *this;
249  }
250 
251  ////////////////////////////////////////////////////////////////////////////////
252  // Insertion
253 
254  void push_back (const value_type& val) {
255  gl_vector_internal::push_back(info, val);
256  }
257 
258  void push_back (value_type&& val) {
259  gl_vector_internal::push_back(info, std::forward<value_type>(val));
260  }
261 
262 
263  template <class... Args>
264  iterator emplace (const_iterator position, Args&&... args) {
265  return gl_vector_internal::emplace(info, position, args...);
266  }
267 
268  template <class... Args>
269  void emplace_back (Args&&... args) {
270  gl_vector_internal::emplace_back(info, args...);
271  }
272 
273  iterator insert (const_iterator position, size_t n, const value_type& val) {
274  return gl_vector_internal::insert(info, position, n, val);
275  }
276 
277  template <typename U>
278  iterator insert (const_iterator position, U&& val) {
279  return gl_vector_internal::insert(info, position, std::forward<U>(val));
280  }
281 
282  template <class InputIterator>
283  iterator insert (const_iterator position, InputIterator first, InputIterator last,
284  _VEC_ENABLE_IF_ITERATOR(InputIterator, value_type) ) {
285  DASSERT_GE(std::distance(first, last), 0);
286  return gl_vector_internal::insert(info, position, first, last);
287  }
288 
289  iterator insert (const_iterator position, std::initializer_list<value_type> il) {
290  return gl_vector_internal::insert(info, position, il.begin(), il.end());
291  }
292 
293  gl_string& insert(size_t pos1, const gl_string& str) {
294  gl_vector_internal::insert(info, _iter_at(pos1), str.begin(), str.end());
295  return *this;
296  }
297 
298  gl_string& insert(size_t pos1, const gl_string& str,
299  size_t pos2, size_t n=npos) {
300  gl_vector_internal::insert(info, _iter_at(pos1), str._iter_at(pos2), str._iter_at(pos2, n));
301  return *this;
302  }
303 
304  gl_string& insert(size_t pos, const value_type* s, size_t n=npos) {
305  gl_vector_internal::insert(info, _iter_at(pos), s, s + ((n == npos) ? strlen(s) : n));
306  return *this;
307  }
308 
309  gl_string& insert(size_t pos, size_t n, value_type c) {
310  gl_vector_internal::insert(info, _iter_at(pos), n, c);
311  return *this;
312  }
313 
314  ////////////////////////////////////////////////////////////////////////////////
315  // Erasing
316 
317  void clear() _VEC_NDEBUG_NOEXCEPT {
318  gl_vector_internal::clear(info);
319  }
320 
321  void pop_back() {
322  gl_vector_internal::pop_back(info);
323  }
324 
325  iterator erase (const_iterator position) {
326  return gl_vector_internal::erase(info, position);
327  }
328 
329  iterator erase (const_iterator first, const_iterator last) {
330  return gl_vector_internal::erase(info, first, last);
331  }
332 
333  gl_string& erase(size_t pos = 0, size_t n = npos) {
334  gl_vector_internal::erase(info, _iter_at(pos), _iter_at(pos, n));
335  return *this;
336  }
337 
338  ////////////////////////////////////////////////////////////////////////////////
339  // Casting
340 
341  operator std::string() const {
342  return std::string(cbegin(), cend());
343  }
344 
345  ////////////////////////////////////////////////////////////////////////////////
346  // Data access / iterators
347 
348  const_iterator begin() const noexcept { return info == nullptr ? nullptr : info->data; }
349  iterator begin() noexcept { return info == nullptr ? nullptr : info->data; }
350 
351  const_reverse_iterator rbegin() const noexcept {
352  return std::reverse_iterator<const_iterator>(end());
353  }
354 
355  reverse_iterator rbegin() noexcept {
356  return std::reverse_iterator<iterator>(end());
357  }
358 
359  const_iterator end() const noexcept { return (info == nullptr) ? nullptr : (info->data + info->size); }
360  iterator end() noexcept { return (info == nullptr) ? nullptr : info->data + info->size; }
361 
362  reverse_iterator rend() noexcept { return std::reverse_iterator<iterator>(begin()); }
363  const_reverse_iterator rend() const noexcept { return std::reverse_iterator<const_iterator>(begin()); }
364 
365  const_iterator cbegin() const noexcept { return begin(); }
366 
367  const_reverse_iterator crbegin() const noexcept { return rbegin(); }
368 
369  const_iterator cend() const noexcept { return end(); }
370 
371  const_reverse_iterator crend() const noexcept { return rend(); }
372 
373  value_type* data() noexcept { return info == nullptr ? nullptr : info->data; }
374 
375  const value_type* data() const noexcept { return info == nullptr ? nullptr : info->data; }
376 
377 
378  ////////////////////////////////////////////////////////////////////////////////
379  // Swaps
380 
381  void swap (gl_string& x) _VEC_NDEBUG_NOEXCEPT {
382  std::swap(info, x.info);
383  }
384 
385  void swap (gl_string&& x) _VEC_NDEBUG_NOEXCEPT {
386  std::swap(info, x.info);
387  }
388 
389  ////////////////////////////////////////////////////////////////////////////////
390  // String specific methods.
391  ////////////////////////////////////////////////////////////////////////////////
392 
393  gl_string& append(const gl_string& str) {
394  gl_vector_internal::insert(info, end(), str.begin(), str.end());
395  return *this;
396  }
397 
398  gl_string& append(const gl_string& str, size_t pos, size_t n = npos) {
399  DASSERT_LE(pos, str.size());
400  gl_vector_internal::insert(info, end(), str._iter_at(pos), str._iter_at(pos, n));
401  return *this;
402  }
403 
404  gl_string& append(const char* s, size_t n) {
405  gl_vector_internal::insert(info, end(), s, s + n);
406  return *this;
407  }
408 
409  gl_string& append(const char* s) {
410  gl_vector_internal::insert(info, end(), s, s + std::strlen(s));
411  return *this;
412  }
413 
414  gl_string& append(size_t n, value_type c) {
415  gl_vector_internal::insert(info, end(), n, c);
416  return *this;
417  }
418 
419  template<class InputIterator>
420  gl_string& append(InputIterator first, InputIterator last,
421  _VEC_ENABLE_IF_ITERATOR(InputIterator, value_type)) {
422  gl_vector_internal::insert(info, end(), first, last);
423  return *this;
424  }
425 
426  gl_string& append(std::initializer_list<value_type> il) {
427  gl_vector_internal::insert(info, end(), il.begin(), il.end());
428  return *this;
429  }
430 
431  gl_string& operator+=(const gl_string& str) {
432  append(str);
433  return *this;
434  }
435 
436  gl_string& operator+=(const value_type* s) {
437  append(s);
438  return *this;
439  }
440 
441  gl_string& operator+=(value_type c) {
442  append(1, c);
443  return *this;
444  }
445 
446  gl_string& operator+=(std::initializer_list<value_type> il) {
447  append(il);
448  return *this;
449  }
450 
451  gl_string& replace(size_t pos1, size_t n1, const gl_string& str) {
452  gl_vector_internal::replace(info, _iter_at(pos1), _iter_at(pos1, n1), str.begin(), str.end());
453  return *this;
454  }
455 
456  gl_string& replace(size_t pos1, size_t n1, const gl_string& str,
457  size_t pos2, size_t n2=npos) {
458  gl_vector_internal::replace(info,
459  _iter_at(pos1), _iter_at(pos1, n1),
460  str._iter_at(pos2), str._iter_at(pos2, n2));
461  return *this;
462  }
463 
464  gl_string& replace(size_t pos, size_t n1, const value_type* s, size_t n2) {
465  gl_vector_internal::replace(info, _iter_at(pos), _iter_at(pos, n1), s, s + n2);
466  return *this;
467  }
468 
469  gl_string& replace(size_t pos, size_t n1, const value_type* s) {
470  gl_vector_internal::replace(info, _iter_at(pos), _iter_at(pos, n1), s, s + std::strlen(s));
471  return *this;
472  }
473 
474  gl_string& replace(size_t pos, size_t n1, size_t n2, value_type c) {
475  gl_vector_internal::replace(info, _iter_at(pos), _iter_at(pos, n1), n2, c);
476  return *this;
477  }
478 
479  gl_string& replace(const_iterator i1, const_iterator i2, const gl_string& str) {
480  gl_vector_internal::replace(info, i1, i2, str.begin(), str.end());
481  return *this;
482  }
483 
484  gl_string& replace(const_iterator i1, const_iterator i2, const value_type* s, size_t n) {
485  gl_vector_internal::replace(info, i1, i2, s, s + n);
486  return *this;
487  }
488 
489  gl_string& replace(const_iterator i1, const_iterator i2, const value_type* s) {
490  gl_vector_internal::replace(info, i1, i2, s, s + strlen(s));
491  return *this;
492  }
493 
494  gl_string& replace(const_iterator i1, const_iterator i2, size_t n, value_type c) {
495  gl_vector_internal::replace(info, i1, i2, n, c);
496  return *this;
497  }
498 
499  template<class InputIterator>
500  gl_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2) {
501  gl_vector_internal::replace(info, i1, i2, j1, j2);
502  return *this;
503  }
504 
505  gl_string& replace(const_iterator i1, const_iterator i2, std::initializer_list<value_type> il) {
506  gl_vector_internal::replace(info, i1, i2, il.begin(), il.end());
507  return *this;
508  }
509 
510  size_t copy(value_type* s, size_t n, size_t pos = 0) const _VEC_NDEBUG_NOEXCEPT {
511  DASSERT_LE(pos, size());
512  size_t sz = size();
513  size_t _end = std::min(sz, n + pos);
514  std::copy(cbegin() + pos, cbegin() + _end, s);
515  return _end - pos;
516  }
517 
518  gl_string substr(size_t pos = 0, size_t n = npos) const {
519  return gl_string(_iter_at(pos), _iter_at(pos, n));
520  }
521 
522  size_t find(const gl_string& str, size_t pos = 0) const _VEC_NDEBUG_NOEXCEPT {
523  return gl_string_internal::str_find(cbegin(), size(), str.cbegin(), pos, str.size());
524  }
525 
526  size_t find(const value_type* s, size_t pos, size_t n) const _VEC_NDEBUG_NOEXCEPT {
527  DASSERT_TRUE(n == 0 || s != nullptr);
528  return gl_string_internal::str_find(cbegin(), size(), s, pos, n);
529  }
530 
531  size_t find(const value_type* s, size_t pos = 0) const _VEC_NDEBUG_NOEXCEPT {
532  DASSERT_TRUE(s != nullptr);
533  return gl_string_internal::str_find(cbegin(), size(), s, pos, std::strlen(s));
534  }
535 
536  size_t find(value_type c, size_t pos = 0) const _VEC_NDEBUG_NOEXCEPT {
537  return gl_string_internal::str_find(cbegin(), size(), c, pos);
538  }
539 
540  size_t rfind(const gl_string& str, size_t pos = npos) const _VEC_NDEBUG_NOEXCEPT {
541  return gl_string_internal::str_rfind(cbegin(), size(), str.cbegin(), pos, str.size());
542  }
543 
544  size_t rfind(const value_type* s, size_t pos, size_t n) const _VEC_NDEBUG_NOEXCEPT {
545  DASSERT_TRUE(n == 0 || s != nullptr);
546  return gl_string_internal::str_rfind(cbegin(), size(), s, pos, n);
547  }
548 
549  size_t rfind(const value_type* s, size_t pos = npos) const _VEC_NDEBUG_NOEXCEPT {
550  DASSERT_TRUE(s != nullptr);
551  return gl_string_internal::str_rfind(cbegin(), size(), s, pos, std::strlen(s));
552  }
553 
554  size_t rfind(value_type c, size_t pos = npos) const _VEC_NDEBUG_NOEXCEPT {
555  return gl_string_internal::str_rfind(cbegin(), size(), c, pos);
556  }
557 
558  size_t find_first_of(const gl_string& str, size_t pos = 0) const _VEC_NDEBUG_NOEXCEPT {
559  return gl_string_internal::str_find_first_of(cbegin(), size(), str.cbegin(), pos, str.size());
560  }
561 
562  size_t find_first_of(const value_type* s, size_t pos, size_t n) const _VEC_NDEBUG_NOEXCEPT {
563  DASSERT_TRUE(n == 0 || s != nullptr);
564  return gl_string_internal::str_find_first_of(cbegin(), size(), s, pos, n);
565  }
566 
567  size_t find_first_of(const value_type* s, size_t pos = 0) const _VEC_NDEBUG_NOEXCEPT {
568  DASSERT_TRUE(s != nullptr);
569  return gl_string_internal::str_find_first_of(cbegin(), size(), s, pos, std::strlen(s));
570  }
571 
572  size_t find_first_of(value_type c, size_t pos = 0) const _VEC_NDEBUG_NOEXCEPT {
573  return find(c, pos);
574  }
575 
576  size_t find_last_of(const gl_string& str, size_t pos = npos) const _VEC_NDEBUG_NOEXCEPT {
577  return gl_string_internal::str_find_last_of(cbegin(), size(), str.cbegin(), pos, str.size());
578  }
579 
580  size_t find_last_of(const value_type* s, size_t pos, size_t n) const _VEC_NDEBUG_NOEXCEPT {
581  DASSERT_TRUE(n == 0 || s != nullptr);
582  return gl_string_internal::str_find_last_of(cbegin(), size(), s, pos, n);
583  }
584 
585  size_t find_last_of(const value_type* s, size_t pos = npos) const _VEC_NDEBUG_NOEXCEPT {
586  DASSERT_TRUE(s != nullptr);
587  return gl_string_internal::str_find_last_of(cbegin(), size(), s, pos, std::strlen(s));
588  }
589 
590  size_t find_last_of(value_type c, size_t pos = npos) const _VEC_NDEBUG_NOEXCEPT {
591  return rfind(c, pos);
592  }
593 
594  size_t find_first_not_of(const gl_string& str, size_t pos = 0) const _VEC_NDEBUG_NOEXCEPT {
595  return gl_string_internal::str_find_first_not_of(cbegin(), size(), str.cbegin(), pos, str.size());
596  }
597 
598  size_t find_first_not_of(const value_type* s, size_t pos, size_t n) const _VEC_NDEBUG_NOEXCEPT {
599  DASSERT_TRUE(n == 0 || s != nullptr);
600  return gl_string_internal::str_find_first_not_of(cbegin(), size(), s, pos, n);
601  }
602 
603  size_t find_first_not_of(const value_type* s, size_t pos = 0) const _VEC_NDEBUG_NOEXCEPT {
604  DASSERT_TRUE(s != nullptr);
605  return gl_string_internal::str_find_first_not_of(cbegin(), size(), s, pos, std::strlen(s));
606  }
607 
608  size_t find_first_not_of(value_type c, size_t pos = 0) const _VEC_NDEBUG_NOEXCEPT {
609  return gl_string_internal::str_find_first_not_of(cbegin(), size(), c, pos);
610  }
611 
612  size_t find_last_not_of(const gl_string& str, size_t pos = npos) const _VEC_NDEBUG_NOEXCEPT {
613  return gl_string_internal::str_find_last_not_of(cbegin(), size(), str.cbegin(), pos, str.size());
614  }
615 
616  size_t find_last_not_of(const value_type* s, size_t pos, size_t n) const _VEC_NDEBUG_NOEXCEPT {
617  DASSERT_TRUE(n == 0 || s != nullptr);
618  return gl_string_internal::str_find_last_not_of(cbegin(), size(), s, pos, n);
619  }
620 
621  size_t find_last_not_of(const value_type* s, size_t pos = npos) const _VEC_NDEBUG_NOEXCEPT {
622  DASSERT_TRUE(s != nullptr);
623  return gl_string_internal::str_find_last_not_of(cbegin(), size(), s, pos, std::strlen(s));
624  }
625 
626  size_t find_last_not_of(value_type c, size_t pos = npos) const _VEC_NDEBUG_NOEXCEPT {
627  return gl_string_internal::str_find_last_not_of(cbegin(), size(), c, pos);
628  }
629 
630  int compare(const gl_string& str) const _VEC_NDEBUG_NOEXCEPT {
631  size_t lhs_sz = size();
632  size_t rhs_sz = str.size();
633  int result = gl_string_internal::compare(data(), str.data(), std::min(lhs_sz, rhs_sz));
634  if (result != 0) return result;
635  if (lhs_sz < rhs_sz) return -1;
636  if (lhs_sz > rhs_sz) return 1;
637  return 0;
638  }
639 
640  int compare(const std::string& str) const _VEC_NDEBUG_NOEXCEPT {
641  size_t lhs_sz = size();
642  size_t rhs_sz = str.size();
643  int result = gl_string_internal::compare(data(), str.data(), std::min(lhs_sz, rhs_sz));
644  if (result != 0) return result;
645  if (lhs_sz < rhs_sz) return -1;
646  if (lhs_sz > rhs_sz) return 1;
647  return 0;
648  }
649 
650  int compare(size_t pos1, size_t n1, const gl_string& str) const _VEC_NDEBUG_NOEXCEPT {
651  return compare(pos1, n1, str.cbegin(), str.size());
652  }
653 
654  int compare(size_t pos1, size_t n1, const gl_string& str,
655  size_t pos2, size_t n2=npos) const _VEC_NDEBUG_NOEXCEPT {
656 
657  size_type sz = str.size();
658  DASSERT_LE(pos2, sz);
659  return compare(pos1, n1, str.data() + pos2, std::min(n2, sz - pos2));
660  }
661 
662  int compare(const value_type* s) const _VEC_NDEBUG_NOEXCEPT {
663  DASSERT_TRUE(s != nullptr);
664  return compare(0, npos, s, std::strlen(s));
665  }
666 
667  int compare(size_t pos1, size_t n1, const value_type* s) const _VEC_NDEBUG_NOEXCEPT {
668  DASSERT_TRUE(s != nullptr);
669  return compare(pos1, n1, s, std::strlen(s));
670  }
671 
672  int compare(size_t pos1, size_t n1, const value_type* s, size_t n2) const _VEC_NDEBUG_NOEXCEPT {
673  DASSERT_TRUE(n2 == 0 || s != nullptr);
674  size_type sz = size();
675  DASSERT_LE(pos1, sz);
676  DASSERT_FALSE(n2 == npos);
677  size_type rlen = std::min(n1, sz - pos1);
678  int r = gl_string_internal::compare(data() + pos1, s, std::min(rlen, n2));
679  if (r == 0) {
680  if (rlen < n2) r = -1;
681  else if (rlen > n2) r = 1;
682  }
683  return r;
684  }
685 
686  ////////////////////////////////////////////////////////////////////////////////
687 
688  private:
689 
690  const_iterator _iter_at(size_t pos) const _VEC_NDEBUG_NOEXCEPT {
691  DASSERT_LE(pos, size());
692  return cbegin() + pos;
693  }
694 
695  const_iterator _iter_at(size_t pos, size_t n) const _VEC_NDEBUG_NOEXCEPT {
696  DASSERT_LE(pos, size());
697  return n == npos ? cend() : cbegin() + std::min(size(), pos + n);
698  }
699 
700  iterator _iter_at(size_t pos) _VEC_NDEBUG_NOEXCEPT {
701  DASSERT_LE(pos, size());
702  return begin() + pos;
703  }
704 
705  iterator _iter_at(size_t pos, size_t n) _VEC_NDEBUG_NOEXCEPT {
706  DASSERT_LE(pos, size());
707  return n == npos ? end() : begin() + std::min(size(), pos + n);
708  }
709 };
710 
711 ////////////////////////////////////////////////////////////////////////////////
712 // operator overloads
713 
714 // operator==
715 GL_HOT_INLINE_FLATTEN static inline
716 bool operator==(const gl_string& lhs, const gl_string& rhs) noexcept {
717  return (lhs.size() == rhs.size()
718  && std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()));
719 }
720 
721 
722 GL_HOT_INLINE_FLATTEN static inline
723 bool operator==(const char* lhs, const gl_string& rhs) noexcept {
724  return (std::strlen(lhs) == rhs.size()
725  && std::equal(rhs.cbegin(), rhs.cend(), lhs));
726 }
727 
728 GL_HOT_INLINE_FLATTEN static inline
729 bool operator==(const gl_string& lhs, const char* rhs) noexcept {
730  return (std::strlen(rhs) == lhs.size()
731  && std::equal(lhs.cbegin(), lhs.cend(), rhs));
732 }
733 
734 GL_HOT_INLINE_FLATTEN static inline
735 bool operator==(const gl_string& lhs, const std::string& rhs) noexcept {
736  return (lhs.size() == rhs.size()
737  && std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()));
738 }
739 
740 GL_HOT_INLINE_FLATTEN static inline
741 bool operator==(const std::string& lhs, const gl_string& rhs) noexcept {
742  return (lhs.size() == rhs.size()
743  && std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()));
744 }
745 
746 
747 // operator!=
748 GL_HOT_INLINE_FLATTEN static inline
749 bool operator!=(const gl_string& lhs, const gl_string& rhs) noexcept {
750  return !(lhs == rhs);
751 }
752 
753 
754 GL_HOT_INLINE_FLATTEN static inline
755 bool operator!=(const char* lhs, const gl_string& rhs) noexcept {
756  return !(lhs == rhs);
757 }
758 
759 
760 GL_HOT_INLINE_FLATTEN static inline bool
761 operator!=(const gl_string& lhs, const char* rhs) noexcept {
762  return !(lhs == rhs);
763 }
764 
765 // operator!=
766 GL_HOT_INLINE_FLATTEN static inline
767 bool operator!=(const std::string& lhs, const gl_string& rhs) noexcept {
768  return !(lhs == rhs);
769 }
770 
771 // operator!=
772 GL_HOT_INLINE_FLATTEN static inline
773 bool operator!=(const gl_string& lhs, const std::string& rhs) noexcept {
774  return !(lhs == rhs);
775 }
776 
777 
778 // operator<
779 GL_HOT_INLINE_FLATTEN static inline
780 bool operator< (const gl_string& lhs, const gl_string& rhs) noexcept {
781  return lhs.compare(rhs) < 0;
782 }
783 
784 // operator<
785 GL_HOT_INLINE_FLATTEN static inline
786 bool operator< (const gl_string& lhs, const std::string& rhs) noexcept {
787  return lhs.compare(rhs) < 0;
788 }
789 
790 // operator<
791 GL_HOT_INLINE_FLATTEN static inline
792 bool operator< (const std::string& lhs, const gl_string& rhs) noexcept {
793  return rhs.compare(lhs) > 0;
794 }
795 
796 GL_HOT_INLINE_FLATTEN static inline
797 bool operator< (const gl_string& lhs, const char* rhs) noexcept {
798  return lhs.compare(rhs) < 0;
799 }
800 
801 
802 GL_HOT_INLINE_FLATTEN static inline
803 bool operator< (const char* lhs, const gl_string& rhs) noexcept {
804  return rhs.compare(lhs) > 0;
805 }
806 
807 // operator>
808 
809 
810 GL_HOT_INLINE_FLATTEN static inline
811 bool operator> (const gl_string& lhs, const gl_string& rhs) noexcept {
812  return rhs < lhs;
813 }
814 
815 
816 GL_HOT_INLINE_FLATTEN static inline
817 bool operator> (const gl_string& lhs, const std::string& rhs) noexcept {
818  return rhs < lhs;
819 }
820 
821 
822 GL_HOT_INLINE_FLATTEN static inline
823 bool operator> (const std::string& lhs, const gl_string& rhs) noexcept {
824  return rhs < lhs;
825 }
826 
827 GL_HOT_INLINE_FLATTEN static inline
828 bool operator> (const gl_string& lhs, const char* rhs) noexcept {
829  return rhs < lhs;
830 }
831 
832 
833 GL_HOT_INLINE_FLATTEN static inline
834 bool operator> (const char* lhs, const gl_string& rhs) noexcept {
835  return rhs < lhs;
836 }
837 
838 // operator<=
839 
840 
841 GL_HOT_INLINE_FLATTEN static inline
842 bool operator<=(const gl_string& lhs, const gl_string& rhs) noexcept {
843  return !(rhs < lhs);
844 }
845 
846 GL_HOT_INLINE_FLATTEN static inline
847 bool operator<=(const gl_string& lhs, const std::string& rhs) noexcept {
848  return !(rhs < lhs);
849 }
850 
851 GL_HOT_INLINE_FLATTEN static inline
852 bool operator<=(const std::string& lhs, const gl_string& rhs) noexcept {
853  return !(rhs < lhs);
854 }
855 
856 
857 GL_HOT_INLINE_FLATTEN static inline
858 bool operator<=(const gl_string& lhs, const char* rhs) noexcept {
859  return !(rhs < lhs);
860 }
861 
862 
863 GL_HOT_INLINE_FLATTEN static inline
864 bool operator<=(const char* lhs, const gl_string& rhs) noexcept {
865  return !(rhs < lhs);
866 }
867 
868 // operator>=
869 GL_HOT_INLINE_FLATTEN static inline
870 bool operator>=(const gl_string& lhs, const gl_string& rhs) noexcept {
871  return !(lhs < rhs);
872 }
873 
874 
875 GL_HOT_INLINE_FLATTEN static inline
876 bool operator>=(const gl_string& lhs, const std::string& rhs) noexcept {
877  return !(lhs < rhs);
878 }
879 
880 
881 GL_HOT_INLINE_FLATTEN static inline
882 bool operator>=(const std::string& lhs, const gl_string& rhs) noexcept {
883  return !(lhs < rhs);
884 }
885 
886 GL_HOT_INLINE_FLATTEN static inline
887 bool operator>=(const gl_string& lhs, const char* rhs) noexcept {
888  return !(lhs < rhs);
889 }
890 
891 
892 GL_HOT_INLINE_FLATTEN static inline
893 bool operator>=(const char* lhs, const gl_string& rhs) noexcept {
894  return !(lhs < rhs);
895 }
896 
897 // operator +
898 GL_HOT_INLINE_FLATTEN static inline
899 gl_string operator+(const gl_string& lhs, const gl_string& rhs) {
900  size_t lhs_sz = lhs.size();
901  size_t rhs_sz = rhs.size();
902  gl_string r;
903  r.reserve(lhs_sz + rhs_sz);
904  r.assign(lhs.data(), lhs_sz);
905  r.append(rhs.data(), rhs_sz);
906  return r;
907 }
908 
909 // operator +
910 GL_HOT_INLINE_FLATTEN static inline
911 gl_string operator+(const gl_string& lhs, const std::string& rhs) {
912  size_t lhs_sz = lhs.size();
913  size_t rhs_sz = rhs.size();
914  gl_string r;
915  r.reserve(lhs_sz + rhs_sz);
916  r.assign(lhs.data(), lhs_sz);
917  r.append(rhs.data(), rhs_sz);
918  return r;
919 }
920 
921 // operator +
922 GL_HOT_INLINE_FLATTEN static inline
923 gl_string operator+(const std::string& lhs, const gl_string& rhs) {
924  size_t lhs_sz = lhs.size();
925  size_t rhs_sz = rhs.size();
926  gl_string r;
927  r.reserve(lhs_sz + rhs_sz);
928  r.assign(lhs.data(), lhs_sz);
929  r.append(rhs.data(), rhs_sz);
930  return r;
931 }
932 
933 
934 GL_HOT_INLINE_FLATTEN static inline
935 gl_string operator+(const char* lhs , const gl_string& rhs) {
936  size_t lhs_sz = std::strlen(lhs);
937  size_t rhs_sz = rhs.size();
938  gl_string r;
939  r.reserve(lhs_sz + rhs_sz);
940  r.assign(lhs, lhs + lhs_sz);
941  r.append(rhs.data(), rhs_sz);
942  return r;
943 }
944 
945 
946 GL_HOT_INLINE_FLATTEN static inline
947 gl_string operator+(char lhs, const gl_string& rhs) {
948  size_t rhs_sz = rhs.size();
949  gl_string r;
950  r.reserve(1 + rhs_sz);
951  r.assign(1, lhs);
952  r.append(rhs.data(), rhs_sz);
953  return r;
954 }
955 
956 
957 GL_HOT_INLINE_FLATTEN static inline
958 gl_string operator+(const gl_string& lhs, const char* rhs) {
959  size_t lhs_sz = lhs.size();
960  size_t rhs_sz = std::strlen(rhs);
961  gl_string r;
962  r.reserve(lhs_sz + rhs_sz);
963  r.assign(lhs.data(), lhs_sz);
964  r.append(rhs, rhs_sz);
965  return r;
966 }
967 
968 GL_HOT_INLINE_FLATTEN static inline
969 gl_string operator+(const gl_string& lhs, char rhs) {
970  size_t lhs_sz = lhs.size();
971  gl_string r;
972  r.reserve(lhs_sz + 1);
973  r.assign(lhs.data(), lhs_sz);
974  r.push_back(rhs);
975  return r;
976 }
977 
978 GL_HOT_INLINE_FLATTEN static inline
979 gl_string operator+(gl_string&& lhs, const gl_string& rhs) {
980  return std::move(lhs.append(rhs));
981 }
982 
983 
984 GL_HOT_INLINE_FLATTEN static inline
985 gl_string operator+(const gl_string& lhs, gl_string&& rhs) {
986  return std::move(rhs.insert(0, lhs));
987 }
988 
989 
990 GL_HOT_INLINE_FLATTEN static inline
991 gl_string operator+(gl_string&& lhs, gl_string&& rhs) {
992  return std::move(lhs.append(rhs));
993 }
994 
995 
996 GL_HOT_INLINE_FLATTEN static inline
997 gl_string operator+(const char* lhs , gl_string&& rhs) {
998  return std::move(rhs.insert(0, lhs));
999 }
1000 
1001 
1002 GL_HOT_INLINE_FLATTEN static inline
1003 gl_string operator+(char lhs, gl_string&& rhs) {
1004  rhs.insert(rhs.begin(), lhs);
1005  return std::move(rhs);
1006 }
1007 
1008 GL_HOT_INLINE_FLATTEN static inline
1009 gl_string operator+(gl_string&& lhs, const char* rhs) {
1010  return std::move(lhs.append(rhs));
1011 }
1012 
1013 GL_HOT_INLINE_FLATTEN static inline
1014 gl_string operator+(gl_string&& lhs, char rhs) {
1015  lhs.push_back(rhs);
1016  return std::move(lhs);
1017 }
1018 } // End namespace turi
1019 
1020 ////////////////////////////////////////////////////////////////////////////////
1021 // Conversion routines to gl_strings
1022 
1023 #include <core/generics/string_conversion_internals.hpp>
1024 
1025 namespace turi {
1026 
1027 static inline gl_string to_gl_string(int val) {
1028  return gl_string_internal::as_string("%d", val);
1029 }
1030 
1031 static inline gl_string to_gl_string(unsigned val) {
1032  return gl_string_internal::as_string("%u", val);
1033 }
1034 
1035 static inline gl_string to_gl_string(long val) {
1036  return gl_string_internal::as_string("%ld", val);
1037 }
1038 
1039 static inline gl_string to_gl_string(unsigned long val) {
1040  return gl_string_internal::as_string("%lu", val);
1041 }
1042 
1043 static inline gl_string to_gl_string(long long val) {
1044  return gl_string_internal::as_string("%lld", val);
1045 }
1046 
1047 static inline gl_string to_gl_string(unsigned long long val) {
1048  return gl_string_internal::as_string("%llu", val);
1049 }
1050 
1051 static inline gl_string to_gl_string(float val) {
1052  return gl_string_internal::as_string("%f", val);
1053 }
1054 
1055 static inline gl_string to_gl_string(double val) {
1056  return gl_string_internal::as_string("%f", val);
1057 }
1058 
1059 static inline gl_string to_gl_string(long double val) {
1060  return gl_string_internal::as_string("%Lf", val);
1061 }
1062 
1063 ////////////////////////////////////////////////////////////////////////////////
1064 }
1065 
1066 #include <core/generics/string_stream_internals.hpp>
1067 
1068 namespace turi {
1069 
1070 template<class _Traits>
1071 static inline
1072 std::basic_ostream<char, _Traits>& operator<<(std::basic_ostream<char, _Traits>& os, const gl_string& s) {
1073  for(auto it = s.begin(); it != s.end(); ++it) {
1074  os << *it;
1075  }
1076  return os;
1077 }
1078 
1079 template<class _Traits>
1080 std::basic_istream<char, _Traits>&
1081 operator>>(std::basic_istream<char, _Traits>& is, gl_string& str) {
1082  return gl_string_internals::stream_in(is, str);
1083 }
1084 
1085 }
1086 
1087 ////////////////////////////////////////////////////////////////////////////////
1088 // Overloads of operators for standard std string operations
1089 
1090 namespace std {
1091 
1092 static inline
1093 std::istream& getline(std::istream& is, turi::gl_string& str, char dlm='\n') {
1094  return turi::gl_string_internals::getline(is, str, dlm);
1095 }
1096 
1097 static inline
1098 std::istream& getline(std::istream&& is, turi::gl_string& str, char dlm='\n') {
1099  return turi::gl_string_internals::getline(is, str, dlm);
1100 }
1101 
1102 static inline int stoi(const turi::gl_string& str, size_t* idx = 0, int base = 10) {
1103  return std::stoi(std::string(str.begin(), str.end()), idx, base);
1104 }
1105 
1106 static inline long stol(const turi::gl_string& str, size_t* idx = 0, int base = 10) {
1107  return std::stol(std::string(str.begin(), str.end()), idx, base);
1108 }
1109 
1110 static inline unsigned long stoul (const turi::gl_string& str, size_t* idx = 0, int base = 10) {
1111  return std::stoul(std::string(str.begin(), str.end()), idx, base);
1112 }
1113 
1114 static inline unsigned long long stoull(const turi::gl_string& str, size_t* idx = 0, int base = 10) {
1115  return std::stoull(std::string(str.begin(), str.end()), idx, base);
1116 }
1117 
1118 static inline float stof (const turi::gl_string& str, size_t* idx = 0) {
1119  return std::stoll(std::string(str.begin(), str.end()), idx);
1120 }
1121 
1122 static inline double stod (const turi::gl_string& str, size_t* idx = 0) {
1123  return std::stod(std::string(str.begin(), str.end()), idx);
1124 }
1125 
1126 static inline long double stold(const turi::gl_string& str, size_t* idx = 0) {
1127  return std::stold(std::string(str.begin(), str.end()), idx);
1128 }
1129 
1130 static inline void swap (turi::gl_string& a, turi::gl_string& b) noexcept {
1131  a.swap(b);
1132 }
1133 
1134 template <> struct hash<turi::gl_string>
1135  : public unary_function<turi::gl_string, size_t> {
1136 
1137  size_t operator()(const turi::gl_string& s) const {
1138  return turi::hash64(s.data(), s.size());
1139  }
1140 };
1141 
1142 }
1143 
1144 // is memmovable
1145 namespace turi {
1146 
1147 template <>
1148 struct is_memmovable<gl_string> {
1149  static constexpr bool value = true;
1150 };
1151 
1152 }
1153 
1154 #include <core/generics/string_serialization.hpp>
1155 
1156 #endif
STL namespace.
static uint64_t hash64(const char *s, size_t len)
void copy(const std::string src, const std::string dest)
#define DASSERT_FALSE(cond)
Definition: assertions.hpp:365
#define GL_HOT_INLINE_FLATTEN
void copy(Iterator begin, Iterator end, SWriter &&writer)
Definition: algorithm.hpp:416
#define DASSERT_TRUE(cond)
Definition: assertions.hpp:364
size_t size() const