musique/lib/replxx/src/unicodestring.hxx
2023-02-22 02:38:46 +01:00

229 lines
5.2 KiB
C++

#ifndef REPLXX_UNICODESTRING_HXX_INCLUDED
#define REPLXX_UNICODESTRING_HXX_INCLUDED
#include <vector>
#include <cstring>
#include <cwctype>
#include <cassert>
#include "conversion.hxx"
namespace replxx {
inline bool case_sensitive_equal( char32_t l, char32_t r ) {
return l == r;
}
inline bool case_insensitive_equal( char32_t l, char32_t r ) {
return towlower( static_cast<wint_t>( l ) ) == towlower( static_cast<wint_t>( r ) );
}
class UnicodeString {
public:
typedef std::vector<char32_t> data_buffer_t;
typedef data_buffer_t::const_iterator const_iterator;
typedef data_buffer_t::iterator iterator;
private:
data_buffer_t _data;
public:
UnicodeString()
: _data() {
}
explicit UnicodeString( std::string const& src )
: _data() {
assign( src );
}
explicit UnicodeString( UnicodeString const& other, int offset, int len = -1 )
: _data() {
_data.insert(
_data.end(),
other._data.begin() + offset,
len > 0 ? other._data.begin() + offset + len : other._data.end()
);
}
explicit UnicodeString( char const* src )
: _data() {
assign( src );
}
explicit UnicodeString( char8_t const* src )
: UnicodeString( reinterpret_cast<const char*>( src ) ) {
}
explicit UnicodeString( char32_t const* src )
: _data() {
int len( 0 );
while ( src[len] != 0 ) {
++ len;
}
_data.assign( src, src + len );
}
explicit UnicodeString( char32_t const* src, int len )
: _data() {
_data.assign( src, src + len );
}
explicit UnicodeString( int len )
: _data() {
_data.resize( len );
}
UnicodeString& assign( std::string const& str_ ) {
_data.resize( static_cast<int>( str_.length() ) );
int len( 0 );
copyString8to32( _data.data(), static_cast<int>( str_.length() ), len, str_.c_str() );
_data.resize( len );
return *this;
}
UnicodeString& assign( char const* str_ ) {
int byteCount( static_cast<int>( strlen( str_ ) ) );
_data.resize( byteCount );
int len( 0 );
copyString8to32( _data.data(), byteCount, len, str_ );
_data.resize( len );
return *this;
}
UnicodeString& assign( UnicodeString const& other_ ) {
_data = other_._data;
return *this;
}
explicit UnicodeString( UnicodeString const& ) = default;
UnicodeString& operator = ( UnicodeString const& ) = default;
UnicodeString( UnicodeString&& ) = default;
UnicodeString& operator = ( UnicodeString&& ) = default;
bool operator == ( UnicodeString const& other_ ) const {
return ( _data == other_._data );
}
bool operator != ( UnicodeString const& other_ ) const {
return ( _data != other_._data );
}
bool operator < ( UnicodeString const& other_ ) const {
return std::lexicographical_compare(begin(), end(), other_.begin(), other_.end());
}
UnicodeString& append( UnicodeString const& other ) {
_data.insert( _data.end(), other._data.begin(), other._data.end() );
return *this;
}
void push_back( char32_t c_ ) {
_data.push_back( c_ );
}
UnicodeString& append( char32_t const* src, int len ) {
_data.insert( _data.end(), src, src + len );
return *this;
}
UnicodeString& insert( int pos_, UnicodeString const& str_, int offset_, int len_ ) {
_data.insert( _data.begin() + pos_, str_._data.begin() + offset_, str_._data.begin() + offset_ + len_ );
return *this;
}
UnicodeString& insert( int pos_, char32_t c_ ) {
_data.insert( _data.begin() + pos_, c_ );
return *this;
}
UnicodeString& erase( int pos_ ) {
_data.erase( _data.begin() + pos_ );
return *this;
}
UnicodeString& erase( int pos_, int len_ ) {
_data.erase( _data.begin() + pos_, _data.begin() + pos_ + len_ );
return *this;
}
char32_t const* get() const {
return _data.data();
}
char32_t* get() {
return _data.data();
}
int length() const {
return static_cast<int>( _data.size() );
}
void clear( void ) {
_data.clear();
}
const char32_t& operator[]( int pos ) const {
assert( ( pos >= 0 ) && ( pos < static_cast<int>( _data.size() ) ) );
return _data[pos];
}
char32_t& operator[]( int pos ) {
assert( ( pos >= 0 ) && ( pos < static_cast<int>( _data.size() ) ) );
return _data[pos];
}
bool starts_with( data_buffer_t::const_iterator first_, data_buffer_t::const_iterator last_ ) const {
return (
( std::distance( first_, last_ ) <= length() )
&& ( std::equal( first_, last_, _data.begin() ) )
);
}
template <class BinaryPredicate>
bool starts_with( data_buffer_t::const_iterator first_, data_buffer_t::const_iterator last_, BinaryPredicate&& pred ) const {
return (
( std::distance( first_, last_ ) <= length() )
&& ( std::equal( first_, last_, _data.begin(), std::forward<BinaryPredicate>( pred ) ) )
);
}
bool ends_with( data_buffer_t::const_iterator first_, data_buffer_t::const_iterator last_ ) const {
int len( static_cast<int>( std::distance( first_, last_ ) ) );
return (
( len <= length() )
&& ( std::equal( first_, last_, _data.end() - len ) )
);
}
bool is_empty( void ) const {
return ( _data.size() == 0 );
}
void swap( UnicodeString& other_ ) {
_data.swap( other_._data );
}
const_iterator begin( void ) const {
return ( _data.begin() );
}
const_iterator end( void ) const {
return ( _data.end() );
}
iterator begin( void ) {
return ( _data.begin() );
}
iterator end( void ) {
return ( _data.end() );
}
char32_t back( void ) const {
return ( _data.back() );
}
};
}
#endif