2019-04-11 14:40:54 +08:00
// Copyright (c) 2016-2018 Kiwano - Nomango
2019-03-31 01:37:06 +08:00
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
# pragma once
# include <string>
# include <algorithm>
2019-03-31 23:09:49 +08:00
# include <codecvt>
2019-04-04 14:25:13 +08:00
# include <ostream>
# include <istream>
2019-03-31 01:37:06 +08:00
# include <cstring>
# include <cstdio>
2019-08-02 13:57:17 +08:00
namespace kiwano
{
template < typename _CharTy >
class basic_string ;
using string = basic_string < char > ;
using wstring = basic_string < wchar_t > ;
// String for kiwano
using String = wstring ;
}
2019-04-11 14:40:54 +08:00
namespace kiwano
2019-03-31 01:37:06 +08:00
{
//
2019-08-04 16:18:35 +08:00
// basic_string<>
// Lightweight std::basic_string<>-like class
// When using basic_string<> with a c-style string (char* or wchar_t*), constructor and operator=() just hold
// a pointer to the character array but don't copy its content, considering performance issues.
// Use assign() and basic_string<>::cstr() to work fine with c-style strings.
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
class basic_string
2019-03-31 01:37:06 +08:00
{
public :
// Iterator
template < typename _Ty >
struct iterator_impl
{
using iterator_category = typename std : : iterator_traits < _Ty * > : : iterator_category ;
using value_type = typename std : : iterator_traits < _Ty * > : : value_type ;
using difference_type = typename std : : iterator_traits < _Ty * > : : difference_type ;
using pointer = typename std : : iterator_traits < _Ty * > : : pointer ;
using reference = typename std : : iterator_traits < _Ty * > : : reference ;
// disable warning 4996
using _Unchecked_type = _Ty ;
inline iterator_impl ( pointer base = nullptr ) : base_ ( base ) { }
inline reference operator * ( ) const { return * base_ ; }
inline pointer base ( ) const { return base_ ; }
inline iterator_impl & operator + + ( ) { + + base_ ; return ( * this ) ; }
inline iterator_impl operator + + ( int ) { iterator_impl old = ( * this ) ; + + ( * this ) ; return old ; }
inline iterator_impl & operator - - ( ) { - - base_ ; return ( * this ) ; }
inline iterator_impl operator - - ( int ) { iterator_impl old = ( * this ) ; - - ( * this ) ; return old ; }
inline const iterator_impl operator + ( difference_type off ) const { return iterator_impl ( base_ + off ) ; }
inline const iterator_impl operator - ( difference_type off ) const { return iterator_impl ( base_ - off ) ; }
inline iterator_impl & operator + = ( difference_type off ) { base_ + = off ; return ( * this ) ; }
inline iterator_impl & operator - = ( difference_type off ) { base_ - = off ; return ( * this ) ; }
inline difference_type operator - ( iterator_impl const & other ) const { return base_ - other . base_ ; }
inline bool operator = = ( iterator_impl const & other ) const { return base_ = = other . base_ ; }
inline bool operator ! = ( iterator_impl const & other ) const { return ! ( * this = = other ) ; }
inline bool operator < ( iterator_impl const & other ) const { return base_ < other . base_ ; }
inline bool operator < = ( iterator_impl const & other ) const { return base_ < = other . base_ ; }
inline bool operator > ( iterator_impl const & other ) const { return base_ > other . base_ ; }
inline bool operator > = ( iterator_impl const & other ) const { return base_ > = other . base_ ; }
inline reference operator [ ] ( difference_type off ) { return * ( base_ + off ) ; }
inline const reference operator [ ] ( difference_type off ) const { return * ( base_ + off ) ; }
inline operator bool ( ) const { return base_ ! = nullptr ; }
private :
pointer base_ { nullptr } ;
} ;
public :
2019-08-02 13:57:17 +08:00
using value_type = _CharTy ;
using char_type = value_type ;
2019-03-31 01:37:06 +08:00
using size_type = size_t ;
using reference = value_type & ;
using const_reference = const value_type & ;
using iterator = iterator_impl < value_type > ;
using const_iterator = iterator_impl < const value_type > ;
using reverse_iterator = std : : reverse_iterator < iterator > ;
using const_reverse_iterator = std : : reverse_iterator < const_iterator > ;
2019-08-02 16:07:01 +08:00
using traits_type = std : : char_traits < value_type > ;
using allocator_type = std : : allocator < value_type > ;
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
basic_string ( ) ;
basic_string ( const char_type * cstr , bool const_str = true ) ;
basic_string ( const char_type * cstr , size_type count ) ;
basic_string ( size_type count , char_type ch ) ;
basic_string ( std : : basic_string < char_type > const & str ) ;
basic_string ( basic_string const & rhs ) ;
basic_string ( basic_string const & rhs , size_type pos , size_type count = npos ) ;
basic_string ( basic_string & & rhs ) noexcept ;
~ basic_string ( ) ;
2019-03-31 01:37:06 +08:00
template < typename _Iter >
2019-08-02 13:57:17 +08:00
basic_string ( _Iter first , _Iter last ) : basic_string ( ) { assign_iter ( first , last ) ; }
inline const char_type * c_str ( ) const { return empty ( ) ? empty_cstr : const_str_ ; }
inline const char_type * data ( ) const { return empty ( ) ? empty_cstr : const_str_ ; }
inline char_type at ( size_t i ) const { return ( * this ) [ i ] ; }
inline size_type size ( ) const { return size_ ; }
inline size_type length ( ) const { return size ( ) ; }
inline size_type capacity ( ) const { return capacity_ ; }
inline size_type max_size ( ) const { return ( static_cast < size_type > ( - 1 ) / sizeof ( value_type ) ) ; }
inline bool empty ( ) const { return size_ = = 0 ; }
inline void clear ( ) { discard_const_data ( ) ; if ( str_ ) { str_ [ 0 ] = value_type ( ) ; } size_ = 0 ; }
2019-03-31 01:37:06 +08:00
void reserve ( const size_type new_cap = 0 ) ;
2019-08-02 13:57:17 +08:00
inline void resize ( const size_type new_size , const char_type ch = value_type ( ) ) { check_operability ( ) ; if ( new_size < size_ ) str_ [ size_ = new_size ] = value_type ( ) ; else append ( new_size - size_ , ch ) ; }
int compare ( const char_type * const str ) const ;
inline int compare ( basic_string const & str ) const { return compare ( str . c_str ( ) ) ; }
basic_string & append ( size_type count , char_type ch ) ;
basic_string & append ( const char_type * cstr , size_type count ) ;
basic_string & append ( basic_string const & other , size_type pos , size_type count = npos ) ;
2019-08-02 16:07:01 +08:00
inline basic_string & append ( const char_type * cstr ) { return append ( cstr , traits_type : : length ( cstr ) ) ; }
2019-08-02 13:57:17 +08:00
inline basic_string & append ( basic_string const & other ) { return append ( other . const_str_ , 0 , npos ) ; }
inline basic_string & append ( std : : basic_string < char_type > const & other ) { return append ( other . c_str ( ) ) ; }
size_type find ( const char_type ch , size_type offset = 0 ) const ;
size_type find ( const char_type * const str , size_type offset , size_type count ) const ;
inline size_type find ( basic_string const & str , size_type offset = 0 ) const { return find ( str . c_str ( ) , offset , str . size ( ) ) ; }
2019-08-02 16:07:01 +08:00
inline size_type find ( const char_type * const str , size_type offset = 0 ) const { return find ( str , offset , traits_type : : length ( str ) ) ; }
2019-08-02 13:57:17 +08:00
size_type find_first_of ( const char_type * const str , size_type offset , size_type count ) const ;
inline size_type find_first_of ( const char_type ch , size_type offset = 0 ) const { return find ( ch , offset ) ; }
inline size_type find_first_of ( basic_string const & str , size_type offset = 0 ) const { return find_first_of ( str . c_str ( ) , offset , str . size ( ) ) ; }
2019-08-02 16:07:01 +08:00
inline size_type find_first_of ( const char_type * const str , size_type offset = 0 ) const { return find_first_of ( str , offset , traits_type : : length ( str ) ) ; }
2019-08-02 13:57:17 +08:00
size_type find_last_of ( const char_type ch , size_type pos = npos ) const ;
size_type find_last_of ( const char_type * const str , size_type pos , size_type count ) const ;
inline size_type find_last_of ( basic_string const & str , size_type pos = npos ) const { return find_first_of ( str . c_str ( ) , pos , str . size ( ) ) ; }
2019-08-02 16:07:01 +08:00
inline size_type find_last_of ( const char_type * const str , size_type pos = npos ) const { return find_first_of ( str , pos , traits_type : : length ( str ) ) ; }
2019-08-02 13:57:17 +08:00
basic_string & replace ( size_type pos , size_type count , const char_type * cstr , size_type count2 ) ;
basic_string & replace ( size_type pos , size_type count , size_type count2 , const char_type ch ) ;
inline basic_string & replace ( size_type pos , size_type count , const basic_string & str ) { return replace ( pos , count , str . c_str ( ) , str . size ( ) ) ; }
2019-08-02 16:07:01 +08:00
inline basic_string & replace ( size_type pos , size_type count , const char_type * cstr ) { return replace ( pos , count , cstr , traits_type : : length ( cstr ) ) ; }
2019-08-02 13:57:17 +08:00
inline basic_string & replace ( const_iterator first , const_iterator last , const basic_string & str ) { return replace ( first , last , str . c_str ( ) , str . size ( ) ) ; }
2019-08-02 16:07:01 +08:00
inline basic_string & replace ( const_iterator first , const_iterator last , const char_type * cstr ) { return replace ( first , last , cstr , traits_type : : length ( cstr ) ) ; }
2019-08-02 13:57:17 +08:00
inline basic_string & replace ( const_iterator first , const_iterator last , const char_type * cstr , size_type count ) { return replace ( first - cbegin ( ) , last - first , cstr , count ) ; }
inline basic_string & replace ( const_iterator first , const_iterator last , size_type count2 , const char_type ch ) { return replace ( first - cbegin ( ) , last - first , count2 , ch ) ; }
basic_string & assign ( size_type count , const char_type ch ) ;
basic_string & assign ( const char_type * cstr , size_type count ) ;
2019-08-04 16:18:35 +08:00
inline basic_string & assign ( const char_type * cstr ) { basic_string ( cstr , false ) . swap ( * this ) ; return * this ; }
2019-08-02 13:57:17 +08:00
inline basic_string & assign ( basic_string const & rhs ) { basic_string { rhs } . swap ( * this ) ; return * this ; }
inline basic_string & assign ( std : : basic_string < char_type > const & rhs ) { basic_string { rhs } . swap ( * this ) ; return * this ; }
basic_string & assign ( basic_string const & rhs , size_type pos , size_type count = npos ) ;
2019-03-31 01:37:06 +08:00
template < typename _Iter >
2019-08-02 13:57:17 +08:00
inline basic_string & assign ( _Iter first , _Iter last ) { assign_iter ( first , last ) ; return ( * this ) ; }
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
basic_string & erase ( size_type offset = 0 , size_type count = npos ) ;
iterator erase ( const const_iterator where ) { size_type off = where - cbegin ( ) ; erase ( off , 1 ) ; return begin ( ) . base ( ) + off ; }
iterator erase ( const const_iterator first , const const_iterator last ) { size_type off = first - cbegin ( ) ; erase ( first - cbegin ( ) , last - first ) ; return begin ( ) . base ( ) + off ; }
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
basic_string substr ( size_type pos = 0 , size_type count = npos ) const { return basic_string ( * this , pos , count ) ; }
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
basic_string & insert ( size_type index , size_type count , char_type ch ) ;
basic_string & insert ( size_type index , const char_type * s , size_type count ) ;
basic_string & insert ( size_type index , const basic_string & str , size_type off , size_type count = npos ) ;
2019-08-02 16:07:01 +08:00
inline basic_string & insert ( size_type index , const char_type * s ) { return insert ( index , s , traits_type : : length ( s ) ) ; }
2019-08-02 13:57:17 +08:00
inline basic_string & insert ( size_type index , const basic_string & str ) { return insert ( index , str , 0 , str . size ( ) ) ; }
inline iterator insert ( const_iterator pos , size_type count , char_type ch ) { size_type off = pos - cbegin ( ) ; insert ( off , count , ch ) ; return begin ( ) . base ( ) + off ; }
inline iterator insert ( const_iterator pos , char_type ch ) { return insert ( pos , 1 , ch ) ; }
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
inline void push_back ( const char_type ch ) { append ( 1 , ch ) ; }
inline char_type pop_back ( ) { if ( empty ( ) ) throw std : : out_of_range ( " pop_back() called on empty string " ) ; check_operability ( ) ; char_type ch = str_ [ - - size_ ] ; str_ [ size_ ] = value_type ( ) ; return ch ; }
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
size_type copy ( char_type * cstr , size_type count , size_type pos = 0 ) const ;
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
void swap ( basic_string & rhs ) noexcept ;
2019-03-31 01:37:06 +08:00
size_t hash ( ) const ;
public :
2019-08-02 13:57:17 +08:00
static basic_string parse ( int val ) ;
static basic_string parse ( unsigned int val ) ;
static basic_string parse ( long val ) ;
static basic_string parse ( unsigned long val ) ;
static basic_string parse ( long long val ) ;
static basic_string parse ( unsigned long long val ) ;
static basic_string parse ( float val ) ;
static basic_string parse ( double val ) ;
static basic_string parse ( long double val ) ;
template < typename . . . _Args >
static basic_string format ( const char_type * fmt , _Args & & . . . args ) ;
2019-03-31 01:37:06 +08:00
2019-08-04 16:18:35 +08:00
static inline basic_string cstr ( const char_type * cstr ) { return basic_string ( cstr , false ) ; }
2019-03-31 01:37:06 +08:00
public :
inline iterator begin ( ) { check_operability ( ) ; return iterator ( str_ ) ; }
inline const_iterator begin ( ) const { return const_iterator ( const_str_ ) ; }
inline const_iterator cbegin ( ) const { return begin ( ) ; }
inline iterator end ( ) { check_operability ( ) ; return iterator ( str_ + size_ ) ; }
inline const_iterator end ( ) const { return const_iterator ( const_str_ + size_ ) ; }
inline const_iterator cend ( ) const { return end ( ) ; }
inline reverse_iterator rbegin ( ) { check_operability ( ) ; return reverse_iterator ( end ( ) ) ; }
inline const_reverse_iterator rbegin ( ) const { return const_reverse_iterator ( end ( ) ) ; }
inline const_reverse_iterator crbegin ( ) const { return rbegin ( ) ; }
inline reverse_iterator rend ( ) { check_operability ( ) ; return reverse_iterator ( begin ( ) ) ; }
inline const_reverse_iterator rend ( ) const { return const_reverse_iterator ( begin ( ) ) ; }
inline const_reverse_iterator crend ( ) const { return rend ( ) ; }
inline reference front ( ) { if ( empty ( ) ) throw std : : out_of_range ( " front() called on empty string " ) ; check_operability ( ) ; return str_ [ 0 ] ; }
inline const_reference front ( ) const { if ( empty ( ) ) throw std : : out_of_range ( " front() called on empty string " ) ; return const_str_ [ 0 ] ; }
inline reference back ( ) { if ( empty ( ) ) throw std : : out_of_range ( " back() called on empty string " ) ; check_operability ( ) ; return str_ [ size_ - 1 ] ; }
inline const_reference back ( ) const { if ( empty ( ) ) throw std : : out_of_range ( " back() called on empty string " ) ; return const_str_ [ size_ - 1 ] ; }
public :
2019-08-04 16:18:35 +08:00
inline char_type operator [ ] ( size_type off ) const { if ( off > = size_ ) throw std : : out_of_range ( " string subscript out of range " ) ; return const_str_ [ off ] ; }
2019-08-02 13:57:17 +08:00
inline char_type & operator [ ] ( size_type off ) { if ( off > = size_ ) throw std : : out_of_range ( " string subscript out of range " ) ; check_operability ( ) ; return str_ [ off ] ; }
2019-03-31 01:37:06 +08:00
public :
2019-08-02 13:57:17 +08:00
inline const basic_string operator + ( const char_type ch ) const { return basic_string { * this } . append ( 1 , ch ) ; }
inline const basic_string operator + ( const char_type * cstr ) const { return basic_string { * this } . append ( cstr ) ; }
inline const basic_string operator + ( basic_string const & rhs ) const { return basic_string { * this } . append ( rhs ) ; }
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
inline basic_string & operator + = ( const char_type ch ) { return append ( 1 , ch ) ; }
inline basic_string & operator + = ( const char_type * cstr ) { return append ( cstr ) ; }
inline basic_string & operator + = ( basic_string const & rhs ) { return append ( rhs ) ; }
2019-03-31 01:37:06 +08:00
public :
2019-08-02 13:57:17 +08:00
inline basic_string & operator = ( const char_type * cstr ) { if ( const_str_ ! = cstr ) basic_string { cstr } . swap ( * this ) ; return * this ; }
inline basic_string & operator = ( std : : basic_string < char_type > const & rhs ) { basic_string { rhs } . swap ( * this ) ; return * this ; }
inline basic_string & operator = ( basic_string const & rhs ) { if ( this ! = & rhs ) basic_string { rhs } . swap ( * this ) ; return * this ; }
inline basic_string & operator = ( basic_string & & rhs ) noexcept { if ( this ! = & rhs ) basic_string { rhs } . swap ( * this ) ; return * this ; }
2019-03-31 01:37:06 +08:00
public :
2019-08-02 13:57:17 +08:00
static const size_type npos ;
static const char_type empty_cstr [ 1 ] ;
2019-03-31 01:37:06 +08:00
2019-08-02 16:07:01 +08:00
static inline allocator_type & get_allocator ( )
2019-03-31 01:37:06 +08:00
{
2019-08-02 16:07:01 +08:00
static allocator_type allocator_ ;
2019-03-31 01:37:06 +08:00
return allocator_ ;
}
private :
2019-08-02 13:57:17 +08:00
char_type * allocate ( size_type count ) ;
void deallocate ( char_type * & ptr , size_type count ) ;
2019-03-31 01:37:06 +08:00
void destroy ( ) ;
void discard_const_data ( ) ;
void check_operability ( ) ;
void check_offset ( size_type offset ) const { if ( offset > size ( ) ) throw std : : out_of_range ( " invalid string position " ) ; }
size_type clamp_suffix_size ( size_type off , size_type count ) const { return std : : min ( size ( ) - off , count ) ; }
template < typename _Iter >
void assign_iter ( _Iter first , _Iter last )
{
size_type diff = static_cast < size_type > ( std : : distance ( first , last ) ) ;
if ( diff = = 0 )
return ;
discard_const_data ( ) ;
if ( diff > capacity_ )
{
destroy ( ) ;
str_ = allocate ( diff + 1 ) ;
capacity_ = diff ;
}
size_ = diff ;
for ( size_type index = 0 ; first ! = last ; + + first , + + index )
{
2019-08-02 16:07:01 +08:00
traits_type : : assign ( str_ [ index ] , traits_type : : to_char_type ( * first ) ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 16:07:01 +08:00
traits_type : : assign ( str_ [ size_ ] , value_type ( ) ) ;
2019-03-31 01:37:06 +08:00
}
private :
union
{
struct
{
value_type * str_ ;
} ;
struct
{
const value_type * const_str_ ;
} ;
} ;
size_type size_ ;
size_type capacity_ ;
const bool operable_ ;
} ;
2019-08-02 13:57:17 +08:00
// static members
template < typename _CharTy >
const typename basic_string < _CharTy > : : size_type basic_string < _CharTy > : : npos = static_cast < typename basic_string < _CharTy > : : size_type > ( - 1 ) ;
template < typename _CharTy >
const typename basic_string < _CharTy > : : char_type basic_string < _CharTy > : : empty_cstr [ 1 ] = { 0 } ;
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
// operator== for basic_string
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
2019-08-02 16:07:01 +08:00
inline bool operator = = ( basic_string < _CharTy > const & lhs , basic_string < _CharTy > const & rhs ) { return lhs . compare ( rhs ) = = 0 ; }
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline bool operator = = ( const typename basic_string < _CharTy > : : char_type * lhs , basic_string < _CharTy > const & rhs ) { return rhs . compare ( lhs ) = = 0 ; }
template < typename _CharTy >
inline bool operator = = ( basic_string < _CharTy > const & lhs , const typename basic_string < _CharTy > : : char_type * rhs ) { return lhs . compare ( rhs ) = = 0 ; }
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
// operator!= for basic_string
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
2019-08-02 16:07:01 +08:00
inline bool operator ! = ( basic_string < _CharTy > const & lhs , basic_string < _CharTy > const & rhs ) { return lhs . compare ( rhs ) ! = 0 ; }
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline bool operator ! = ( const typename basic_string < _CharTy > : : char_type * lhs , basic_string < _CharTy > const & rhs ) { return rhs . compare ( lhs ) ! = 0 ; }
template < typename _CharTy >
inline bool operator ! = ( basic_string < _CharTy > const & lhs , const typename basic_string < _CharTy > : : char_type * rhs ) { return lhs . compare ( rhs ) ! = 0 ; }
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
// operator+ for basic_string
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
2019-08-02 16:07:01 +08:00
inline basic_string < _CharTy > operator + ( const typename basic_string < _CharTy > : : char_type * lhs , basic_string < _CharTy > const & rhs ) { return basic_string < _CharTy > { lhs } + rhs ; }
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
// operator<> for basic_string
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline bool operator < ( basic_string < _CharTy > const & lhs , basic_string < _CharTy > const & rhs ) { return lhs . compare ( rhs ) < 0 ; }
template < typename _CharTy >
inline bool operator > ( basic_string < _CharTy > const & lhs , basic_string < _CharTy > const & rhs ) { return lhs . compare ( rhs ) > 0 ; }
template < typename _CharTy >
2019-08-02 16:07:01 +08:00
inline bool operator < = ( basic_string < _CharTy > const & lhs , basic_string < _CharTy > const & rhs ) { return lhs . compare ( rhs ) < = 0 ; }
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
2019-08-02 16:07:01 +08:00
inline bool operator > = ( basic_string < _CharTy > const & lhs , basic_string < _CharTy > const & rhs ) { return lhs . compare ( rhs ) > = 0 ; }
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
// operator<<>> for basic_string
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
std : : basic_ostream < typename basic_string < _CharTy > : : char_type > & operator < < ( std : : basic_ostream < typename basic_string < _CharTy > : : char_type > & os , const basic_string < _CharTy > & str ) ;
template < typename _CharTy >
std : : basic_istream < typename basic_string < _CharTy > : : char_type > & operator > > ( std : : basic_istream < typename basic_string < _CharTy > : : char_type > & is , basic_string < _CharTy > & str ) ;
2019-04-09 02:25:17 +08:00
2019-03-31 01:37:06 +08:00
//
// to_string functions
//
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
basic_string < _CharTy > to_basic_string ( int val ) ;
template < typename _CharTy >
basic_string < _CharTy > to_basic_string ( unsigned int val ) ;
template < typename _CharTy >
basic_string < _CharTy > to_basic_string ( long val ) ;
template < typename _CharTy >
basic_string < _CharTy > to_basic_string ( unsigned long val ) ;
template < typename _CharTy >
basic_string < _CharTy > to_basic_string ( long long val ) ;
template < typename _CharTy >
basic_string < _CharTy > to_basic_string ( unsigned long long val ) ;
template < typename _CharTy >
basic_string < _CharTy > to_basic_string ( float val ) ;
template < typename _CharTy >
basic_string < _CharTy > to_basic_string ( double val ) ;
template < typename _CharTy >
basic_string < _CharTy > to_basic_string ( long double val ) ;
2019-03-31 01:37:06 +08:00
//
// format_wstring
//
2019-08-02 13:57:17 +08:00
template < typename . . . _Args >
basic_string < char > format_string ( const char * const fmt , _Args & & . . . args ) ;
template < typename . . . _Args >
basic_string < wchar_t > format_string ( const wchar_t * const fmt , _Args & & . . . args ) ;
2019-03-31 01:37:06 +08:00
}
2019-04-11 14:40:54 +08:00
namespace kiwano
2019-03-31 01:37:06 +08:00
{
//
2019-08-02 13:57:17 +08:00
// details of basic_string
2019-03-31 01:37:06 +08:00
//
namespace __string_details
{
template < class _Traits >
size_t TraitsFind (
const typename _Traits : : char_type * first , size_t first_size , size_t offset ,
const typename _Traits : : char_type * second , size_t count )
{
if ( count > first_size | | offset > first_size - count )
{
return static_cast < size_t > ( - 1 ) ;
}
if ( count = = 0 )
{
return offset ;
}
const auto matches_end = first + ( first_size - count ) + 1 ;
for ( auto iter = first + offset ; ; + + iter )
{
iter = typename _Traits : : find ( iter , static_cast < size_t > ( matches_end - iter ) , * second ) ;
if ( ! iter )
{
return static_cast < size_t > ( - 1 ) ;
}
if ( typename _Traits : : compare ( iter , second , count ) = = 0 )
{
return static_cast < size_t > ( iter - first ) ;
}
}
}
template < class _Traits >
size_t TraitsFindLastOf (
const typename _Traits : : char_type * first , const size_t first_size , const size_t pos ,
const typename _Traits : : char_type * second , const size_t count )
{
if ( count ! = 0 & & first_size ! = 0 )
{
for ( auto iter = first + std : : min ( pos , first_size - 1 ) ; ; - - iter )
{
if ( typename _Traits : : find ( second , count , * iter ) )
{
return static_cast < size_t > ( iter - first ) ;
}
if ( iter = = first )
{
break ;
}
}
}
return static_cast < size_t > ( - 1 ) ;
}
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > : : basic_string ( )
2019-03-31 01:37:06 +08:00
: str_ ( nullptr )
, size_ ( 0 )
, capacity_ ( 0 )
, operable_ ( true )
{
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > : : basic_string ( const char_type * cstr , bool const_str )
2019-03-31 01:37:06 +08:00
: operable_ ( ! const_str )
, size_ ( 0 )
, capacity_ ( 0 )
, str_ ( nullptr )
{
if ( cstr = = nullptr )
return ;
if ( operable_ )
{
2019-08-02 16:07:01 +08:00
assign ( cstr , traits_type : : length ( cstr ) ) ;
2019-03-31 01:37:06 +08:00
}
else
{
const_str_ = cstr ;
2019-08-02 16:07:01 +08:00
size_ = traits_type : : length ( cstr ) ;
2019-03-31 01:37:06 +08:00
capacity_ = size_ ;
}
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > : : basic_string ( const char_type * cstr , size_type count )
: basic_string ( )
2019-03-31 01:37:06 +08:00
{
assign ( cstr , count ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > : : basic_string ( size_type count , char_type ch )
: basic_string ( )
2019-03-31 01:37:06 +08:00
{
assign ( count , ch ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > : : basic_string ( basic_string const & rhs )
: basic_string ( rhs . const_str_ , ! rhs . operable_ )
2019-03-31 01:37:06 +08:00
{
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > : : basic_string ( basic_string const & rhs , size_type pos , size_type count )
: basic_string ( )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
assign ( rhs , pos , count ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > : : basic_string ( std : : basic_string < char_type > const & str )
2019-08-02 16:07:01 +08:00
: basic_string ( str . c_str ( ) , false )
2019-03-31 01:37:06 +08:00
{
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > : : basic_string ( basic_string & & rhs ) noexcept
2019-04-04 14:25:13 +08:00
: str_ ( rhs . str_ )
, size_ ( rhs . size_ )
, capacity_ ( rhs . capacity_ )
, operable_ ( rhs . operable_ )
2019-03-31 01:37:06 +08:00
{
2019-04-04 14:25:13 +08:00
rhs . str_ = nullptr ;
rhs . size_ = rhs . capacity_ = 0 ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > : : ~ basic_string ( )
2019-03-31 01:37:06 +08:00
{
destroy ( ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : assign ( size_type count , const char_type ch )
2019-03-31 01:37:06 +08:00
{
discard_const_data ( ) ;
if ( count ! = 0 )
{
if ( count > capacity_ )
{
destroy ( ) ;
str_ = allocate ( count + 1 ) ;
capacity_ = count ;
}
size_ = count ;
2019-08-02 16:07:01 +08:00
traits_type : : assign ( str_ , size_ , ch ) ;
traits_type : : assign ( str_ [ size_ ] , value_type ( ) ) ;
2019-03-31 01:37:06 +08:00
}
else
{
clear ( ) ;
}
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : assign ( const char_type * cstr , size_type count )
2019-03-31 01:37:06 +08:00
{
discard_const_data ( ) ;
2019-03-31 13:56:05 +08:00
if ( cstr & & count )
2019-03-31 01:37:06 +08:00
{
if ( count > capacity_ )
{
destroy ( ) ;
str_ = allocate ( count + 1 ) ;
capacity_ = count ;
}
size_ = count ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( str_ , cstr , size_ ) ;
traits_type : : assign ( str_ [ size_ ] , value_type ( ) ) ;
2019-03-31 01:37:06 +08:00
}
else
{
clear ( ) ;
}
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : assign ( basic_string const & rhs , size_type pos , size_type count )
2019-04-05 16:06:32 +08:00
{
if ( count = = 0 | | pos > rhs . size ( ) )
{
clear ( ) ;
return ( * this ) ;
}
discard_const_data ( ) ;
count = rhs . clamp_suffix_size ( pos , count ) ;
if ( count > capacity_ )
{
destroy ( ) ;
str_ = allocate ( count + 1 ) ;
capacity_ = count ;
}
size_ = count ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( str_ , rhs . begin ( ) . base ( ) + pos , size_ ) ;
traits_type : : assign ( str_ [ size_ ] , value_type ( ) ) ;
2019-04-05 16:06:32 +08:00
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : erase ( size_type offset , size_type count )
2019-03-31 01:37:06 +08:00
{
if ( count = = 0 )
return ( * this ) ;
check_offset ( offset ) ;
check_operability ( ) ;
count = clamp_suffix_size ( offset , count ) ;
if ( count = = 0 )
{
clear ( ) ;
return ( * this ) ;
}
size_type new_size = size_ - count ;
iterator erase_at = begin ( ) . base ( ) + offset ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( erase_at . base ( ) , erase_at . base ( ) + count , new_size - offset + 1 ) ;
2019-03-31 01:37:06 +08:00
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : insert ( size_type index , size_type count , char_type ch )
2019-03-31 01:37:06 +08:00
{
if ( count = = 0 )
return ( * this ) ;
if ( index > = size ( ) )
return append ( count , ch ) ;
check_operability ( ) ;
2019-08-02 13:57:17 +08:00
char_type * const old_ptr = str_ ;
2019-03-31 01:37:06 +08:00
const size_type old_size = size_ ;
const size_type old_capacity = capacity_ ;
const size_type suffix_size = old_size - index + 1 ;
size_ = old_size + count ;
if ( size_ > old_capacity )
{
capacity_ = size_ ;
2019-08-02 13:57:17 +08:00
char_type * new_ptr = allocate ( capacity_ + 1 ) ;
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
char_type * const insert_at = new_ptr + index ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( new_ptr , old_ptr , index ) ; // (0) - (index)
traits_type : : assign ( insert_at , count , ch ) ; // (index) - (index + count)
traits_type : : move ( insert_at + count , old_ptr + index , suffix_size ) ; // (index + count) - (old_size - index)
2019-03-31 01:37:06 +08:00
deallocate ( str_ , old_capacity + 1 ) ;
str_ = new_ptr ;
}
else
{
2019-08-02 13:57:17 +08:00
char_type * const insert_at = old_ptr + index ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( insert_at + count , old_ptr + index , suffix_size ) ;
traits_type : : assign ( insert_at , count , ch ) ;
2019-03-31 01:37:06 +08:00
}
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : insert ( size_type index , const char_type * cstr , size_type count )
2019-03-31 01:37:06 +08:00
{
if ( count = = 0 )
return ( * this ) ;
if ( index > = size ( ) )
return append ( cstr , count ) ;
check_operability ( ) ;
2019-08-02 13:57:17 +08:00
char_type * const old_ptr = str_ ;
2019-03-31 01:37:06 +08:00
const size_type old_size = size_ ;
const size_type old_capacity = capacity_ ;
const size_type suffix_size = old_size - index + 1 ;
size_ = old_size + count ;
if ( size_ > old_capacity )
{
capacity_ = size_ ;
2019-08-02 13:57:17 +08:00
char_type * new_ptr = allocate ( capacity_ + 1 ) ;
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
char_type * const insert_at = new_ptr + index ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( new_ptr , old_ptr , index ) ; // (0) - (index)
traits_type : : move ( insert_at , cstr , count ) ; // (index) - (index + count)
traits_type : : move ( insert_at + count , old_ptr + index , suffix_size ) ; // (index + count) - (old_size - index)
2019-03-31 01:37:06 +08:00
deallocate ( str_ , old_capacity + 1 ) ;
str_ = new_ptr ;
}
else
{
2019-08-02 13:57:17 +08:00
char_type * const insert_at = old_ptr + index ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( insert_at + count , old_ptr + index , suffix_size ) ;
traits_type : : move ( insert_at , cstr , count ) ;
2019-03-31 01:37:06 +08:00
}
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : insert ( size_type index , const basic_string & str , size_type off , size_type count )
2019-03-31 01:37:06 +08:00
{
if ( count = = 0 | | off > str . size ( ) )
return ( * this ) ;
if ( index > = size ( ) )
return append ( str , off , count ) ;
check_operability ( ) ;
count = clamp_suffix_size ( off , count ) ;
2019-08-02 13:57:17 +08:00
char_type * const old_ptr = str_ ;
2019-03-31 01:37:06 +08:00
const size_type old_size = size_ ;
const size_type old_capacity = capacity_ ;
const size_type suffix_size = old_size - index + 1 ;
size_ = old_size + count ;
if ( size_ > old_capacity )
{
capacity_ = size_ ;
2019-08-02 13:57:17 +08:00
char_type * new_ptr = allocate ( capacity_ + 1 ) ;
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
char_type * const insert_at = new_ptr + index ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( new_ptr , old_ptr , index ) ; // (0) - (index)
traits_type : : move ( insert_at , str . begin ( ) . base ( ) + off , count ) ; // (index) - (index + count)
traits_type : : move ( insert_at + count , old_ptr + index , suffix_size ) ; // (index + count) - (old_size - index)
2019-03-31 01:37:06 +08:00
deallocate ( str_ , old_capacity + 1 ) ;
str_ = new_ptr ;
}
else
{
2019-08-02 13:57:17 +08:00
char_type * const insert_at = old_ptr + index ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( insert_at + count , old_ptr + index , suffix_size ) ;
traits_type : : move ( insert_at , str . begin ( ) . base ( ) + off , count ) ;
2019-03-31 01:37:06 +08:00
}
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : append ( size_type count , char_type ch )
2019-03-31 01:37:06 +08:00
{
check_operability ( ) ;
size_t new_size = size_ + count ;
size_t new_cap = new_size + 1 ;
2019-08-02 13:57:17 +08:00
char_type * new_str = allocate ( new_cap ) ;
2019-03-31 01:37:06 +08:00
2019-08-02 16:07:01 +08:00
traits_type : : move ( new_str , str_ , size_ ) ;
traits_type : : assign ( new_str + size_ , count , ch ) ;
traits_type : : assign ( new_str [ new_size ] , value_type ( ) ) ;
2019-03-31 01:37:06 +08:00
destroy ( ) ;
str_ = new_str ;
size_ = new_size ;
capacity_ = new_cap ;
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : append ( const char_type * cstr , size_type count )
2019-03-31 01:37:06 +08:00
{
check_operability ( ) ;
size_t new_size = size_ + count ;
size_t new_cap = new_size + 1 ;
2019-08-02 13:57:17 +08:00
char_type * new_str = allocate ( new_cap ) ;
2019-03-31 01:37:06 +08:00
2019-08-02 16:07:01 +08:00
traits_type : : move ( new_str , str_ , size_ ) ;
traits_type : : move ( new_str + size_ , cstr , count ) ;
traits_type : : assign ( new_str [ new_size ] , value_type ( ) ) ;
2019-03-31 01:37:06 +08:00
destroy ( ) ;
str_ = new_str ;
size_ = new_size ;
capacity_ = new_cap ;
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : append ( basic_string const & other , size_type pos , size_type count )
2019-03-31 01:37:06 +08:00
{
check_operability ( ) ;
if ( pos > = other . size ( ) )
return ( * this ) ;
count = other . clamp_suffix_size ( pos , count ) ;
size_t new_size = size_ + count ;
size_t new_cap = new_size + 1 ;
2019-08-02 13:57:17 +08:00
char_type * new_str = allocate ( new_cap ) ;
2019-03-31 01:37:06 +08:00
2019-08-02 16:07:01 +08:00
traits_type : : move ( new_str , str_ , size_ ) ;
traits_type : : move ( new_str + size_ , other . begin ( ) . base ( ) + pos , count ) ;
traits_type : : assign ( new_str [ new_size ] , value_type ( ) ) ;
2019-03-31 01:37:06 +08:00
destroy ( ) ;
str_ = new_str ;
size_ = new_size ;
capacity_ = new_cap ;
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline void basic_string < _CharTy > : : reserve ( const size_type new_cap )
2019-03-31 01:37:06 +08:00
{
if ( new_cap < = capacity_ )
return ;
check_operability ( ) ;
2019-08-02 13:57:17 +08:00
char_type * new_str = allocate ( new_cap ) ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( new_str , str_ , capacity_ ) ;
2019-03-31 01:37:06 +08:00
destroy ( ) ;
str_ = new_str ;
capacity_ = new_cap ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline size_t basic_string < _CharTy > : : hash ( ) const
2019-03-31 01:37:06 +08:00
{
static size_t fnv_prime = 16777619U ;
size_t fnv_offset_basis = 2166136261U ;
for ( size_t index = 0 ; index < size_ ; + + index )
{
fnv_offset_basis ^ = static_cast < size_t > ( const_str_ [ index ] ) ;
fnv_offset_basis * = fnv_prime ;
}
return fnv_offset_basis ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline int basic_string < _CharTy > : : compare ( const char_type * const str ) const
2019-03-31 01:37:06 +08:00
{
size_type count1 = size ( ) ;
2019-08-02 16:07:01 +08:00
size_type count2 = traits_type : : length ( str ) ;
2019-03-31 01:37:06 +08:00
size_type rlen = std : : min ( count1 , count2 ) ;
2019-08-02 16:07:01 +08:00
int ret = traits_type : : compare ( const_str_ , str , rlen ) ;
2019-03-31 01:37:06 +08:00
if ( ret ! = 0 )
return ret ;
if ( count1 < count2 )
return - 1 ;
if ( count1 > count2 )
return 1 ;
return 0 ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline typename basic_string < _CharTy > : : size_type basic_string < _CharTy > : : find ( const char_type ch , size_type offset ) const
2019-03-31 01:37:06 +08:00
{
if ( offset > = size_ )
2019-08-02 13:57:17 +08:00
return basic_string < _CharTy > : : npos ;
2019-03-31 01:37:06 +08:00
2019-08-02 16:07:01 +08:00
const_iterator citer = traits_type : : find ( cbegin ( ) . base ( ) + offset , size_ , ch ) ;
2019-08-02 13:57:17 +08:00
return citer ? ( citer - cbegin ( ) ) : basic_string < _CharTy > : : npos ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline typename basic_string < _CharTy > : : size_type basic_string < _CharTy > : : find ( const char_type * const str , size_type offset , size_type count ) const
2019-03-31 01:37:06 +08:00
{
if ( offset > = size_ )
2019-08-02 13:57:17 +08:00
return basic_string < _CharTy > : : npos ;
2019-08-02 16:07:01 +08:00
return __string_details : : TraitsFind < typename basic_string < _CharTy > : : traits_type > ( const_str_ , size_ , offset , str , count ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline typename basic_string < _CharTy > : : size_type basic_string < _CharTy > : : find_first_of ( const char_type * const str , size_type offset , size_type count ) const
2019-03-31 01:37:06 +08:00
{
if ( offset > = size_ )
2019-08-02 13:57:17 +08:00
return basic_string < _CharTy > : : npos ;
2019-03-31 01:37:06 +08:00
const_iterator citer = std : : find_first_of ( cbegin ( ) . base ( ) + offset , cend ( ) . base ( ) , str , str + count ) ;
2019-08-02 13:57:17 +08:00
return ( citer ! = cend ( ) ) ? ( citer - cbegin ( ) ) : basic_string < _CharTy > : : npos ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline typename basic_string < _CharTy > : : size_type basic_string < _CharTy > : : find_last_of ( const char_type ch , size_type pos ) const
2019-03-31 01:37:06 +08:00
{
if ( pos = = 0 | | pos > size_ | | pos = = npos )
return npos ;
const_reverse_iterator criter = std : : find ( crbegin ( ) , crend ( ) , ch ) ;
2019-08-02 13:57:17 +08:00
return ( criter ! = crend ( ) ) ? ( criter . base ( ) - cbegin ( ) ) : basic_string < _CharTy > : : npos ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline typename basic_string < _CharTy > : : size_type basic_string < _CharTy > : : find_last_of ( const char_type * const str , size_type pos , size_type count ) const
2019-03-31 01:37:06 +08:00
{
if ( pos = = 0 | | pos > size_ | | pos = = npos )
return npos ;
2019-08-02 16:07:01 +08:00
return __string_details : : TraitsFindLastOf < typename basic_string < _CharTy > : : traits_type > ( const_str_ , size_ , pos , str , count ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : replace ( size_type pos , size_type count , const char_type * cstr , size_type count2 )
2019-03-31 01:37:06 +08:00
{
check_offset ( pos ) ;
check_operability ( ) ;
count = clamp_suffix_size ( pos , count ) ;
if ( count = = count2 )
{
2019-08-02 16:07:01 +08:00
traits_type : : move ( str_ + pos , cstr , count2 ) ;
2019-03-31 01:37:06 +08:00
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
char_type * new_ptr = nullptr ;
char_type * const old_ptr = str_ ;
2019-03-31 01:37:06 +08:00
const size_type old_size = size_ ;
const size_type old_capacity = capacity_ ;
const size_type suffix_size = old_size - count - pos + 1 ;
if ( count < count2 & & ( old_size + count2 - count ) > capacity_ )
{
const size_type growth = count2 - count ;
size_ = old_size + growth ;
capacity_ = size_ ;
new_ptr = allocate ( capacity_ + 1 ) ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( new_ptr , old_ptr , pos ) ;
2019-03-31 01:37:06 +08:00
}
else
{
size_ = old_size - ( count - count2 ) ;
}
2019-08-02 13:57:17 +08:00
char_type * const insert_at = ( new_ptr ? new_ptr : old_ptr ) + pos ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( insert_at , cstr , count2 ) ;
traits_type : : move ( insert_at + count2 , old_ptr + count , suffix_size ) ;
2019-03-31 01:37:06 +08:00
if ( new_ptr )
{
deallocate ( str_ , old_capacity + 1 ) ;
str_ = new_ptr ;
}
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > & basic_string < _CharTy > : : replace ( size_type pos , size_type count , size_type count2 , const char_type ch )
2019-03-31 01:37:06 +08:00
{
check_offset ( pos ) ;
check_operability ( ) ;
count = clamp_suffix_size ( pos , count ) ;
if ( count = = count2 )
{
2019-08-02 16:07:01 +08:00
traits_type : : assign ( str_ + pos , count2 , ch ) ;
2019-03-31 01:37:06 +08:00
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
char_type * new_ptr = nullptr ;
char_type * const old_ptr = str_ ;
2019-03-31 01:37:06 +08:00
const size_type old_size = size_ ;
const size_type old_capacity = capacity_ ;
const size_type suffix_size = old_size - count - pos + 1 ;
if ( count < count2 & & ( old_size + count2 - count ) > capacity_ )
{
const size_type growth = count2 - count ;
size_ = old_size + growth ;
capacity_ = size_ ;
new_ptr = allocate ( capacity_ + 1 ) ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( new_ptr , old_ptr , pos ) ;
2019-03-31 01:37:06 +08:00
}
else
{
size_ = old_size - ( count - count2 ) ;
}
2019-08-02 13:57:17 +08:00
char_type * const insert_at = ( new_ptr ? new_ptr : old_ptr ) + pos ;
2019-08-02 16:07:01 +08:00
traits_type : : assign ( insert_at , count2 , ch ) ;
traits_type : : move ( insert_at + count2 , old_ptr + count , suffix_size ) ;
2019-03-31 01:37:06 +08:00
if ( new_ptr )
{
deallocate ( str_ , old_capacity + 1 ) ;
str_ = new_ptr ;
}
return ( * this ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline typename basic_string < _CharTy > : : size_type basic_string < _CharTy > : : copy ( char_type * cstr , size_type count , size_type pos ) const
2019-03-31 01:37:06 +08:00
{
if ( count = = 0 | | cstr = = const_str_ )
return 0 ;
check_offset ( pos ) ;
count = clamp_suffix_size ( pos , count ) ;
2019-08-02 16:07:01 +08:00
traits_type : : move ( cstr , cbegin ( ) . base ( ) + pos , count ) ;
2019-03-31 01:37:06 +08:00
return count ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline typename basic_string < _CharTy > : : char_type * basic_string < _CharTy > : : allocate ( size_type count )
2019-03-31 01:37:06 +08:00
{
return get_allocator ( ) . allocate ( count ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline void basic_string < _CharTy > : : deallocate ( char_type * & ptr , size_type count )
2019-03-31 01:37:06 +08:00
{
get_allocator ( ) . deallocate ( ptr , count ) ;
ptr = nullptr ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline void basic_string < _CharTy > : : destroy ( )
2019-03-31 01:37:06 +08:00
{
if ( operable_ & & str_ )
{
deallocate ( str_ , capacity_ + 1 ) ;
}
else
{
const_str_ = nullptr ;
}
size_ = capacity_ = 0 ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline void basic_string < _CharTy > : : swap ( basic_string & rhs ) noexcept
2019-03-31 01:37:06 +08:00
{
std : : swap ( const_str_ , rhs . const_str_ ) ;
std : : swap ( size_ , rhs . size_ ) ;
std : : swap ( capacity_ , rhs . capacity_ ) ;
// swap const datas
std : : swap ( * const_cast < bool * > ( & operable_ ) , * const_cast < bool * > ( & rhs . operable_ ) ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline void basic_string < _CharTy > : : discard_const_data ( )
2019-03-31 01:37:06 +08:00
{
if ( ! operable_ )
{
// force to enable operability
* const_cast < bool * > ( & operable_ ) = true ;
const_str_ = nullptr ;
capacity_ = size_ = 0 ;
}
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline void basic_string < _CharTy > : : check_operability ( )
2019-03-31 01:37:06 +08:00
{
if ( ! operable_ )
{
// create a new string, then swap it with self
2019-08-02 13:57:17 +08:00
basic_string ( const_str_ , false ) . swap ( * this ) ;
2019-03-31 01:37:06 +08:00
}
}
//
2019-08-02 13:57:17 +08:00
// details of basic_string<>::parese
2019-03-31 01:37:06 +08:00
//
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > basic_string < _CharTy > : : parse ( int val ) { return : : kiwano : : to_basic_string < char_type > ( val ) ; }
template < typename _CharTy >
inline basic_string < _CharTy > basic_string < _CharTy > : : parse ( unsigned int val ) { return : : kiwano : : to_basic_string < char_type > ( val ) ; }
template < typename _CharTy >
inline basic_string < _CharTy > basic_string < _CharTy > : : parse ( long val ) { return : : kiwano : : to_basic_string < char_type > ( val ) ; }
template < typename _CharTy >
inline basic_string < _CharTy > basic_string < _CharTy > : : parse ( unsigned long val ) { return : : kiwano : : to_basic_string < char_type > ( val ) ; }
template < typename _CharTy >
inline basic_string < _CharTy > basic_string < _CharTy > : : parse ( long long val ) { return : : kiwano : : to_basic_string < char_type > ( val ) ; }
template < typename _CharTy >
inline basic_string < _CharTy > basic_string < _CharTy > : : parse ( unsigned long long val ) { return : : kiwano : : to_basic_string < char_type > ( val ) ; }
template < typename _CharTy >
inline basic_string < _CharTy > basic_string < _CharTy > : : parse ( float val ) { return : : kiwano : : to_basic_string < char_type > ( val ) ; }
template < typename _CharTy >
inline basic_string < _CharTy > basic_string < _CharTy > : : parse ( double val ) { return : : kiwano : : to_basic_string < char_type > ( val ) ; }
template < typename _CharTy >
inline basic_string < _CharTy > basic_string < _CharTy > : : parse ( long double val ) { return : : kiwano : : to_basic_string < char_type > ( val ) ; }
//
// details of basic_string::format
//
template < typename _CharTy >
template < typename . . . _Args >
inline basic_string < _CharTy > basic_string < _CharTy > : : format ( const char_type * fmt , _Args & & . . . args )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
return : : kiwano : : format_string ( fmt , std : : forward < _Args > ( args ) . . . ) ;
2019-03-31 01:37:06 +08:00
}
//
// details of operator<<>>
//
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline std : : basic_ostream < typename basic_string < _CharTy > : : char_type > & operator < < ( std : : basic_ostream < typename basic_string < _CharTy > : : char_type > & os , const basic_string < _CharTy > & str )
2019-03-31 01:37:06 +08:00
{
2019-08-02 16:07:01 +08:00
using ostream = std : : basic_ostream < typename basic_string < _CharTy > : : char_type , typename basic_string < _CharTy > : : traits_type > ;
2019-08-02 13:57:17 +08:00
using size_type = typename basic_string < _CharTy > : : size_type ;
2019-08-02 16:07:01 +08:00
using traits = typename basic_string < _CharTy > : : traits_type ;
2019-03-31 01:37:06 +08:00
const ostream : : sentry ok ( os ) ;
std : : ios_base : : iostate state = std : : ios_base : : goodbit ;
if ( ! ok )
{
state | = std : : ios_base : : badbit ;
}
else
{
const auto str_size = str . size ( ) ;
size_type pad = ( os . width ( ) < = 0 | | static_cast < size_type > ( os . width ( ) ) < = str_size ) ? 0 : static_cast < size_type > ( os . width ( ) ) - str_size ;
try
{
if ( ( os . flags ( ) & std : : ios_base : : adjustfield ) ! = std : : ios_base : : left )
{
for ( ; 0 < pad ; - - pad )
{
if ( traits : : eq_int_type ( traits : : eof ( ) , os . rdbuf ( ) - > sputc ( os . fill ( ) ) ) )
{
state | = std : : ios_base : : badbit ;
break ;
}
}
}
if ( state = = std : : ios_base : : goodbit
& & os . rdbuf ( ) - > sputn ( str . data ( ) , ( std : : streamsize ) str_size ) ! = ( std : : streamsize ) str_size )
{
state | = std : : ios_base : : badbit ;
}
else
{
for ( ; 0 < pad ; - - pad )
{
if ( traits : : eq_int_type ( traits : : eof ( ) , os . rdbuf ( ) - > sputc ( os . fill ( ) ) ) )
{
state | = std : : ios_base : : badbit ;
break ;
}
}
}
os . width ( 0 ) ;
}
catch ( . . . )
{
os . setstate ( std : : ios_base : : badbit , true ) ;
}
}
os . setstate ( state ) ;
return ( os ) ;
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline std : : basic_istream < typename basic_string < _CharTy > : : char_type > & operator > > ( std : : basic_istream < typename basic_string < _CharTy > : : char_type > & is , basic_string < _CharTy > & str )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
using ctype = std : : ctype < typename basic_string < _CharTy > : : char_type > ;
2019-08-02 16:07:01 +08:00
using istream = std : : basic_istream < typename basic_string < _CharTy > : : char_type , typename basic_string < _CharTy > : : traits_type > ;
2019-08-02 13:57:17 +08:00
using size_type = typename basic_string < _CharTy > : : size_type ;
2019-08-02 16:07:01 +08:00
using traits = typename basic_string < _CharTy > : : traits_type ;
2019-03-31 01:37:06 +08:00
bool changed = false ;
const istream : : sentry ok ( is ) ;
std : : ios_base : : iostate state = std : : ios_base : : goodbit ;
if ( ok )
{
const ctype & ctype_fac = std : : use_facet < ctype > ( is . getloc ( ) ) ;
str . erase ( ) ;
try
{
size_type size = ( 0 < is . width ( ) & & static_cast < size_type > ( is . width ( ) ) < str . max_size ( ) ) ? static_cast < size_type > ( is . width ( ) ) : str . max_size ( ) ;
2019-08-02 13:57:17 +08:00
typename traits : : int_type meta = is . rdbuf ( ) - > sgetc ( ) ;
2019-03-31 01:37:06 +08:00
for ( ; 0 < size ; - - size , meta = is . rdbuf ( ) - > snextc ( ) )
{
if ( traits : : eq_int_type ( traits : : eof ( ) , meta ) )
{
state | = std : : ios_base : : eofbit ;
break ;
}
else if ( ctype_fac . is ( ctype : : space , traits : : to_char_type ( meta ) ) )
{
break ;
}
else
{
str . push_back ( traits : : to_char_type ( meta ) ) ;
changed = true ;
}
}
}
catch ( . . . )
{
is . setstate ( std : : ios_base : : badbit , true ) ;
}
}
is . width ( 0 ) ;
if ( ! changed )
state | = std : : ios_base : : failbit ;
is . setstate ( state ) ;
return is ;
}
//
// details of to_string functions
//
namespace __to_string_detail
{
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
struct FloatingToString
{
// template <typename _Ty>
// static basic_string<_CharTy> convert(const _Ty val);
} ;
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
struct IntegralToString
{
// template <typename _Ty>
// static basic_string<_CharTy> convert(const _Ty val);
} ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > to_basic_string ( int val )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
return ( __to_string_detail : : IntegralToString < _CharTy > : : convert ( val ) ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > to_basic_string ( unsigned int val )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
return ( __to_string_detail : : IntegralToString < _CharTy > : : convert ( val ) ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > to_basic_string ( long val )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
return ( __to_string_detail : : IntegralToString < _CharTy > : : convert ( val ) ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > to_basic_string ( unsigned long val )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
return ( __to_string_detail : : IntegralToString < _CharTy > : : convert ( val ) ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > to_basic_string ( long long val )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
return ( __to_string_detail : : IntegralToString < _CharTy > : : convert ( val ) ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > to_basic_string ( unsigned long long val )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
return ( __to_string_detail : : IntegralToString < _CharTy > : : convert ( val ) ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > to_basic_string ( float val )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
return ( __to_string_detail : : FloatingToString < _CharTy > : : convert ( val ) ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > to_basic_string ( double val )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
return ( __to_string_detail : : FloatingToString < _CharTy > : : convert ( val ) ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename _CharTy >
inline basic_string < _CharTy > to_basic_string ( long double val )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
return ( __to_string_detail : : FloatingToString < _CharTy > : : convert ( val ) ) ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename . . . _Args >
inline basic_string < char > format_string ( const char * const fmt , _Args & & . . . args )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
using string_type = basic_string < char > ;
const auto len = static_cast < typename string_type : : size_type > ( : : _scprintf ( fmt , std : : forward < _Args > ( args ) . . . ) ) ;
2019-03-31 01:37:06 +08:00
if ( len )
{
2019-08-02 13:57:17 +08:00
string_type str ( len , ' \0 ' ) ;
: : sprintf_s ( & str [ 0 ] , len + 1 , fmt , std : : forward < _Args > ( args ) . . . ) ;
2019-03-31 01:37:06 +08:00
return str ;
}
2019-08-02 13:57:17 +08:00
return string_type { } ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < typename . . . _Args >
inline basic_string < wchar_t > format_string ( const wchar_t * const fmt , _Args & & . . . args )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
using string_type = basic_string < wchar_t > ;
const auto len = static_cast < typename string_type : : size_type > ( : : _scwprintf ( fmt , std : : forward < _Args > ( args ) . . . ) ) ;
if ( len )
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
string_type str ( len , L ' \0 ' ) ;
: : swprintf_s ( & str [ 0 ] , len + 1 , fmt , std : : forward < _Args > ( args ) . . . ) ;
return str ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
return string_type { } ;
}
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
namespace __to_string_detail
{
template < typename _Ty , typename _Elem >
_Elem * __IntegerToStringBufferEnd ( const _Ty val , _Elem * const buffer_end )
2019-03-31 01:37:06 +08:00
{
using _UTy = std : : make_unsigned_t < _Ty > ;
_Elem * next = buffer_end ;
auto uval = static_cast < _UTy > ( val ) ;
if ( val < 0 )
uval = 0 - uval ;
do
{
* - - next = static_cast < _Elem > ( ' 0 ' + uval % 10 ) ;
uval / = 10 ;
} while ( uval ! = 0 ) ;
if ( val < 0 )
2019-08-02 13:57:17 +08:00
* - - next = static_cast < _Elem > ( ' - ' ) ;
2019-03-31 01:37:06 +08:00
2019-08-02 13:57:17 +08:00
return next ;
2019-03-31 01:37:06 +08:00
}
2019-08-02 13:57:17 +08:00
template < >
struct IntegralToString < char >
{
template < typename _Ty >
static basic_string < char > convert ( const _Ty val )
{
static_assert ( std : : is_integral < _Ty > : : value , " _Ty must be integral " ) ;
2019-08-02 16:07:01 +08:00
using _Elem = typename basic_string < char > : : traits_type : : char_type ;
2019-08-02 13:57:17 +08:00
_Elem buffer [ 21 ] ;
_Elem * const buffer_end = std : : end ( buffer ) ;
_Elem * buffer_begin = __IntegerToStringBufferEnd ( val , buffer_end ) ;
return basic_string < char > ( buffer_begin , buffer_end ) ;
}
} ;
template < >
struct IntegralToString < wchar_t >
{
template < typename _Ty >
static basic_string < wchar_t > convert ( const _Ty val )
{
static_assert ( std : : is_integral < _Ty > : : value , " _Ty must be integral " ) ;
2019-08-02 16:07:01 +08:00
using _Elem = typename basic_string < wchar_t > : : traits_type : : char_type ;
2019-08-02 13:57:17 +08:00
_Elem buffer [ 21 ] ;
_Elem * const buffer_end = std : : end ( buffer ) ;
_Elem * buffer_begin = __IntegerToStringBufferEnd ( val , buffer_end ) ;
return basic_string < wchar_t > ( buffer_begin , buffer_end ) ;
}
} ;
template < >
struct FloatingToString < wchar_t >
{
static inline basic_string < wchar_t > convert ( const float val )
{
return format_string ( L " %g " , val ) ;
}
static inline basic_string < wchar_t > convert ( const double val )
{
return format_string ( L " %g " , val ) ;
}
static inline basic_string < wchar_t > convert ( const long double val )
{
return format_string ( L " %Lg " , val ) ;
}
} ;
template < >
struct FloatingToString < char >
{
static inline basic_string < char > convert ( const float val )
{
return format_string ( " %g " , val ) ;
}
static inline basic_string < char > convert ( const double val )
{
return format_string ( " %g " , val ) ;
}
static inline basic_string < char > convert ( const long double val )
{
return format_string ( " %Lg " , val ) ;
}
} ;
}
}
namespace kiwano
{
2019-08-02 16:07:01 +08:00
template < typename _Codecvt , typename _Elem = wchar_t >
class string_convert
2019-08-02 13:57:17 +08:00
{
2019-08-02 16:07:01 +08:00
enum { BUFFER_INCREASE = 8 , BUFFER_MAX = 16 } ;
public :
using byte_string = kiwano : : basic_string < char > ;
using wide_string = kiwano : : basic_string < _Elem > ;
using codecvt_type = _Codecvt ;
using state_type = typename codecvt_type : : state_type ;
using int_type = typename wide_string : : traits_type : : int_type ;
string_convert ( )
: string_convert ( new codecvt_type )
{
}
explicit string_convert ( const codecvt_type * cvt )
: state_ { }
, cvt_ ( cvt )
, loc_ ( )
, conv_num_ ( 0 )
{
loc_ = std : : locale ( loc_ , cvt_ ) ;
}
virtual ~ string_convert ( ) { }
size_t converted ( ) const noexcept { return conv_num_ ; }
state_type state ( ) const { return state_ ; }
wide_string from_bytes ( char _Byte )
{
return from_bytes ( & _Byte , & _Byte + 1 ) ;
}
wide_string from_bytes ( const char * ptr )
2019-08-02 13:57:17 +08:00
{
2019-08-02 16:07:01 +08:00
return from_bytes ( ptr , ptr + std : : strlen ( ptr ) ) ;
}
wide_string from_bytes ( const byte_string & byte_str )
{
const char * ptr = byte_str . c_str ( ) ;
return from_bytes ( ptr , ptr + byte_str . size ( ) ) ;
}
wide_string from_bytes ( const char * first , const char * last )
{
wide_string wbuf , wstr ;
const char * first_save = first ;
state_ = state_type { } ;
2019-08-02 13:57:17 +08:00
2019-08-02 16:07:01 +08:00
wbuf . append ( ( std : : size_t ) BUFFER_INCREASE , ( _Elem ) ' \0 ' ) ;
for ( conv_num_ = 0 ; first ! = last ; conv_num_ = static_cast < size_t > ( first - first_save ) )
2019-08-02 13:57:17 +08:00
{
2019-08-02 16:07:01 +08:00
_Elem * dest = & * wbuf . begin ( ) ;
_Elem * dnext ;
switch ( cvt_ - > in ( state_ , first , last , first , dest , dest + wbuf . size ( ) , dnext ) )
{
case codecvt_type : : partial :
case codecvt_type : : ok :
{
if ( dest < dnext )
{
wstr . append ( dest , static_cast < size_t > ( dnext - dest ) ) ;
}
else if ( wbuf . size ( ) < BUFFER_MAX )
{
wbuf . append ( static_cast < size_t > ( BUFFER_INCREASE ) , ' \0 ' ) ;
}
else
{
throw ( std : : range_error ( " bad conversion " ) ) ;
}
break ;
}
case codecvt_type : : noconv :
{
// no conversion, just copy code values
for ( ; first ! = last ; + + first ) {
wstr . push_back ( ( _Elem ) ( unsigned char ) * first ) ;
}
break ;
}
default :
throw ( std : : range_error ( " bad conversion " ) ) ;
}
2019-08-02 13:57:17 +08:00
}
2019-08-02 16:07:01 +08:00
return wstr ;
}
2019-08-02 13:57:17 +08:00
2019-08-02 16:07:01 +08:00
byte_string to_bytes ( _Elem _Char )
{
return to_bytes ( & _Char , & _Char + 1 ) ;
}
byte_string to_bytes ( const _Elem * _Wptr )
{
const _Elem * _Next = _Wptr ;
while ( ( int_type ) * _Next ! = 0 ) { + + _Next ; }
return to_bytes ( _Wptr , _Next ) ;
}
byte_string to_bytes ( const wide_string & _Wstr )
{
const _Elem * _Wptr = _Wstr . c_str ( ) ;
return to_bytes ( _Wptr , _Wptr + _Wstr . size ( ) ) ;
}
byte_string to_bytes ( const _Elem * first , const _Elem * last )
{
byte_string bbuf , bstr ;
const _Elem * first_save = first ;
state_ = state_type { } ;
bbuf . append ( ( std : : size_t ) BUFFER_INCREASE , ' \0 ' ) ;
for ( conv_num_ = 0 ; first ! = last ; conv_num_ = static_cast < size_t > ( first - first_save ) )
2019-08-02 13:57:17 +08:00
{
2019-08-02 16:07:01 +08:00
char * dest = & * bbuf . begin ( ) ;
char * dnext ;
switch ( cvt_ - > out ( state_ , first , last , first , dest , dest + bbuf . size ( ) , dnext ) )
{
case codecvt_type : : partial :
case codecvt_type : : ok :
{
if ( dest < dnext )
{
bstr . append ( dest , ( std : : size_t ) ( dnext - dest ) ) ;
}
else if ( bbuf . size ( ) < BUFFER_MAX )
{
bbuf . append ( ( std : : size_t ) BUFFER_INCREASE , ' \0 ' ) ;
}
else
{
throw ( std : : range_error ( " bad conversion " ) ) ;
}
break ;
}
case codecvt_type : : noconv :
{
// no conversion, just copy code values
for ( ; first ! = last ; + + first ) {
bstr . push_back ( ( char ) ( int_type ) * first ) ;
}
break ;
}
default :
throw ( std : : range_error ( " bad conversion " ) ) ;
}
2019-08-02 13:57:17 +08:00
}
2019-08-02 16:07:01 +08:00
return bstr ;
}
string_convert ( const string_convert & ) = delete ;
string_convert & operator = ( const string_convert & ) = delete ;
private :
const codecvt_type * cvt_ ;
std : : locale loc_ ;
state_type state_ ;
size_t conv_num_ ;
} ;
class chs_codecvt
: public std : : codecvt_byname < wchar_t , char , std : : mbstate_t >
{
public :
chs_codecvt ( ) : codecvt_byname ( " chs " ) { }
static inline kiwano : : wstring string_to_wide ( kiwano : : string const & str )
{
string_convert < chs_codecvt > conv ;
return conv . from_bytes ( str ) ;
}
static inline kiwano : : string wide_to_string ( kiwano : : wstring const & str )
{
string_convert < chs_codecvt > conv ;
return conv . to_bytes ( str ) ;
}
} ;
2019-08-02 13:57:17 +08:00
2019-08-02 16:07:01 +08:00
inline kiwano : : wstring string_to_wide ( kiwano : : string const & str )
2019-08-02 13:57:17 +08:00
{
2019-08-02 16:07:01 +08:00
return kiwano : : chs_codecvt : : string_to_wide ( str ) ;
2019-08-02 13:57:17 +08:00
}
2019-08-02 16:07:01 +08:00
inline kiwano : : string wide_to_string ( kiwano : : wstring const & str )
2019-08-02 13:57:17 +08:00
{
2019-08-02 16:07:01 +08:00
return kiwano : : chs_codecvt : : wide_to_string ( str ) ;
2019-03-31 01:37:06 +08:00
}
}
namespace std
{
template < >
2019-08-02 13:57:17 +08:00
struct hash < : : kiwano : : string >
2019-03-31 01:37:06 +08:00
{
2019-08-02 13:57:17 +08:00
inline size_t operator ( ) ( const kiwano : : string & key ) const
2019-03-31 01:37:06 +08:00
{
return key . hash ( ) ;
}
} ;
template < >
2019-08-02 13:57:17 +08:00
struct hash < : : kiwano : : wstring >
{
inline size_t operator ( ) ( const kiwano : : wstring & key ) const
{
return key . hash ( ) ;
}
} ;
}
namespace std
{
template < >
inline void swap < : : kiwano : : string > ( : : kiwano : : string & lhs , : : kiwano : : string & rhs ) noexcept
{
lhs . swap ( rhs ) ;
}
template < >
inline void swap < : : kiwano : : wstring > ( : : kiwano : : wstring & lhs , : : kiwano : : wstring & rhs ) noexcept
2019-03-31 01:37:06 +08:00
{
lhs . swap ( rhs ) ;
}
}