1 #ifndef REPLXX_UNICODESTRING_HXX_INCLUDED
2 #define REPLXX_UNICODESTRING_HXX_INCLUDED
3 
4 #include <vector>
5 #include <cstring>
6 #include <string>
7 
8 #include "conversion.hxx"
9 
10 namespace replxx {
11 
12 class UnicodeString {
13 public:
14 	typedef std::vector<char32_t> data_buffer_t;
15 	typedef data_buffer_t::const_iterator const_iterator;
16 	typedef data_buffer_t::iterator iterator;
17 private:
18 	data_buffer_t _data;
19 public:
UnicodeString()20 	UnicodeString()
21 		: _data() {
22 	}
23 
UnicodeString(std::string const & src)24 	explicit UnicodeString( std::string const& src )
25 		: _data() {
26 		assign( src );
27 	}
28 
UnicodeString(UnicodeString const & other,int offset,int len=-1)29 	explicit UnicodeString( UnicodeString const& other, int offset, int len = -1 )
30 		: _data() {
31 		_data.insert(
32 			_data.end(),
33 			other._data.begin() + offset,
34 			len > 0 ? other._data.begin() + offset + len : other._data.end()
35 		);
36 	}
37 
UnicodeString(char const * src)38 	explicit UnicodeString( char const* src )
39 		: _data() {
40 		assign( src );
41 	}
42 
UnicodeString(char8_t const * src)43 	explicit UnicodeString( char8_t const* src )
44 		: UnicodeString( reinterpret_cast<const char*>( src ) ) {
45 	}
46 
UnicodeString(char32_t const * src)47 	explicit UnicodeString( char32_t const* src )
48 		: _data() {
49 		int len( 0 );
50 		while ( src[len] != 0 ) {
51 			++ len;
52 		}
53 		_data.assign( src, src + len );
54 	}
55 
UnicodeString(char32_t const * src,int len)56 	explicit UnicodeString( char32_t const* src, int len )
57 		: _data() {
58 		_data.assign( src, src + len );
59 	}
60 
UnicodeString(int len)61 	explicit UnicodeString( int len )
62 		: _data() {
63 		_data.resize( len );
64 	}
65 
assign(std::string const & str_)66 	UnicodeString& assign( std::string const& str_ ) {
67 		_data.resize( static_cast<int>( str_.length() ) );
68 		int len( 0 );
69 		copyString8to32( _data.data(), static_cast<int>( str_.length() ), len, str_.c_str() );
70 		_data.resize( len );
71 		return *this;
72 	}
73 
assign(char const * str_)74 	UnicodeString& assign( char const* str_ ) {
75 		int byteCount( static_cast<int>( strlen( str_ ) ) );
76 		_data.resize( byteCount );
77 		int len( 0 );
78 		copyString8to32( _data.data(), byteCount, len, str_ );
79 		_data.resize( len );
80 		return *this;
81 	}
82 
assign(UnicodeString const & other_)83 	UnicodeString& assign( UnicodeString const& other_ ) {
84 		_data = other_._data;
85 		return *this;
86 	}
87 
88 	explicit UnicodeString( UnicodeString const& ) = default;
89 	UnicodeString& operator = ( UnicodeString const& ) = default;
90 	UnicodeString( UnicodeString&& ) = default;
91 	UnicodeString& operator = ( UnicodeString&& ) = default;
operator ==(UnicodeString const & other_) const92 	bool operator == ( UnicodeString const& other_ ) const {
93 		return ( _data == other_._data );
94 	}
95 
operator !=(UnicodeString const & other_) const96 	bool operator != ( UnicodeString const& other_ ) const {
97 		return ( _data != other_._data );
98 	}
99 
append(UnicodeString const & other)100 	UnicodeString& append( UnicodeString const& other ) {
101 		_data.insert( _data.end(), other._data.begin(), other._data.end() );
102 		return *this;
103 	}
104 
push_back(char32_t c_)105 	void push_back( char32_t c_ ) {
106 		_data.push_back( c_ );
107 	}
108 
append(char32_t const * src,int len)109 	UnicodeString& append( char32_t const* src, int len ) {
110 		_data.insert( _data.end(), src, src + len );
111 		return *this;
112 	}
113 
insert(int pos_,UnicodeString const & str_,int offset_,int len_)114 	UnicodeString& insert( int pos_, UnicodeString const& str_, int offset_, int len_ ) {
115 		_data.insert( _data.begin() + pos_, str_._data.begin() + offset_, str_._data.begin() + offset_ + len_ );
116 		return *this;
117 	}
118 
insert(int pos_,char32_t c_)119 	UnicodeString& insert( int pos_, char32_t c_ ) {
120 		_data.insert( _data.begin() + pos_, c_ );
121 		return *this;
122 	}
123 
erase(int pos_)124 	UnicodeString& erase( int pos_ ) {
125 		_data.erase( _data.begin() + pos_ );
126 		return *this;
127 	}
128 
erase(int pos_,int len_)129 	UnicodeString& erase( int pos_, int len_ ) {
130 		_data.erase( _data.begin() + pos_, _data.begin() + pos_ + len_ );
131 		return *this;
132 	}
133 
get() const134 	char32_t const* get() const {
135 		return _data.data();
136 	}
137 
get()138 	char32_t* get() {
139 		return _data.data();
140 	}
141 
length() const142 	int length() const {
143 		return static_cast<int>( _data.size() );
144 	}
145 
clear(void)146 	void clear( void ) {
147 		_data.clear();
148 	}
149 
operator [](size_t pos) const150 	const char32_t& operator[]( size_t pos ) const {
151 		return _data[pos];
152 	}
153 
operator [](size_t pos)154 	char32_t& operator[]( size_t pos ) {
155 		return _data[pos];
156 	}
157 
starts_with(data_buffer_t::const_iterator first_,data_buffer_t::const_iterator last_) const158 	bool starts_with( data_buffer_t::const_iterator first_, data_buffer_t::const_iterator last_ ) const {
159 		return (
160 			( std::distance( first_, last_ ) <= length() )
161 			&& ( std::equal( first_, last_, _data.begin() ) )
162 		);
163 	}
164 
ends_with(data_buffer_t::const_iterator first_,data_buffer_t::const_iterator last_) const165 	bool ends_with( data_buffer_t::const_iterator first_, data_buffer_t::const_iterator last_ ) const {
166 		int len( static_cast<int>( std::distance( first_, last_ ) ) );
167 		return (
168 			( len <= length() )
169 			&& ( std::equal( first_, last_, _data.end() - len ) )
170 		);
171 	}
172 
is_empty(void) const173 	bool is_empty( void ) const {
174 		return ( _data.size() == 0 );
175 	}
176 
swap(UnicodeString & other_)177 	void swap( UnicodeString& other_ ) {
178 		_data.swap( other_._data );
179 	}
180 
begin(void) const181 	const_iterator begin( void ) const {
182 		return ( _data.begin() );
183 	}
184 
end(void) const185 	const_iterator end( void ) const {
186 		return ( _data.end() );
187 	}
188 
begin(void)189 	iterator begin( void ) {
190 		return ( _data.begin() );
191 	}
192 
end(void)193 	iterator end( void ) {
194 		return ( _data.end() );
195 	}
196 };
197 
198 }
199 
200 #endif
201 
202