3 * - By John Hodge (thePowersGang)
8 #ifndef _LIBCXX_STRING_
9 #define _LIBCXX_STRING_
11 #include "_libcxx_helpers.h"
16 template <class charT>
22 struct char_traits<char>
24 typedef char char_type;
26 //typedef streamoff off_type;
27 //typedef streampos pos_type;
28 //typedef mbstate_t state_type;
30 static bool eq(const char_type& c, const char_type& d) {
33 static bool lt(const char_type& c, const char_type& d) {
36 static size_t length(const char_type* s) {
44 struct char_traits<wchar_t>
46 typedef wchar_t char_type;
48 //typedef streamoff off_type;
49 //typedef streampos pos_type;
50 //typedef mbstate_t state_type;
52 static size_t length(const char_type* s) {
57 static bool eq(const char_type& c, const char_type& d) {
60 static bool lt(const char_type& c, const char_type& d) {
65 extern void _throw_out_of_range(const char *message);
67 template < class charT, class traits=char_traits<charT>, class Alloc=allocator<charT> >
71 typedef traits traits_type;
72 typedef Alloc allocator_type;
73 typedef charT value_type;
74 typedef typename allocator_type::reference reference;
75 typedef typename allocator_type::const_reference const_reference;
76 typedef size_t size_type;
81 allocator_type m_allocator;
83 size_type m_capacity = 0;
85 typename allocator_type::pointer m_data = 0;
86 dynamic_info(const allocator_type& alloc):
90 dynamic_info(const dynamic_info& other):
91 m_allocator(other.m_allocator),
93 m_capacity(other.m_capacity),
96 m_data = m_allocator.allocate(m_capacity);
97 for( size_type i = 0; i < m_size; i ++ )
98 m_data[i] = other.m_data[i];
102 allocator_type m_allocator;
103 dynamic_info *m_content;
106 basic_string(const allocator_type& alloc = allocator_type()):
111 basic_string(const basic_string& str) throw():
112 basic_string(allocator_type())
117 basic_string(basic_string&& str):
118 m_allocator(str.m_allocator),
119 m_content(str.m_content)
122 ::_sys::debug("basic_string(move) %p %s", m_content, c_str());
125 basic_string(const basic_string& str, const allocator_type& alloc):
126 basic_string(str, 0, str.length(), alloc)
129 basic_string(const basic_string& str, size_type pos, size_type len = npos, const allocator_type& alloc = allocator_type()):
132 if( pos < str.length() )
134 if( len > str.length() - pos )
135 len = str.length() - pos;
137 for( size_type i = 0; i < len; i ++ )
138 m_content->m_data[i] = str.m_content->m_data[pos+i];
139 m_content->m_size = len;
142 basic_string(const charT *s, const allocator_type& alloc = allocator_type()):
143 basic_string(s, traits::length(s), alloc)
146 basic_string(const charT *s, size_type n, const allocator_type& alloc = allocator_type()):
152 for( size_type i = 0; i < n; i ++ )
153 m_content->m_data[i] = s[i];
154 m_content->m_data[n] = 0;
155 m_content->m_size = n;
158 basic_string(size_type n, charT c, const allocator_type& alloc = allocator_type()):
164 for( size_type i = 0; i < n; i ++ )
165 m_content->m_data[i] = c;
166 m_content->m_data[n] = 0;
167 m_content->m_size = n;
170 #if __cplusplus < 199711L
171 basic_string(basic_string&& str) noexcept:
172 basic_string(allocator_type())
175 basic_string(basic_string&& str, const allocator_type& alloc) noexcept:
178 m_content = str.m_content;
186 basic_string& operator=(const basic_string& str) throw() {
189 basic_string& operator=(const charT* s) {
192 basic_string& operator=(charT c) {
199 size_type size() const {
200 return m_content ? m_content->m_size : 0;
202 size_type length() const {
205 size_type max_size() const {
208 void resize(size_type size, charT c = 0) {
210 if( m_content->m_size < size ) {
211 for( size_type ofs = m_content->m_size; ofs < size; ofs ++ )
212 m_content->m_data[ofs] = c;
213 m_content->m_data[size] = 0;
215 m_content->m_size = size;
216 m_content->m_data[size] = 0;
218 size_type capacity() const {
219 return m_content ? m_content->m_capacity : 0;
221 void reserve(size_type size) {
223 size = (size+1 + 31) & ~31;
224 if( size > m_content->m_capacity ) {
225 auto new_area = m_allocator.allocate(size);
226 for( size_type i = 0; i < m_content->m_size; i ++ )
227 new_area[i] = m_content->m_data[i];
228 m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
229 m_content->m_data = new_area;
230 m_content->m_capacity = size;
235 m_content->m_size = 0;
238 return length() == 0;
242 reference operator[] (size_type pos) {
244 return m_content->m_data[pos];
246 const_reference operator[] (size_type pos) const {
247 return (m_content ? m_content->m_data[pos] : *(const charT*)0);
249 reference at(size_type pos) {
251 if(pos >= m_content->m_size)
252 _throw_out_of_range("basic_string - at");
253 return m_content->m_data[pos];
255 const_reference at(size_type pos) const {
256 if(!m_content || pos >= m_content.m_size)
257 _throw_out_of_range("basic_string - at");
258 return m_content->m_data[pos];
262 basic_string& operator +=(const basic_string& str) {
265 basic_string& operator +=(const charT* s) {
268 basic_string& operator +=(charT c) {
272 basic_string& append(const basic_string& str) {
273 return append(str, 0, npos);
275 basic_string& append(const basic_string& str, size_type subpos, size_type sublen) {
276 if(subpos >= str.size())
277 _throw_out_of_range("basic_string - assign source");
278 if( sublen > str.size() - subpos )
279 sublen = str.size() - subpos;
280 append( str.data() + subpos, sublen );
283 basic_string& append(const charT* s) {
284 return append(s, traits::length(s));
286 basic_string& append(const charT* s, size_type n) {
288 for( size_type i = 0; i < n; i ++ )
289 m_content->m_data[size() + i] = s[i];
290 m_content->m_data[size()+n] = '\0';
291 m_content->m_size += n;
294 basic_string& append(size_type n, charT c) {
296 for( size_type i = 0; i < n; i ++ )
297 m_content->m_data[size() + i] = c;
298 m_content->m_data[size()+n] = '\0';
299 m_content->m_size += n;
302 void push_back(charT c) {
305 basic_string& assign(const basic_string& str) throw() {
306 // Special case, triggers copy-on-write.
308 m_content = str.m_content;
309 m_content->m_ref_count ++;
312 basic_string& assign(const basic_string& str, size_type subpos, size_type sublen) {
313 if(subpos >= str.size())
314 _throw_out_of_range("basic_string - assign source");
315 if( sublen > str.size() - subpos )
316 sublen = str.size() - subpos;
318 return assign(str.data() + subpos, sublen);
320 basic_string& assign(const charT* s) {
321 return assign(s, traits::length(s));
323 basic_string& assign(const charT* s, size_type n) {
326 for( size_type i = 0; i < n; i ++ )
327 m_content->m_data[i] = s[i];
328 m_content->m_data[n] = '\0';
329 m_content->m_size = n;
332 basic_string& assign(size_type n, charT c) {
335 for( size_type i = 0; i < n; i ++ )
336 m_content->m_data[i] = c;
337 m_content->m_data[n] = '\0';
338 m_content->m_size = n;
343 const char *c_str() const {
344 // TODO: this is const, but also might need to do processing
346 _libcxx_assert(m_content->m_data[m_content->m_size] == '\0');
348 return (m_content ? m_content->m_data : "");
350 const char *data() const {
351 return (m_content ? m_content->m_data : NULL);
354 static const size_type npos = -1;
359 m_content = new dynamic_info(m_allocator);
361 else if( m_content->m_ref_count > 1 )
363 dynamic_info *new_cont = new dynamic_info(*m_content);
364 m_content->m_ref_count --;
365 m_content = new_cont;
372 void release_content() {
375 m_content->m_ref_count --;
376 if( m_content->m_ref_count == 0 ) {
377 m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
385 typedef basic_string<char> string;
387 template <class charT, class traits, class Alloc>
388 basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const basic_string<charT,traits,Alloc>& rhs)
390 basic_string<charT,traits,Alloc> ret;
391 ret.reserve(lhs.size() + rhs.size());
396 template <class charT, class traits, class Alloc>
397 basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const charT* rhs)
399 basic_string<charT,traits,Alloc> ret;
400 ret.reserve(lhs.size() + traits::length(rhs));
405 template <class charT, class traits, class Alloc>
406 basic_string<charT,traits,Alloc> operator+(const charT* lhs, const basic_string<charT,traits,Alloc>& rhs)
408 basic_string<charT,traits,Alloc> ret;
409 ret.reserve(traits::length(lhs) + rhs.size());
414 template <class charT, class traits, class Alloc>
415 basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const charT rhs)
417 basic_string<charT,traits,Alloc> ret;
418 ret.reserve(lhs.size() + 1);
423 template <class charT, class traits, class Alloc>
424 basic_string<charT,traits,Alloc> operator+(const charT lhs, const basic_string<charT,traits,Alloc>& rhs)
426 basic_string<charT,traits,Alloc> ret;
427 ret.reserve(1 + rhs.size());