#pragma GCC system_header #ifndef _LIBCXX_STRING #define _LIBCXX_STRING #include <__config> #include #include #include #include #include #include #include _LIBCXX_BEGIN_NAMESPACE_STD static char __null_char = '\0'; template class char_traits { public: using char_type = CharT; using int_type = int; using pos_type = int; using off_type = int; using state_type = int; static constexpr void assign(char_type& r, const char_type& a) { r = a; } static constexpr char_type* assign(char_type* p, size_t count, char_type a) { for (size_t sz = 0; sz < count; sz++) { assign(p[sz], a); } return p; } static constexpr char_type* move(char_type* dest, const char_type* src, size_t count) { for (size_t sz = 0; sz < count; sz++) { dest[sz] = std::move(src[sz]); } return dest; } static constexpr size_t length(const char_type* s) { return strlen(s); } static constexpr char_type* copy(char_type* dest, const char_type* src, size_t count) { for (size_t sz = 0; sz < count; sz++) { dest[sz] = src[sz]; } return dest; } static constexpr int compare(const char_type* a, const char_type* b, size_t count) { return strncmp(a, b, count); } static constexpr char_type to_char_type(int_type c) { return static_cast(c); } static constexpr int_type to_int_type(char_type c) { return static_cast(c); } static constexpr bool eq_int_type(int_type c1, int_type c2) { return c1 == c2; } static constexpr int_type eof() { return -1; } static constexpr bool not_eof(int_type a) { return a != eof(); } static constexpr bool eq(char_type a, char_type b) { return a == b; } static constexpr bool lt(char_type a, char_type b) { return a < b; } }; template class basic_string_view; template , class Allocator = std::allocator> class basic_string { public: using value_type = CharT; using allocator_type = Allocator; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using pointer = CharT*; using const_pointer = const CharT*; using reference = CharT&; using const_reference = const CharT&; using iterator = std::__legacy_iter; using const_iterator = std::__legacy_iter; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; basic_string() = default; basic_string(const value_type* str) { m_size = Traits::length(str); ensure_capacity(m_size + 1); Traits::copy(m_str, str, m_size); Traits::assign(m_str[m_size], '\0'); } basic_string(const value_type* str, size_t size) { m_size = size; ensure_capacity(m_size + 1); Traits::copy(m_str, str, m_size); Traits::assign(m_str[m_size], '\0'); } template constexpr basic_string(Iter first, Iter last) { m_size = std::distance(first, last); ensure_capacity(m_size + 1); for (size_t i = 0; first != last; ++first, ++i) { Traits::assign(at(i), *first); } } basic_string(const basic_string& s) { m_size = s.m_size; ensure_capacity(m_size + 1); Traits::copy(m_str, s.m_str, m_size); Traits::assign(m_str[m_size], '\0'); } basic_string(basic_string&& s) { m_size = s.m_size; m_capacity = s.m_capacity; m_str = s.m_str; s.m_size = s.m_capacity = 0; s.m_str = &__null_char; } ~basic_string() { clear(); } basic_string& operator=(const basic_string& s) { m_size = s.m_size; ensure_capacity(m_size + 1); Traits::copy(m_str, s.m_str, m_size); Traits::assign(m_str[m_size], '\0'); return *this; } basic_string& operator=(basic_string&& s) { if (this != &s) { clear(); m_size = s.m_size; m_capacity = s.m_capacity; m_str = s.m_str; s.m_size = s.m_capacity = 0; s.m_str = &__null_char; } return *this; } basic_string& operator+=(const basic_string& s) { ensure_capacity(size() + s.size() + 1); Traits::copy(&m_str[m_size], s.m_str, s.m_size); m_size += s.size(); Traits::assign(m_str[m_size], '\0'); return *this; } basic_string operator+(const basic_string& s) const { basic_string res(*this); res += s; return res; } basic_string operator+(const value_type* s) const { basic_string res(*this); res += basic_string(s); return res; } constexpr allocator_type get_allocator() const { return m_allocator; } inline void push_back(const value_type& c) { ensure_capacity(size() + 2); Traits::assign(m_str[m_size], c); m_size++; Traits::assign(m_str[m_size], '\0'); } inline void pop_back() { --m_size; Traits::assign(m_str[m_size], '\0'); } inline const_reference at(size_t i) const { return m_str[i]; } inline reference at(size_t i) { return m_str[i]; } void clear() { if (m_capacity && m_str != &__null_char) { free(m_str); m_str = &__null_char; } m_size = 0; m_capacity = 0; } void resize(size_t count, const value_type& c) { ensure_capacity(count + 1); Traits::assign(&m_str[m_size], count - size(), c); m_size = count; Traits::assign(m_str[m_size], '\0'); } void resize(size_t count) { resize(count, '\0'); } inline size_t size() const { return m_size; } inline size_t length() const { return m_size; } inline bool empty() const { return size() == 0; } inline const_reference operator[](size_t i) const { return at(i); } inline reference operator[](size_t i) { return at(i); } inline const_reference front() const { return at(0); } inline reference front() { return at(0); } inline const_reference back() const { return at(size() - 1); } inline reference back() { return at(size() - 1); } inline const_pointer c_str() const { return m_str; } inline const_pointer data() const { return m_str; } inline iterator begin() { return iterator(&m_str[0]); } inline iterator end() { return iterator(&m_str[m_size]); } inline const_iterator cbegin() const { return const_iterator(&m_str[0]); } inline const_iterator cend() const { return const_iterator(&m_str[m_size]); } inline reverse_iterator rbegin() { return reverse_iterator(&m_str[m_size - 1]); } inline reverse_iterator rend() { return reverse_iterator(&m_str[-1]); } inline const_reverse_iterator crbegin() const { return const_reverse_iterator(&m_str[m_size - 1]); } inline const_reverse_iterator crend() const { return const_reverse_iterator(&m_str[-1]); } inline operator std::basic_string_view() const { return std::basic_string_view(data(), size()); } bool starts_with(value_type c) const { if (size() == 0) { return false; } return Traits::eq(at(0), c) == 0; } bool starts_with(const value_type* s) const { size_t len = Traits::length(s); if (size() < len) { return false; } return Traits::compare(c_str(), s, len) == 0; } private: inline void ensure_capacity(size_t new_size) { int capacity = 4; while (new_size > capacity) { capacity *= 2; } grow(capacity); } void grow(size_t capacity) { if (capacity < m_capacity) { return; } if (!m_capacity) { m_str = m_allocator.allocate(capacity); } else { auto new_str = m_allocator.allocate(capacity); Traits::move(new_str, m_str, m_capacity); m_allocator.deallocate(m_str, m_capacity); m_str = new_str; } m_capacity = capacity; } size_t m_size { 0 }; size_t m_capacity { 0 }; value_type* m_str { &__null_char }; allocator_type m_allocator; }; typedef basic_string string; static std::string to_string(int a) { char buf[32]; std::sprintf(buf, "%d", a); return std::string(buf); } static std::string to_string(unsigned a) { char buf[32]; std::sprintf(buf, "%u", a); return std::string(buf); } template bool operator==(const std::basic_string& a, const std::basic_string& b) { if (a.size() != b.size()) { return false; } return Traits::compare(a.c_str(), b.c_str(), a.size()) == 0; } template bool operator==(const std::basic_string& a, const CharT* cstr) { size_t bsize = Traits::length(cstr); if (a.size() != bsize) { return false; } return Traits::compare(a.c_str(), cstr, a.size()) == 0; } template bool operator<(const std::basic_string& a, const std::basic_string& b) { int eq = Traits::compare(a.c_str(), b.c_str(), std::min(a.size(), b.size())); if (!eq) { return eq == -1; } return a.size() < b.size(); } _LIBCXX_END_NAMESPACE_STD #endif // _LIBCXX_STRING