/* * Copyright: JessMA Open Source (ldcsaa@gmail.com) * * Author : Bruce Liang * Website : https://github.com/ldcsaa * Project : https://github.com/ldcsaa/HP-Socket * Blog : http://www.cnblogs.com/ldcsaa * Wiki : http://www.oschina.net/p/hp-socket * QQ Group : 44636872, 75375912 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "FuncHelper.h" #include #include #include using namespace std; template, typename _Alloc = allocator<_CharT>> class CStringT : public basic_string<_CharT, _Traits, _Alloc> { public: using __super = basic_string<_CharT, _Traits, _Alloc>; using XCHAR = _CharT; using PXSTR = _CharT*; using PCXSTR = const _CharT*; using traits_type = typename __super::traits_type; using value_type = typename __super::value_type; using allocator_type = typename __super::allocator_type; using size_type = typename __super::size_type; using difference_type = typename __super::difference_type; using reference = typename __super::reference; using const_reference = typename __super::const_reference; using pointer = typename __super::pointer; using const_pointer = typename __super::const_pointer; using iterator = typename __super::iterator; using const_iterator = typename __super::const_iterator; using const_reverse_iterator = typename __super::const_reverse_iterator; using reverse_iterator = typename __super::reverse_iterator; using __super::clear; using __super::empty; using __super::size; using __super::resize; using __super::data; using __super::c_str; private: constexpr static PCXSTR SPACE_CHARS = _T(" \t\r\n\f\v"); public: void Empty() {clear();} bool IsEmpty() const {return empty();} int GetLength() const {return (int)size();} const _CharT* GetString() const {return c_str();} operator const _CharT* () const {return __super::c_str();} _CharT* GetBuffer(int length) { resize((size_type)length); return (_CharT*)data(); } void ReleaseBuffer(int length = -1) { if(length == -1) length = lstrlen(data()); resize(length); } void ReleaseBufferSetLength(int length) { ASSERT(length >=0); ReleaseBuffer(length); } void Truncate(int length) { if(length >= GetLength()) return; ReleaseBuffer(length); } int Format(const _CharT* format, ...) { int rs; va_list ap; va_start(ap, format); rs = VASprintf(0, format, ap); va_end(ap); return rs; } int AppendFormat(const _CharT* format, ...) { int rs; va_list ap; va_start(ap, format); rs = VASprintf(GetLength(), format, ap); va_end(ap); return rs; } int VASprintf(int offset, const _CharT* format, va_list ap) { va_list ap_cpy; va_copy(ap_cpy, ap); int count = vsnprintf(nullptr, 0, format, ap); if(count >= 0) { _CharT* p = GetBuffer(count + offset); vsnprintf(p + offset, count + 1, format, ap_cpy); } va_end(ap_cpy); return count; } CStringT& Append(const _CharT* __s) { append(__s); return *this; } CStringT& Append(const _CharT* __s, int __n) { append(__s, __n); return *this; } CStringT& AppendChar(_CharT __c) { push_back(__c); return *this; } int Compare(const _CharT* __s) const { return lstrcmp(c_str(), __s); } int CompareNoCase(const _CharT* __s) const { return lstricmp(c_str(), __s); } bool Equals(const _CharT* __s) const { return (Compare(__s) == 0); } bool EqualsNoCase(const _CharT* __s) const { return (CompareNoCase(__s) == 0); } CStringT& MakeLower() { size_type s = size(); _CharT* p = (_CharT*)c_str(); _CharT c; for(size_type i = 0; i < s; i++) { c = p[i]; if(c >= 'A' && c <= 'Z') p[i] = (_CharT)(c + 32); } return *this; } CStringT& MakeUpper() { size_type s = size(); _CharT* p = (_CharT*)c_str(); _CharT c; for(size_type i = 0; i < s; i++) { c = p[i]; if(c >= 'a' && c <= 'z') p[i] = (_CharT)(c - 32); } return *this; } CStringT Mid(int iFirst, int nCount = (int)__super::npos) const { return substr(iFirst, nCount); } CStringT Left(int nCount) const { return Mid(0, nCount); } CStringT Right(int nCount) const { int nLength = GetLength(); if(nCount >= nLength) return *this; return Mid(nLength - nCount, nCount); } CStringT Tokenize(PCXSTR lpszTokens, int& iStart) const { ASSERT(iStart >= 0); if((lpszTokens == nullptr) || (*lpszTokens == (_CharT)0)) { if(iStart < GetLength()) return CStringT(GetString() + iStart); } else { PCXSTR pszPlace = GetString() + iStart; PCXSTR pszEnd = GetString() + GetLength(); if(pszPlace < pszEnd) { int nIncluding = lstrspn(pszPlace, lpszTokens); if((pszPlace + nIncluding) < pszEnd) { pszPlace += nIncluding; int nExcluding = lstrcspn(pszPlace, lpszTokens); int iFrom = iStart + nIncluding; int nUntil = nExcluding; iStart = iFrom + nUntil + 1; return Mid(iFrom, nUntil); } } } iStart = -1; return CStringT(); } CStringT& Trim() { return Trim(SPACE_CHARS); } CStringT& TrimRight() { return TrimRight(SPACE_CHARS); } CStringT& TrimLeft() { return TrimLeft(SPACE_CHARS); } CStringT& Trim(XCHAR c) { return(TrimRight(c).TrimLeft(c)); } CStringT& TrimRight(XCHAR c) { int iLength = GetLength(); if(iLength == 0) return *this; PCXSTR lpszBegin = GetString(); PCXSTR lpszEnd = lpszBegin + iLength; while(lpszEnd > lpszBegin) { if(*(lpszEnd - 1) != c) break; --lpszEnd; } int iNewLength = (int)(lpszEnd - lpszBegin); if(iNewLength < iLength) Truncate(iNewLength); return *this; } CStringT& TrimLeft(XCHAR c) { int iLength = GetLength(); if(iLength == 0) return *this; PCXSTR lpszBegin = GetString(); PCXSTR lpszEnd = lpszBegin; int iOffset = 0; while(*lpszEnd == c) { ++lpszEnd; ++iOffset; if(iOffset == iLength) break; } if(iOffset != 0) { int iNewLength = iLength - iOffset; if(iNewLength > 0) memcpy((PXSTR)lpszBegin, lpszEnd, (iLength - iOffset) * sizeof(XCHAR)); ReleaseBufferSetLength(iNewLength); } return *this; } CStringT& Trim(PCXSTR lpszChars) { return(TrimRight(lpszChars).TrimLeft(lpszChars)); } CStringT& TrimRight(PCXSTR lpszChars) { ASSERT(!::IsStrEmpty(lpszChars)); if(::IsStrEmpty(lpszChars)) return *this; int iLength = GetLength(); if(iLength == 0) return *this; PCXSTR lpszBegin = GetString(); PCXSTR lpszEnd = lpszBegin + iLength; while(lpszEnd > lpszBegin) { if(::StrChr(lpszChars, *(lpszEnd - 1)) == nullptr) break; --lpszEnd; } int iNewLength = (int)(lpszEnd - lpszBegin); if(iNewLength < iLength) Truncate(iNewLength); return *this; } CStringT& TrimLeft(PCXSTR lpszChars) { ASSERT(!::IsStrEmpty(lpszChars)); if(::IsStrEmpty(lpszChars)) return *this; int iLength = GetLength(); if(iLength == 0) return *this; PCXSTR lpszBegin = GetString(); PCXSTR lpszEnd = lpszBegin; int iOffset = 0; while(::StrChr(lpszChars, *lpszEnd) != nullptr) { ++lpszEnd; ++iOffset; if(iOffset == iLength) break; } if(iOffset != 0) { int iNewLength = iLength - iOffset; if(iNewLength > 0) memcpy((PXSTR)lpszBegin, lpszEnd, (iLength - iOffset) * sizeof(XCHAR)); ReleaseBufferSetLength(iNewLength); } return *this; } int Find(XCHAR c, int iStart = 0) const { ASSERT(iStart >= 0); int iLength = GetLength(); if(iStart < 0 || iStart >= iLength) return -1; PCXSTR lpszBegin = GetString(); PCXSTR lpszFind = ::StrChr(lpszBegin + iStart, c); return ((lpszFind == nullptr) ? -1 : (int)(lpszFind - lpszBegin)); } int Find(PCXSTR lpszSub, int iStart = 0) const { ASSERT(iStart >= 0 && !::IsStrEmpty(lpszSub)); int iLength = GetLength(); if(lpszSub == nullptr || iStart < 0 || iStart > iLength) return -1; PCXSTR lpszBegin = GetString(); PCXSTR lpszFind = ::StrStr(lpszBegin + iStart, lpszSub); return ((lpszFind == nullptr) ? -1 : (int)(lpszFind - lpszBegin)); } int FindOneOf(PCXSTR lpszChars) const { ASSERT(!::IsStrEmpty(lpszChars)); if(lpszChars == nullptr) return -1; PCXSTR lpszBegin = GetString(); PCXSTR lpszFind = ::StrPBrk(lpszBegin, lpszChars); return ((lpszFind == nullptr) ? -1 : (int)(lpszFind - lpszBegin)); } int ReverseFind(XCHAR c) const { PCXSTR lpszBegin = GetString(); PCXSTR lpszFind = ::StrRChr(lpszBegin, c); return ((lpszFind == nullptr) ? -1 : (int)(lpszFind - lpszBegin)); } int Remove(XCHAR c) { int iLength = GetLength(); if(iLength == 0) return 0; PCXSTR lpszBegin = GetString(); PXSTR lpszCur = (PXSTR)lpszBegin; PCXSTR lpszEnd = lpszBegin + iLength; int iRemoved = 0; while(lpszCur < lpszEnd) { if(*lpszCur == c) ++iRemoved; else if(iRemoved > 0) *(lpszCur - iRemoved) = *lpszCur; ++lpszCur; } if(iRemoved > 0) ReleaseBufferSetLength(iLength - iRemoved); return iRemoved; } XCHAR GetAt(int i) const { return (*this)[i]; } void SetAt(int i, XCHAR c) { (*this)[i] = c; } XCHAR operator[](int i) const { ASSERT(i >= 0 && i < GetLength()); return *(GetString() + i); } XCHAR& operator[](int i) { ASSERT(i >= 0 && i < GetLength()); return *(PXSTR)(GetString() + i); } CStringT& Insert(int i, XCHAR c) { return insert((size_type)i, 1, c); } CStringT& Insert(int i, PCXSTR lpszChars) { return insert((size_type)i, lpszChars); } CStringT& SetString(PCXSTR lpszStr) { return assign(lpszStr); } CStringT& SetString(PCXSTR lpszStr, int iLength) { return assign(lpszStr, iLength); } friend bool operator==(const CStringT& str1, const CStringT& str2) { return (str1.Compare(str2) == 0); } friend bool operator==(const CStringT& str1, const _CharT* psz2) { return (str1.Compare(psz2) == 0); } friend bool operator==(const _CharT* psz1, const CStringT& str2) { return (str2.Compare(psz1) == 0); } friend bool operator!=(const CStringT& str1, const CStringT& str2) { return !(str1 == str2); } friend bool operator!=(const CStringT& str1, const _CharT* psz2) { return !(str1 == psz2); } friend bool operator!=(const _CharT* psz1, const CStringT& str2) { return !(psz1 == str2); } public: CStringT() : __super() {}; explicit CStringT(const _Alloc& __a) : __super(__a) {} CStringT(const __super& __str) : __super(__str) {} CStringT(const CStringT& __str) : __super(__str) {} CStringT(const __super& __str, size_type __pos, size_type __n = __super::npos) : __super(__str, __pos, __n) {} CStringT(const __super& __str, size_type __pos, size_type __n, const _Alloc& __a) : __super(__str, __pos, __n, __a) {} CStringT(const _CharT* __s, size_type __n, const _Alloc& __a = _Alloc()) : __super(::SafeStr(__s), __n, __a) {} CStringT(const _CharT* __s, const _Alloc& __a = _Alloc()) : __super(::SafeStr(__s), __a) {} CStringT(size_type __n, _CharT __c, const _Alloc& __a = _Alloc()) : __super(__n, __c, __a) {} #if __cplusplus >= 201103L CStringT(__super&& __str) : __super(__str) {} CStringT(CStringT&& __str) : __super(__str) {} CStringT(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc()) : __super(__l, __a) {} #endif // C++11 template CStringT(_InputIterator __beg, _InputIterator __end, const _Alloc& __a = _Alloc()) : __super(__beg, __end, __a) {} ~CStringT() = default; CStringT& operator=(const __super& __str) {__super::operator=(__str); return *this;} CStringT& operator=(const CStringT& __str) {__super::operator=(__str); return *this;} CStringT& operator=(const _CharT* __s) {__super::operator=(::SafeStr(__s)); return *this;} CStringT& operator=(_CharT __c) {__super::operator=(__c); return *this;} #if __cplusplus >= 201103L CStringT& operator=(__super&& __str) {__super::operator=(__str); return *this;} CStringT& operator=(CStringT&& __str) {__super::operator=(__str); return *this;} CStringT& operator=(initializer_list<_CharT> __l) {__super::operator=(__l); return *this;} #endif // C++11 public: CStringT& operator+=(const __super& __str) {__super::operator+=(__str); return *this;} CStringT& operator+=(const _CharT* __s) {__super::operator+=(::SafeStr(__s)); return *this;} CStringT& operator+=(_CharT __c) {__super::operator+=(__c); return *this;} #if __cplusplus >= 201103L CStringT& operator+=(initializer_list<_CharT> __l) {__super::operator+=(__l); return *this;} #endif // C++11 CStringT& append(const __super& __str) {__super::append(__str); return *this;} CStringT& append(const __super& __str, size_type __pos, size_type __n) {__super::append(__str, __pos, __n); return *this;} CStringT& append(const _CharT* __s, size_type __n) {__super::append(::SafeStr(__s), __n); return *this;} CStringT& append(const _CharT* __s) {__super::append(::SafeStr(__s)); return *this;} CStringT& append(size_type __n, _CharT __c) {__super::append(__n, __c); return *this;} #if __cplusplus >= 201103L CStringT& append(initializer_list<_CharT> __l) {__super::append(__l); return *this;} #endif // C++11 template CStringT& append(_InputIterator __first, _InputIterator __last) {__super::append(__first, __last); return *this;} void push_back(_CharT __c) {__super::push_back(__c);} CStringT& assign(const __super& __str) {__super::assign(__str); return *this;} #if __cplusplus >= 201103L CStringT& assign(__super&& __str) {__super::assign(__str); return *this;} #endif // C++11 CStringT& assign(const __super& __str, size_type __pos, size_type __n) {__super::assign(__str, __pos, __n); return *this;} CStringT& assign(const _CharT* __s, size_type __n) {__super::assign(::SafeStr(__s), __n); return *this;} CStringT& assign(const _CharT* __s) {__super::assign(::SafeStr(__s)); return *this;} CStringT& assign(size_type __n, _CharT __c) {__super::assign(__n, __c); return *this;} template CStringT& assign(_InputIterator __first, _InputIterator __last) {__super::assign(__first, __last); return *this;} #if __cplusplus >= 201103L CStringT& assign(initializer_list<_CharT> __l) {__super::assign(__l); return *this;} #endif // C++11 CStringT& insert(size_type __pos1, const __super& __str) {__super::insert(__pos1, __str); return *this;} CStringT& insert(size_type __pos1, const __super& __str, size_type __pos2, size_type __n) {__super::insert(__pos1, __str, __pos2, __n); return *this;} CStringT& insert(size_type __pos, const _CharT* __s, size_type __n) {__super::insert(__pos, __s, __n); return *this;} CStringT& insert(size_type __pos, const _CharT* __s) {__super::insert(__pos, __s); return *this;} CStringT& insert(size_type __pos, size_type __n, _CharT __c) {__super::insert(__pos, __n, __c); return *this;} CStringT& erase(size_type __pos = 0, size_type __n = __super::npos) {__super::erase(__pos, __n); return *this;} CStringT& replace(size_type __pos, size_type __n, const __super& __str) {__super::replace(__pos, __n, __str); return *this;} CStringT& replace(size_type __pos1, size_type __n1, const __super& __str, size_type __pos2, size_type __n2) {__super::replace(__pos1, __n1, __str, __pos2, __n2); return *this;} CStringT& replace(size_type __pos, size_type __n1, const _CharT* __s, size_type __n2) {__super::replace(__pos, __n1, __s, __n2); return *this;} CStringT& replace(size_type __pos, size_type __n1, const _CharT* __s) {__super::replace(__pos, __n1, __s); return *this;} CStringT& replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c) {__super::replace(__pos, __n1, __n2, __c); return *this;} CStringT& replace(iterator __i1, iterator __i2, const __super& __str) {__super::replace(__i1, __i2, __str); return *this;} CStringT& replace(iterator __i1, iterator __i2, const _CharT* __s, size_type __n) {__super::replace(__i1, __i2, __s, __n); return *this;} CStringT& replace(iterator __i1, iterator __i2, const _CharT* __s) {__super::replace(__i1, __i2, __s); return *this;} CStringT& replace(iterator __i1, iterator __i2, size_type __n, _CharT __c) {__super::replace(__i1, __i2, __n, __c); return *this;} template CStringT& replace(iterator __i1, iterator __i2, _InputIterator __k1, _InputIterator __k2) {__super::replace(__i1, __i2, __k1, __k2); return *this;} CStringT& replace(iterator __i1, iterator __i2, _CharT* __k1, _CharT* __k2) {__super::replace(__i1, __i2, __k1, __k2); return *this;} CStringT& replace(iterator __i1, iterator __i2, const _CharT* __k1, const _CharT* __k2) {__super::replace(__i1, __i2, __k1, __k2); return *this;} CStringT& replace(iterator __i1, iterator __i2, iterator __k1, iterator __k2) {__super::replace(__i1, __i2, __k1, __k2); return *this;} CStringT& replace(iterator __i1, iterator __i2, const_iterator __k1, const_iterator __k2) {__super::replace(__i1, __i2, __k1, __k2); return *this;} #if __cplusplus >= 201103L CStringT& replace(iterator __i1, iterator __i2, initializer_list<_CharT> __l) {__super::replace(__i1, __i2, __l); return *this;} #endif // C++11 CStringT substr(size_type __pos = 0, size_type __n = __super::npos) const {return __super::substr(__pos, __n);} }; template CStringT<_CharT, _Traits, _Alloc> operator+(const CStringT<_CharT, _Traits, _Alloc>& __lhs, const CStringT<_CharT, _Traits, _Alloc>& __rhs) { CStringT<_CharT, _Traits, _Alloc> __str(__lhs); __str.append(__rhs); return __str; } template CStringT<_CharT,_Traits,_Alloc> operator+(const _CharT* __lhs, const CStringT<_CharT,_Traits,_Alloc>& __rhs); template CStringT<_CharT,_Traits,_Alloc> operator+(_CharT __lhs, const CStringT<_CharT,_Traits,_Alloc>& __rhs); template inline CStringT<_CharT, _Traits, _Alloc> operator+(const CStringT<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) { CStringT<_CharT, _Traits, _Alloc> __str(__lhs); __str.append(__rhs); return __str; } template inline CStringT<_CharT, _Traits, _Alloc> operator+(const CStringT<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs) { typedef CStringT<_CharT, _Traits, _Alloc> __string_type; typedef typename __string_type::size_type __size_type; __string_type __str(__lhs); __str.append(__size_type(1), __rhs); return __str; } #if __cplusplus >= 201103L template inline CStringT<_CharT, _Traits, _Alloc> operator+(CStringT<_CharT, _Traits, _Alloc>&& __lhs, const CStringT<_CharT, _Traits, _Alloc>& __rhs) {return std::move(__lhs.append(__rhs));} template inline CStringT<_CharT, _Traits, _Alloc> operator+(const CStringT<_CharT, _Traits, _Alloc>& __lhs, CStringT<_CharT, _Traits, _Alloc>&& __rhs) {return std::move(__rhs.insert(0, __lhs));} template inline CStringT<_CharT, _Traits, _Alloc> operator+(CStringT<_CharT, _Traits, _Alloc>&& __lhs, CStringT<_CharT, _Traits, _Alloc>&& __rhs) { const auto __size = __lhs.size() + __rhs.size(); const bool __cond = (__size > __lhs.capacity() && __size <= __rhs.capacity()); return __cond ? std::move(__rhs.insert(0, __lhs)) : std::move(__lhs.append(__rhs)); } template inline CStringT<_CharT, _Traits, _Alloc> operator+(const _CharT* __lhs, CStringT<_CharT, _Traits, _Alloc>&& __rhs) {return std::move(__rhs.insert(0, __lhs));} template inline CStringT<_CharT, _Traits, _Alloc> operator+(_CharT __lhs, CStringT<_CharT, _Traits, _Alloc>&& __rhs) {return std::move(__rhs.insert(0, 1, __lhs));} template inline CStringT<_CharT, _Traits, _Alloc> operator+(CStringT<_CharT, _Traits, _Alloc>&& __lhs, const _CharT* __rhs) {return std::move(__lhs.append(__rhs));} template inline CStringT<_CharT, _Traits, _Alloc> operator+(CStringT<_CharT, _Traits, _Alloc>&& __lhs, _CharT __rhs) {return std::move(__lhs.append(1, __rhs));} #endif using CStringA = CStringT; using CStringW = CStringT; using CStdStringA = string; using CStdStringW = wstring; #ifdef _UNICODE using CString = CStringW; using CStdString = CStdStringW; #else using CString = CStringA; using CStdString = CStdStringA; #endif #define _HASH_SEED (size_t)0xdeadbeef template inline size_t hash_value(const _Kty& _Keyval) { return ((size_t)_Keyval ^ _HASH_SEED); } template inline size_t _Hash_value(_InIt _Begin, _InIt _End) { size_t _Val = 2166136261U; while(_Begin != _End) _Val = 16777619U * _Val ^ (size_t)*_Begin++; return (_Val); } template inline size_t hash_value(const basic_string<_Elem, _Traits, _Alloc>& _Str) { const _Elem *_Ptr = _Str.c_str(); return (_Hash_value(_Ptr, _Ptr + _Str.size())); } template inline size_t hash_value(const CStringT<_Elem>& _Str) { const _Elem *_Ptr = _Str.c_str(); return (_Hash_value(_Ptr, _Ptr + _Str.size())); } inline size_t hash_value(const char *_Str) { return (_Hash_value(_Str, _Str + strlen(_Str))); } inline size_t hash_value(const wchar_t *_Str) { return (_Hash_value(_Str, _Str + wcslen(_Str))); }