string 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. #ifndef __GBLIBCPP_STRING__
  2. #define __GBLIBCPP_STRING__
  3. #include <bits/compressed_pair>
  4. #include <bits/iter_ops>
  5. #include <algorithm>
  6. #include <functional>
  7. #include <memory>
  8. #include <initializer_list>
  9. #include <cstddef>
  10. #include <string.h>
  11. namespace std {
  12. template <typename T>
  13. class char_traits;
  14. template <>
  15. class char_traits<char>
  16. {
  17. public:
  18. static std::size_t length(const char* str) { return strlen(str); }
  19. static int compare(const char* s1, const char* s2, std::size_t cnt)
  20. {
  21. return strncmp(s1, s2, cnt);
  22. }
  23. };
  24. template <typename Char,
  25. typename Traits = std::char_traits<Char>,
  26. typename Allocator = std::allocator<Char>>
  27. class basic_string {
  28. public:
  29. using traits_type = Traits;
  30. using value_type = Char;
  31. using allocator_type = Allocator;
  32. using size_type = typename std::allocator_traits<Allocator>::size_type;
  33. using difference_type = typename std::allocator_traits<Allocator>::difference_type;
  34. using reference = value_type&;
  35. using const_reference = const value_type&;
  36. using pointer = typename std::allocator_traits<Allocator>::pointer;
  37. using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
  38. template <bool Const>
  39. class _iterator {
  40. public:
  41. // TODO:
  42. // using iterator_category = std::random_access_iterator_tag;
  43. using _reference = std::conditional_t<Const, const_reference, reference>;
  44. private:
  45. pointer m_ptr;
  46. public:
  47. constexpr _iterator(void) noexcept : m_ptr() {}
  48. constexpr explicit _iterator(pointer ptr) noexcept
  49. : m_ptr(ptr) {}
  50. constexpr _iterator(const _iterator& other) noexcept = default;
  51. constexpr _iterator(_iterator&& other) noexcept = default;
  52. constexpr _iterator& operator=(const _iterator& other) noexcept = default;
  53. constexpr _iterator& operator=(_iterator&& other) noexcept = default;
  54. constexpr bool operator==(const _iterator& other) const noexcept = default;
  55. constexpr _reference operator*() const noexcept { return *m_ptr; }
  56. constexpr pointer operator&() const noexcept
  57. { return std::addressof(this->operator*()); }
  58. constexpr pointer operator->() const noexcept
  59. { return this->operator&(); }
  60. constexpr _iterator& operator++() noexcept
  61. { ++m_ptr; return *this; }
  62. constexpr _iterator operator++(int) noexcept
  63. { _iterator ret(m_ptr); (void)this->operator++(); return ret; }
  64. constexpr _iterator& operator--(void) noexcept
  65. { --m_ptr; return *this; }
  66. constexpr _iterator operator--(int) noexcept
  67. { _iterator ret(m_ptr); (void)this->operator--(); return ret; }
  68. constexpr _iterator& operator+=(difference_type n) noexcept
  69. { m_ptr += n; return *this; }
  70. constexpr _iterator& operator-=(difference_type n) noexcept
  71. { m_ptr -= n; return *this; }
  72. constexpr _iterator operator+(difference_type n) const noexcept
  73. { return _iterator { m_ptr + n }; }
  74. constexpr _iterator operator-(difference_type n) const noexcept
  75. { return _iterator { m_ptr - n }; }
  76. constexpr difference_type operator-(const _iterator& other) const noexcept
  77. { return m_ptr - other.m_ptr; }
  78. constexpr _reference operator[](difference_type n) const noexcept
  79. { return m_ptr[n]; }
  80. constexpr operator bool() { return m_ptr; }
  81. constexpr operator _iterator<true>() { return _iterator<true> { m_ptr }; }
  82. constexpr operator _iterator<false>() { return _iterator<false> { m_ptr }; }
  83. constexpr operator pointer() { return m_ptr; }
  84. };
  85. private:
  86. using alloc_traits = std::allocator_traits<Allocator>;
  87. public:
  88. using iterator = _iterator<false>;
  89. using const_iterator = _iterator<true>;
  90. private:
  91. static constexpr std::size_t STATIC_SIZE = 32;
  92. static constexpr std::size_t STATIC_COUNT =
  93. STATIC_SIZE / sizeof(Char) - 2;
  94. struct string_data_type { union {
  95. std::byte __data[STATIC_SIZE];
  96. struct {
  97. union {
  98. Char __data;
  99. unsigned char n;
  100. } m_size;
  101. Char str[STATIC_COUNT];
  102. Char end;
  103. } stackdata;
  104. struct {
  105. std::size_t m_size;
  106. std::size_t m_capacity;
  107. Char* m_ptr;
  108. } heapdata;
  109. } in; };
  110. impl::compressed_pair<string_data_type, Allocator> m_data;
  111. constexpr Allocator& _alloc() noexcept { return m_data.second(); }
  112. constexpr const Allocator& _alloc() const noexcept { return m_data.second(); }
  113. constexpr bool _stack_data() const
  114. {
  115. return m_data.first().in.stackdata.end == 0;
  116. }
  117. constexpr bool _stack_data(bool val)
  118. {
  119. return (m_data.first().in.stackdata.end = !val), val;
  120. }
  121. constexpr void _release()
  122. {
  123. if (_stack_data()) {
  124. _size(0);
  125. return;
  126. }
  127. alloc_traits::deallocate(m_data.second(), data(), capacity()+1);
  128. _stack_data(true);
  129. _size(0);
  130. _data()[0] = 0;
  131. }
  132. constexpr void _reserve(std::size_t cnt)
  133. {
  134. std::size_t cursize = size();
  135. Char* newdata = alloc_traits::allocate(_alloc(), cnt+1);
  136. memcpy(newdata, data(), size());
  137. newdata[cursize] = 0;
  138. if (_stack_data()) {
  139. _stack_data(false);
  140. _size(cursize);
  141. }
  142. else {
  143. alloc_traits::deallocate(_alloc(), data(), capacity()+1);
  144. }
  145. _capacity(cnt);
  146. _data(newdata);
  147. }
  148. constexpr std::size_t _size() const
  149. {
  150. if (_stack_data())
  151. return m_data.first().in.stackdata.m_size.n;
  152. else
  153. return m_data.first().in.heapdata.m_size;
  154. }
  155. constexpr std::size_t _size(std::size_t val)
  156. {
  157. if (_stack_data())
  158. return m_data.first().in.stackdata.m_size.n = (Char)val;
  159. else
  160. return m_data.first().in.heapdata.m_size = val;
  161. }
  162. constexpr std::size_t _capacity() const
  163. {
  164. if (_stack_data())
  165. return STATIC_COUNT;
  166. else
  167. return m_data.first().in.heapdata.m_capacity;
  168. }
  169. constexpr std::size_t _capacity(std::size_t val)
  170. {
  171. if (_stack_data())
  172. return STATIC_COUNT;
  173. else
  174. return m_data.first().in.heapdata.m_capacity = val;
  175. }
  176. constexpr const Char* _data() const
  177. {
  178. if (_stack_data())
  179. return m_data.first().in.stackdata.str;
  180. else
  181. return m_data.first().in.heapdata.m_ptr;
  182. }
  183. constexpr Char* _data()
  184. {
  185. if (_stack_data())
  186. return m_data.first().in.stackdata.str;
  187. else
  188. return m_data.first().in.heapdata.m_ptr;
  189. }
  190. constexpr Char* _data(Char* val)
  191. {
  192. if (_stack_data())
  193. return m_data.first().in.stackdata.str;
  194. else
  195. return m_data.first().in.heapdata.m_ptr = val;
  196. }
  197. public:
  198. constexpr basic_string() noexcept(noexcept(Allocator()))
  199. : basic_string{Allocator{}} { }
  200. constexpr explicit basic_string(const Allocator& alloc) noexcept
  201. : m_data{{}, alloc} { }
  202. constexpr basic_string(const basic_string& other, const Allocator& alloc)
  203. : basic_string{alloc}
  204. {
  205. append(other.c_str(), other.size());
  206. }
  207. constexpr basic_string(const basic_string& other)
  208. : basic_string{other, alloc_traits::
  209. select_on_container_copy_construction(other._alloc())} { }
  210. constexpr basic_string(basic_string&& other) noexcept
  211. : m_data{other.m_data.first(), std::move(other._alloc())}
  212. {
  213. other._stack_data(true);
  214. other._size(0);
  215. other._data()[0] = 0;
  216. }
  217. constexpr basic_string(basic_string&& other, const Allocator& alloc)
  218. : basic_string{alloc}
  219. {
  220. if (alloc == other._alloc()) {
  221. m_data.first() = other.m_data.first();
  222. other._stack_data(true);
  223. other._size(0);
  224. other._data()[0] = 0;
  225. }
  226. else {
  227. append(other.c_str(), other.size());
  228. }
  229. }
  230. constexpr basic_string(const basic_string& other, size_type pos,
  231. const Allocator& alloc = Allocator{})
  232. : basic_string{other.c_str() + pos, alloc} { }
  233. // constexpr basic_string(std::initializer_list<Char> ilist,
  234. // const Allocator& alloc = Allocator{})
  235. // : basic_string {alloc}
  236. // {
  237. // assign(ilist.begin(), ilist.end());
  238. // }
  239. constexpr basic_string(const Char* str, size_type count,
  240. const Allocator& alloc = Allocator{})
  241. : basic_string{alloc}
  242. {
  243. assign(str, count);
  244. }
  245. constexpr basic_string(const Char* str, const Allocator& alloc = Allocator{})
  246. : basic_string{str, traits_type::length(str), alloc} { }
  247. constexpr ~basic_string()
  248. {
  249. _release();
  250. }
  251. constexpr basic_string& operator=(const Char* str)
  252. {
  253. return assign(str);
  254. }
  255. constexpr basic_string& operator=(const basic_string& other)
  256. {
  257. return assign(other.c_str(), other.size());
  258. }
  259. constexpr basic_string& operator=(basic_string&& other)
  260. {
  261. if constexpr (alloc_traits::
  262. propagate_on_container_move_assignment::value) {
  263. _release();
  264. _alloc() = std::move(other._alloc());
  265. }
  266. else {
  267. if (_alloc() != other._alloc()) {
  268. assign(other.c_str(), other.size());
  269. return *this;
  270. }
  271. _release();
  272. }
  273. m_data.first() = other.m_data.first();
  274. other._stack_data(true);
  275. other._size(0);
  276. other._data()[0] = 0;
  277. return *this;
  278. }
  279. constexpr basic_string& operator=(Char ch)
  280. {
  281. return assign(1, ch);
  282. }
  283. // constexpr basic_string& operator=(std::initializer_list<Char> init)
  284. // {
  285. // assign(init.begin(), init.end());
  286. // return *this;
  287. // }
  288. constexpr basic_string& append(std::size_t len, Char ch)
  289. {
  290. std::size_t cursize = size();
  291. std::size_t newsize = cursize + len;
  292. if (newsize > capacity())
  293. _reserve(std::max(capacity() * 2, newsize));
  294. auto* pdata = data();
  295. for (std::size_t i = cursize; i < newsize; ++i)
  296. pdata[i] = ch;
  297. pdata[newsize] = 0;
  298. _size(newsize);
  299. return *this;
  300. }
  301. constexpr basic_string& append(const Char* str, std::size_t count)
  302. {
  303. std::size_t cursize = size();
  304. std::size_t newsize = cursize + count;
  305. if (newsize > capacity())
  306. _reserve(std::max(capacity() * 2, newsize));
  307. memcpy(data() + cursize, str, count);
  308. data()[newsize] = 0;
  309. _size(newsize);
  310. return *this;
  311. }
  312. constexpr basic_string& append(const Char* str)
  313. {
  314. return append(str, traits_type::length(str));
  315. }
  316. constexpr basic_string& assign(size_type n, Char ch)
  317. {
  318. clear();
  319. return append(n, ch);
  320. }
  321. constexpr basic_string& assign(const Char* str, size_type count)
  322. {
  323. clear();
  324. return append(str, count);
  325. }
  326. constexpr basic_string& assign(const Char* str)
  327. {
  328. return assign(str, traits_type::length(str));
  329. }
  330. // TODO: check whether InputIter satisfies LegacyInputIterator
  331. // template <typename InputIter>
  332. // constexpr basic_string& assign(InputIter first, InputIter last)
  333. // {
  334. // clear();
  335. // insert(cbegin(), first, last);
  336. // return *this;
  337. // }
  338. // constexpr basic_string& assign(std::initializer_list<T> init)
  339. // {
  340. // clear();
  341. // insert(cbegin(), init.begin(), init.end());
  342. // return *this;
  343. // }
  344. constexpr basic_string& operator+=(Char ch)
  345. {
  346. return append(1, ch);
  347. }
  348. constexpr basic_string& operator+=(const Char* str)
  349. {
  350. return append(str);
  351. }
  352. constexpr basic_string& operator+=(const basic_string& str)
  353. {
  354. return append(str.c_str(), str.size());
  355. }
  356. constexpr bool empty() const noexcept
  357. { return size() == 0; }
  358. constexpr size_type size() const noexcept
  359. { return _size(); }
  360. constexpr size_type capacity() const noexcept
  361. { return _capacity(); }
  362. constexpr Char* data() noexcept { return _data(); }
  363. constexpr const Char* data() const noexcept { return _data(); }
  364. constexpr const Char* c_str() const noexcept { return data(); }
  365. constexpr reference operator[](size_type pos)
  366. { return data()[pos]; }
  367. constexpr const_reference operator[](size_type pos) const
  368. { return data()[pos]; }
  369. // constexpr reference at(size_type pos)
  370. // {
  371. // // TODO: exceptions
  372. // // if (pos >= size())
  373. // // throw std::out_of_range("basic_string::at");
  374. // return operator[](pos);
  375. // }
  376. // constexpr const_reference at(size_type pos) const
  377. // {
  378. // // TODO: exceptions
  379. // // if (pos >= size())
  380. // // throw std::out_of_range("basic_string::at");
  381. // return operator[](pos);
  382. // }
  383. constexpr reference front() noexcept
  384. { return operator[](0); }
  385. constexpr const_reference front() const noexcept
  386. { return operator[](0); }
  387. constexpr reference back() noexcept
  388. { return operator[](size() - 1); }
  389. constexpr const_reference back() const noexcept
  390. { return operator[](size() - 1); }
  391. // TODO: std::reverse_iterator
  392. constexpr iterator begin() noexcept
  393. { return iterator { data() }; }
  394. constexpr const_iterator begin() const noexcept
  395. { return const_iterator { data() }; }
  396. constexpr const_iterator cbegin() const noexcept
  397. { return const_iterator { data() }; }
  398. constexpr iterator end() noexcept
  399. { return iterator { data() + size() }; }
  400. constexpr const_iterator end() const noexcept
  401. { return const_iterator { data() + size() }; }
  402. constexpr const_iterator cend() const noexcept
  403. { return const_iterator { data() + size() }; }
  404. constexpr void clear() noexcept{ _size(0); }
  405. constexpr void push_back(Char ch) { append(1, ch); }
  406. constexpr void pop_back() { erase(cend()-1); }
  407. constexpr void swap(basic_string& other) noexcept(
  408. alloc_traits::propagate_on_container_swap::value
  409. || alloc_traits::is_always_equal::value)
  410. {
  411. if (alloc_traits::propagate_on_container_swap::value)
  412. std::swap(_alloc(), other._alloc());
  413. std::swap(m_data.first(), other.m_data.first());
  414. }
  415. constexpr int compare(const basic_string& str) const noexcept
  416. {
  417. return traits_type::compare(c_str(), str.c_str(), size()+1);
  418. }
  419. constexpr int compare(const Char* str) const
  420. {
  421. return traits_type::compare(c_str(), str, size()+1);
  422. }
  423. };
  424. template <typename Char, typename Traits, typename Allocator>
  425. constexpr bool operator==(
  426. const std::basic_string<Char, Traits, Allocator>& lhs,
  427. const std::basic_string<Char, Traits, Allocator>& rhs) noexcept
  428. {
  429. return lhs.compare(rhs) == 0;
  430. }
  431. template <typename Char, typename Traits, typename Allocator>
  432. constexpr bool operator==(
  433. const std::basic_string<Char, Traits, Allocator>& lhs, const Char* rhs)
  434. {
  435. return lhs.compare(rhs) == 0;
  436. }
  437. template <typename Char, typename Traits, typename Allocator>
  438. constexpr bool operator<(
  439. const std::basic_string<Char, Traits, Allocator>& lhs,
  440. const std::basic_string<Char, Traits, Allocator>& rhs) noexcept
  441. {
  442. return lhs.compare(rhs) < 0;
  443. }
  444. template <typename Char, typename Traits, typename Allocator>
  445. constexpr void swap(
  446. std::basic_string<Char, Traits, Allocator>& lhs,
  447. std::basic_string<Char, Traits, Allocator>& rhs) noexcept(noexcept(lhs.swap(rhs)))
  448. {
  449. lhs.swap(rhs);
  450. }
  451. using string = basic_string<char>;
  452. } // namespace std
  453. #endif