From cd3a7e21339d6576965efba2a6d933085e13b49d Mon Sep 17 00:00:00 2001 From: Nomango Date: Thu, 28 May 2020 02:41:59 +0800 Subject: [PATCH] add StringView --- src/kiwano/core/String.h | 358 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 356 insertions(+), 2 deletions(-) diff --git a/src/kiwano/core/String.h b/src/kiwano/core/String.h index cdb45b54..2307a5f7 100644 --- a/src/kiwano/core/String.h +++ b/src/kiwano/core/String.h @@ -20,17 +20,24 @@ #pragma once #include +#include namespace kiwano { +/// \~chinese +/// @brief »ù´¡×Ö·û´®ÈÝÆ÷ +template +using BasicString = std::basic_string; + /// \~chinese /// @brief ×Ö·û´®ÈÝÆ÷ -using String = std::string; +using String = BasicString; /// \~chinese /// @brief ¿í×Ö·û´®ÈÝÆ÷ -using WideString = std::wstring; +using WideString = BasicString; + namespace strings { @@ -53,4 +60,351 @@ WideString NarrowToWide(const String& str); } + +/// \~chinese +/// @brief »ù´¡³£×Ö·û´®ÊÓͼ +template +class BasicStringView +{ +public: + using value_type = CharTy; + using pointer = CharTy*; + using const_pointer = const CharTy*; + using reference = CharTy&; + using const_reference = const CharTy&; + using traits_type = std::char_traits; + using size_type = std::size_t; + using string_type = BasicString; + + BasicStringView() + : ptr_(nullptr) + , count_(0) + { + } + + BasicStringView(const_pointer c_str) + { + ptr_ = c_str; + if (c_str) + { + count_ = traits_type::length(c_str); + } + else + { + count_ = 0; + } + } + + BasicStringView(const_pointer c_str, size_type count) + { + ptr_ = c_str; + if (c_str) + { + count_ = count; + } + else + { + count_ = 0; + } + } + + BasicStringView(const string_type& str) + : ptr_(str.c_str()) + , count_(str.length()) + { + } + + BasicStringView(const BasicStringView& rhs) + : ptr_(rhs.ptr_) + , count_(rhs.count_) + { + } + + inline const value_type* Data() const + { + return ptr_; + } + + inline bool IsEmpty() const + { + return !ptr_ || !count_; + } + + inline size_type Find(value_type ch) const + { + const auto ptr = traits_type::find(ptr_, count_, ch); + if (ptr) + { + return ptr - ptr_; + } + return string_type::npos; + } + + inline BasicStringView SubStr(size_type pos, size_type count = string_type::npos) const + { + if (pos >= count_) + return BasicStringView(); + + if (count == string_type::npos) + return BasicStringView(ptr_ + pos, count_ - pos); + + KGE_ASSERT(pos + count <= count_); + return BasicStringView(ptr_ + pos, count); + } + + inline size_type GetLength() const + { + return count_; + } + + inline value_type At(size_type index) const + { + return operator[](index); + } + + inline value_type operator[](size_type index) const + { + if (IsEmpty() || index >= count_) + throw std::out_of_range("operator[] out of index"); + return ptr_[index]; + } + + inline operator string_type() const + { + return string_type(ptr_, count_); + } + + inline BasicStringView& operator=(const BasicStringView& rhs) + { + ptr_ = rhs.ptr_; + count_ = rhs.count_; + return *this; + } + +public: + // + // Iterators for BasicStringView + // + class Iterator + { + const value_type* ptr_; + size_type pos_; + size_type count_; + + public: + using iterator_category = std::random_access_iterator_tag; + using value_type = value_type; + using pointer = value_type*; + using reference = value_type&; + using difference_type = ptrdiff_t; + + inline Iterator(pointer ptr, size_type pos, size_type count) + : ptr_(ptr) + , pos_(pos) + , count_(count) + { + } + + inline Iterator(const Iterator& rhs) + : ptr_(rhs.ptr_) + , pos_(rhs.pos_) + , count_(rhs.count_) + { + } + + inline Iterator& operator=(const Iterator& rhs) + { + ptr_ = rhs.ptr_; + pos_ = rhs.pos_; + count_ = rhs.count_; + return *this; + } + + inline const value_type& operator*() const + { + KGE_ASSERT(pos_ < count_); + return ptr_[pos_]; + } + + inline const value_type* operator->() const + { + return std::pointer_traits::pointer_to(**this); + } + + inline Iterator& operator+=(size_type count) + { + KGE_ASSERT(pos_ + count >= 0 && pos_ + count <= count_); + pos_ += count; + return (*this); + } + + inline Iterator& operator-=(size_type count) + { + KGE_ASSERT(pos_ - count >= 0 && pos_ - count <= count_); + pos_ -= count; + return (*this); + } + + inline const Iterator operator+(size_type count) const + { + Iterator iter(*this); + iter += count; + return iter; + } + + inline const Iterator& operator-(size_type count) const + { + Iterator iter(*this); + iter -= count; + return iter; + } + + inline Iterator& operator++() + { + KGE_ASSERT(pos_ < count_); + ++pos_; + return (*this); + } + + inline Iterator operator++(int) + { + Iterator old = (*this); + ++(*this); + return old; + } + + inline Iterator& operator--() + { + KGE_ASSERT(pos_ > 0); + --pos_; + return (*this); + } + + inline Iterator operator--(int) + { + Iterator old = (*this); + --(*this); + return old; + } + + inline const value_type& operator[](size_type index) const + { + Iterator iter = (*this + index); + return iter.ptr_[iter.pos_]; + } + + inline difference_type operator-(const Iterator& other) const + { + KGE_ASSERT(ptr_ == other.ptr_ && count_ == other.count_); + return static_cast(pos_ - other.pos_); + } + + inline bool operator==(const Iterator& other) const + { + return ptr_ == other.ptr_ && pos_ == other.pos_ && count_ == other.count_; + } + + inline bool operator!=(const Iterator& other) const + { + return !(*this == other); + } + + inline bool operator<(const Iterator& other) const + { + return ptr_ < other.ptr_ || pos_ < other.pos_ || count_ < other.count_; + } + + inline bool operator<=(const Iterator& other) const + { + return (*this < other) || (*this == other); + } + + inline bool operator>(const Iterator& other) const + { + return !(*this <= other); + } + + inline bool operator>=(const Iterator& other) const + { + return !(*this < other); + } + + inline operator bool() const + { + return ptr_ != nullptr && pos_ != count_; + } + }; + + using const_iterator = Iterator; + using iterator = const_iterator; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = const_reverse_iterator; + + inline const_iterator begin() const + { + return const_iterator(ptr_, 0, count_); + } + + inline const_iterator cbegin() const + { + return begin(); + } + + inline const_iterator end() const + { + return const_iterator(ptr_, count_, count_); + } + + inline const_iterator cend() const + { + return end(); + } + + inline const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + + inline const_reverse_iterator crbegin() const + { + return rbegin(); + } + + inline const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + + inline const_reverse_iterator crend() const + { + return rend(); + } + + inline const value_type& front() const + { + if (IsEmpty()) + throw std::out_of_range("front() called on empty list"); + return ptr_[0]; + } + + inline const value_type& back() const + { + if (IsEmpty()) + throw std::out_of_range("back() called on empty list"); + return ptr_[count_]; + } + +private: + const value_type* ptr_; + size_type count_; +}; + +/// \~chinese +/// @brief ×Ö·û´®ÊÓͼ +using StringView = BasicStringView; + +/// \~chinese +/// @brief ¿í×Ö·û´®ÊÓͼ +using WideStringView = BasicStringView; + } // namespace kiwano