string 15 KB

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