add StringView
This commit is contained in:
parent
de4b480dc2
commit
cd3a7e2133
|
|
@ -20,17 +20,24 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// \~chinese
|
||||||
|
/// @brief »ù´¡×Ö·û´®ÈÝÆ÷
|
||||||
|
template <typename CharTy>
|
||||||
|
using BasicString = std::basic_string<CharTy>;
|
||||||
|
|
||||||
/// \~chinese
|
/// \~chinese
|
||||||
/// @brief 字符串容器
|
/// @brief 字符串容器
|
||||||
using String = std::string;
|
using String = BasicString<char>;
|
||||||
|
|
||||||
/// \~chinese
|
/// \~chinese
|
||||||
/// @brief 宽字符串容器
|
/// @brief 宽字符串容器
|
||||||
using WideString = std::wstring;
|
using WideString = BasicString<wchar_t>;
|
||||||
|
|
||||||
|
|
||||||
namespace strings
|
namespace strings
|
||||||
{
|
{
|
||||||
|
|
@ -53,4 +60,351 @@ WideString NarrowToWide(const String& str);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// \~chinese
|
||||||
|
/// @brief »ù´¡³£×Ö·û´®ÊÓͼ
|
||||||
|
template <typename CharTy>
|
||||||
|
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<CharTy>;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using string_type = BasicString<CharTy>;
|
||||||
|
|
||||||
|
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>::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<difference_type>(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<const_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<char>;
|
||||||
|
|
||||||
|
/// \~chinese
|
||||||
|
/// @brief ¿í×Ö·û´®ÊÓͼ
|
||||||
|
using WideStringView = BasicStringView<wchar_t>;
|
||||||
|
|
||||||
} // namespace kiwano
|
} // namespace kiwano
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue