| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543 | 
							- #ifndef __GBLIBCPP_STRING__
 
- #define __GBLIBCPP_STRING__
 
- #include <bits/compressed_pair>
 
- #include <bits/iter_ops>
 
- #include <algorithm>
 
- #include <functional>
 
- #include <memory>
 
- #include <initializer_list>
 
- #include <cstddef>
 
- #include <string.h>
 
- namespace std {
 
- template <typename T>
 
- class char_traits;
 
- template <>
 
- class char_traits<char>
 
- {
 
- public:
 
-     static std::size_t length(const char* str) { return strlen(str); }
 
-     static int compare(const char* s1, const char* s2, std::size_t cnt)
 
-     {
 
-         return strncmp(s1, s2, cnt);
 
-     }
 
- };
 
- template <typename Char,
 
-          typename Traits = std::char_traits<Char>,
 
-          typename Allocator = std::allocator<Char>>
 
- class basic_string {
 
- public:
 
-     using traits_type = Traits;
 
-     using value_type = Char;
 
-     using allocator_type = Allocator;
 
-     using size_type = typename std::allocator_traits<Allocator>::size_type;
 
-     using difference_type = typename std::allocator_traits<Allocator>::difference_type;
 
-     using reference = value_type&;
 
-     using const_reference = const value_type&;
 
-     using pointer = typename std::allocator_traits<Allocator>::pointer;
 
-     using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
 
-     template <bool Const>
 
-     class _iterator {
 
-     public:
 
-         // TODO:
 
-         // using iterator_category = std::random_access_iterator_tag;
 
-         using _reference = std::conditional_t<Const, const_reference, reference>;
 
-     private:
 
-         pointer m_ptr;
 
-     public:
 
-         constexpr _iterator(void) noexcept : m_ptr() {}
 
-         constexpr explicit _iterator(pointer ptr) noexcept
 
-             : m_ptr(ptr) {}
 
-         constexpr _iterator(const _iterator& other) noexcept = default;
 
-         constexpr _iterator(_iterator&& other) noexcept = default;
 
-         constexpr _iterator& operator=(const _iterator& other) noexcept = default;
 
-         constexpr _iterator& operator=(_iterator&& other) noexcept = default;
 
-         constexpr bool operator==(const _iterator& other) const noexcept = default;
 
-         constexpr _reference operator*() const noexcept { return *m_ptr; }
 
-         constexpr pointer operator&() const noexcept
 
-         { return std::addressof(this->operator*()); }
 
-         constexpr pointer operator->() const noexcept
 
-         { return this->operator&(); }
 
-         constexpr _iterator& operator++() noexcept
 
-         { ++m_ptr; return *this; }
 
-         constexpr _iterator operator++(int) noexcept
 
-         { _iterator ret(m_ptr); (void)this->operator++(); return ret; }
 
-         constexpr _iterator& operator--(void) noexcept
 
-         { --m_ptr; return *this; }
 
-         constexpr _iterator operator--(int) noexcept
 
-         { _iterator ret(m_ptr); (void)this->operator--(); return ret; }
 
-         constexpr _iterator& operator+=(difference_type n) noexcept
 
-         { m_ptr += n; return *this; }
 
-         constexpr _iterator& operator-=(difference_type n) noexcept
 
-         { m_ptr -= n; return *this; }
 
-         constexpr _iterator operator+(difference_type n) const noexcept
 
-         { return _iterator { m_ptr + n }; }
 
-         constexpr _iterator operator-(difference_type n) const noexcept
 
-         { return _iterator { m_ptr - n }; }
 
-         constexpr difference_type operator-(const _iterator& other) const noexcept
 
-         { return m_ptr - other.m_ptr; }
 
-         constexpr _reference operator[](difference_type n) const noexcept
 
-         { return m_ptr[n]; }
 
-         constexpr operator bool() { return m_ptr; }
 
-         constexpr operator _iterator<true>() { return _iterator<true> { m_ptr }; }
 
-         constexpr operator _iterator<false>() { return _iterator<false> { m_ptr }; }
 
-         constexpr operator pointer() { return m_ptr; }
 
-     };
 
- private:
 
-     using alloc_traits = std::allocator_traits<Allocator>;
 
- public:
 
-     using iterator = _iterator<false>;
 
-     using const_iterator = _iterator<true>;
 
- private:
 
-     static constexpr std::size_t STATIC_SIZE = 32;
 
-     static constexpr std::size_t STATIC_COUNT =
 
-         STATIC_SIZE / sizeof(Char) - 2;
 
-     struct string_data_type { union {
 
-         std::byte __data[STATIC_SIZE];
 
-         struct {
 
-             union {
 
-                 Char __data;
 
-                 unsigned char n;
 
-             } m_size;
 
-             Char str[STATIC_COUNT];
 
-             Char end;
 
-         } stackdata;
 
-         struct {
 
-             std::size_t m_size;
 
-             std::size_t m_capacity;
 
-             Char* m_ptr;
 
-         } heapdata;
 
-     } in; };
 
-     impl::compressed_pair<string_data_type, Allocator> m_data;
 
-     constexpr Allocator& _alloc() noexcept { return m_data.second(); }
 
-     constexpr const Allocator& _alloc() const noexcept { return m_data.second(); }
 
-     constexpr bool _stack_data() const
 
-     {
 
-         return m_data.first().in.stackdata.end == 0;
 
-     }
 
-     constexpr bool _stack_data(bool val)
 
-     {
 
-         return (m_data.first().in.stackdata.end = !val), val;
 
-     }
 
-     constexpr void _release()
 
-     {
 
-         if (_stack_data()) {
 
-             _size(0);
 
-             return;
 
-         }
 
-         alloc_traits::deallocate(m_data.second(), data(), capacity()+1);
 
-         _stack_data(true);
 
-         _size(0);
 
-         _data()[0] = 0;
 
-     }
 
-     constexpr void _reserve(std::size_t cnt)
 
-     {
 
-         std::size_t cursize = size();
 
-         Char* newdata = alloc_traits::allocate(_alloc(), cnt+1);
 
-         memcpy(newdata, data(), size());
 
-         newdata[cursize] = 0;
 
-         if (_stack_data()) {
 
-             _stack_data(false);
 
-             _size(cursize);
 
-         }
 
-         else {
 
-             alloc_traits::deallocate(_alloc(), data(), capacity()+1);
 
-         }
 
-         _capacity(cnt);
 
-         _data(newdata);
 
-     }
 
-     constexpr std::size_t _size() const
 
-     {
 
-         if (_stack_data())
 
-             return m_data.first().in.stackdata.m_size.n;
 
-         else
 
-             return m_data.first().in.heapdata.m_size;
 
-     }
 
-     constexpr std::size_t _size(std::size_t val)
 
-     {
 
-         if (_stack_data())
 
-             return m_data.first().in.stackdata.m_size.n = (Char)val;
 
-         else
 
-             return m_data.first().in.heapdata.m_size = val;
 
-     }
 
-     constexpr std::size_t _capacity() const
 
-     {
 
-         if (_stack_data())
 
-             return STATIC_COUNT;
 
-         else
 
-             return m_data.first().in.heapdata.m_capacity;
 
-     }
 
-     constexpr std::size_t _capacity(std::size_t val)
 
-     {
 
-         if (_stack_data())
 
-             return STATIC_COUNT;
 
-         else
 
-             return m_data.first().in.heapdata.m_capacity = val;
 
-     }
 
-     constexpr const Char* _data() const
 
-     {
 
-         if (_stack_data())
 
-             return m_data.first().in.stackdata.str;
 
-         else
 
-             return m_data.first().in.heapdata.m_ptr;
 
-     }
 
-     constexpr Char* _data()
 
-     {
 
-         if (_stack_data())
 
-             return m_data.first().in.stackdata.str;
 
-         else
 
-             return m_data.first().in.heapdata.m_ptr;
 
-     }
 
-     constexpr Char* _data(Char* val)
 
-     {
 
-         if (_stack_data())
 
-             return m_data.first().in.stackdata.str;
 
-         else
 
-             return m_data.first().in.heapdata.m_ptr = val;
 
-     }
 
- public:
 
-     constexpr basic_string() noexcept(noexcept(Allocator()))
 
-         : basic_string{Allocator{}} { }
 
-     constexpr explicit basic_string(const Allocator& alloc) noexcept
 
-         : m_data{{}, alloc} { }
 
-     constexpr basic_string(const basic_string& other, const Allocator& alloc)
 
-         : basic_string{alloc}
 
-     {
 
-         append(other.c_str(), other.size());
 
-     }
 
-     constexpr basic_string(const basic_string& other)
 
-         : basic_string{other, alloc_traits::
 
-             select_on_container_copy_construction(other._alloc())} { }
 
-     constexpr basic_string(basic_string&& other) noexcept
 
-         : m_data{other.m_data.first(), std::move(other._alloc())}
 
-     {
 
-         other._stack_data(true);
 
-         other._size(0);
 
-         other._data()[0] = 0;
 
-     }
 
-     constexpr basic_string(basic_string&& other, const Allocator& alloc)
 
-         : basic_string{alloc}
 
-     {
 
-         if (alloc == other._alloc()) {
 
-             m_data.first() = other.m_data.first();
 
-             other._stack_data(true);
 
-             other._size(0);
 
-             other._data()[0] = 0;
 
-         }
 
-         else {
 
-             append(other.c_str(), other.size());
 
-         }
 
-     }
 
-     constexpr basic_string(const basic_string& other, size_type pos,
 
-             const Allocator& alloc = Allocator{})
 
-         : basic_string{other.c_str() + pos, alloc} { }
 
-     // constexpr basic_string(std::initializer_list<Char> ilist,
 
-     //         const Allocator& alloc = Allocator{})
 
-     //     : basic_string {alloc}
 
-     // {
 
-     //     assign(ilist.begin(), ilist.end());
 
-     // }
 
-     constexpr basic_string(const Char* str, size_type count,
 
-             const Allocator& alloc = Allocator{})
 
-         : basic_string{alloc}
 
-     {
 
-         assign(str, count);
 
-     }
 
-     constexpr basic_string(const Char* str, const Allocator& alloc = Allocator{})
 
-         : basic_string{str, traits_type::length(str), alloc} { }
 
-     constexpr ~basic_string()
 
-     {
 
-         _release();
 
-     }
 
-     constexpr basic_string& operator=(const Char* str)
 
-     {
 
-         return assign(str);
 
-     }
 
-     constexpr basic_string& operator=(const basic_string& other)
 
-     {
 
-         return assign(other.c_str(), other.size());
 
-     }
 
-     constexpr basic_string& operator=(basic_string&& other)
 
-     {
 
-         if constexpr (alloc_traits::
 
-                 propagate_on_container_move_assignment::value) {
 
-             _release();
 
-             _alloc() = std::move(other._alloc());
 
-         }
 
-         else {
 
-             if (_alloc() != other._alloc()) {
 
-                 assign(other.c_str(), other.size());
 
-                 return *this;
 
-             }
 
-             _release();
 
-         }
 
-         m_data.first() = other.m_data.first();
 
-         other._stack_data(true);
 
-         other._size(0);
 
-         other._data()[0] = 0;
 
-         return *this;
 
-     }
 
-     constexpr basic_string& operator=(Char ch)
 
-     {
 
-         return assign(1, ch);
 
-     }
 
-     // constexpr basic_string& operator=(std::initializer_list<Char> init)
 
-     // {
 
-     //     assign(init.begin(), init.end());
 
-     //     return *this;
 
-     // }
 
-     constexpr basic_string& append(std::size_t len, Char ch)
 
-     {
 
-         std::size_t cursize = size();
 
-         std::size_t newsize = cursize + len;
 
-         if (newsize > capacity())
 
-             _reserve(std::max(capacity() * 2, newsize));
 
-         auto* pdata = data();
 
-         for (std::size_t i = cursize; i < newsize; ++i)
 
-             pdata[i] = ch;
 
-         pdata[newsize] = 0;
 
-         _size(newsize);
 
-         return *this;
 
-     }
 
-     constexpr basic_string& append(const Char* str, std::size_t count)
 
-     {
 
-         std::size_t cursize = size();
 
-         std::size_t newsize = cursize + count;
 
-         if (newsize > capacity())
 
-             _reserve(std::max(capacity() * 2, newsize));
 
-         memcpy(data() + cursize, str, count);
 
-         data()[newsize] = 0;
 
-         _size(newsize);
 
-         return *this;
 
-     }
 
-     constexpr basic_string& append(const Char* str)
 
-     {
 
-         return append(str, traits_type::length(str));
 
-     }
 
-     constexpr basic_string& assign(size_type n, Char ch)
 
-     {
 
-         clear();
 
-         return append(n, ch);
 
-     }
 
-     constexpr basic_string& assign(const Char* str, size_type count)
 
-     {
 
-         clear();
 
-         return append(str, count);
 
-     }
 
-     constexpr basic_string& assign(const Char* str)
 
-     {
 
-         return assign(str, traits_type::length(str));
 
-     }
 
-     // TODO: check whether InputIter satisfies LegacyInputIterator
 
-     // template <typename InputIter>
 
-     // constexpr basic_string& assign(InputIter first, InputIter last)
 
-     // {
 
-     //     clear();
 
-     //     insert(cbegin(), first, last);
 
-     //     return *this;
 
-     // }
 
-     // constexpr basic_string& assign(std::initializer_list<T> init)
 
-     // {
 
-     //     clear();
 
-     //     insert(cbegin(), init.begin(), init.end());
 
-     //     return *this;
 
-     // }
 
-     constexpr basic_string& operator+=(Char ch)
 
-     {
 
-         return append(1, ch);
 
-     }
 
-     constexpr basic_string& operator+=(const Char* str)
 
-     {
 
-         return append(str);
 
-     }
 
-     constexpr basic_string& operator+=(const basic_string& str)
 
-     {
 
-         return append(str.c_str(), str.size());
 
-     }
 
-     constexpr bool empty() const noexcept
 
-     { return size() == 0; }
 
-     constexpr size_type size() const noexcept
 
-     { return _size(); }
 
-     constexpr size_type capacity() const noexcept
 
-     { return _capacity(); }
 
-     constexpr Char* data() noexcept { return _data(); }
 
-     constexpr const Char* data() const noexcept { return _data(); }
 
-     constexpr const Char* c_str() const noexcept { return data(); }
 
-     constexpr reference operator[](size_type pos)
 
-     { return data()[pos]; }
 
-     constexpr const_reference operator[](size_type pos) const
 
-     { return data()[pos]; }
 
-     // constexpr reference at(size_type pos)
 
-     // {
 
-     //     // TODO: exceptions
 
-     //     // if (pos >= size())
 
-     //     //     throw std::out_of_range("basic_string::at");
 
-     //     return operator[](pos);
 
-     // }
 
-     // constexpr const_reference at(size_type pos) const
 
-     // {
 
-     //     // TODO: exceptions
 
-     //     // if (pos >= size())
 
-     //     //     throw std::out_of_range("basic_string::at");
 
-     //     return operator[](pos);
 
-     // }
 
-     constexpr reference front() noexcept
 
-     { return operator[](0); }
 
-     constexpr const_reference front() const noexcept
 
-     { return operator[](0); }
 
-     constexpr reference back() noexcept
 
-     { return operator[](size() - 1); }
 
-     constexpr const_reference back() const noexcept
 
-     { return operator[](size() - 1); }
 
-     // TODO: std::reverse_iterator
 
-     constexpr iterator begin() noexcept
 
-     { return iterator { data() }; }
 
-     constexpr const_iterator begin() const noexcept
 
-     { return const_iterator { data() }; }
 
-     constexpr const_iterator cbegin() const noexcept
 
-     { return const_iterator { data() }; }
 
-     constexpr iterator end() noexcept
 
-     { return iterator { data() + size() }; }
 
-     constexpr const_iterator end() const noexcept
 
-     { return const_iterator { data() + size() }; }
 
-     constexpr const_iterator cend() const noexcept
 
-     { return const_iterator { data() + size() }; }
 
-     constexpr void clear() noexcept{ _size(0); }
 
-     constexpr void push_back(Char ch) { append(1, ch); }
 
-     constexpr void pop_back() { erase(cend()-1); }
 
-     constexpr void swap(basic_string& other) noexcept(
 
-         alloc_traits::propagate_on_container_swap::value
 
-         || alloc_traits::is_always_equal::value)
 
-     {
 
-         if (alloc_traits::propagate_on_container_swap::value)
 
-             std::swap(_alloc(), other._alloc());
 
-         std::swap(m_data.first(), other.m_data.first());
 
-     }
 
-     constexpr int compare(const basic_string& str) const noexcept
 
-     {
 
-         return traits_type::compare(c_str(), str.c_str(), size()+1);
 
-     }
 
-     constexpr int compare(const Char* str) const
 
-     {
 
-         return traits_type::compare(c_str(), str, size()+1);
 
-     }
 
- };
 
- template <typename Char, typename Traits, typename Allocator>
 
- constexpr bool operator==(
 
-     const std::basic_string<Char, Traits, Allocator>& lhs,
 
-     const std::basic_string<Char, Traits, Allocator>& rhs) noexcept
 
- {
 
-     return lhs.compare(rhs) == 0;
 
- }
 
- template <typename Char, typename Traits, typename Allocator>
 
- constexpr bool operator==(
 
-     const std::basic_string<Char, Traits, Allocator>& lhs, const Char* rhs)
 
- {
 
-     return lhs.compare(rhs) == 0;
 
- }
 
- template <typename Char, typename Traits, typename Allocator>
 
- constexpr bool operator<(
 
-     const std::basic_string<Char, Traits, Allocator>& lhs,
 
-     const std::basic_string<Char, Traits, Allocator>& rhs) noexcept
 
- {
 
-     return lhs.compare(rhs) < 0;
 
- }
 
- template <typename Char, typename Traits, typename Allocator>
 
- constexpr void swap(
 
-     std::basic_string<Char, Traits, Allocator>& lhs,
 
-     std::basic_string<Char, Traits, Allocator>& rhs) noexcept(noexcept(lhs.swap(rhs)))
 
- {
 
-     lhs.swap(rhs);
 
- }
 
- using string = basic_string<char>;
 
- } // namespace std
 
- #endif
 
 
  |