3 * - By John Hodge (thePowersGang)
8 #ifndef _LIBCXX_STRING_
9 #define _LIBCXX_STRING_
11 #include "_libcxx_helpers.h"
13 #include <initializer_list>
17 template <class charT>
23 struct char_traits<char>
25 typedef char char_type;
27 //typedef streamoff off_type;
28 //typedef streampos pos_type;
29 //typedef mbstate_t state_type;
31 static bool eq(const char_type& c, const char_type& d) {
34 static bool lt(const char_type& c, const char_type& d) {
37 static size_t length(const char_type* s) {
42 static int compare (const char_type* p, const char_type* q, size_t n) {
45 return lt(*p,*q) ? -1 : 1;
53 struct char_traits<wchar_t>
55 typedef wchar_t char_type;
57 //typedef streamoff off_type;
58 //typedef streampos pos_type;
59 //typedef mbstate_t state_type;
61 static size_t length(const char_type* s) {
66 static bool eq(const char_type& c, const char_type& d) {
69 static bool lt(const char_type& c, const char_type& d) {
74 extern void _throw_out_of_range(const char *message);
76 template < class charT, class traits=char_traits<charT>, class Alloc=allocator<charT> >
80 typedef traits traits_type;
81 typedef Alloc allocator_type;
82 typedef charT value_type;
83 typedef typename allocator_type::reference reference;
84 typedef typename allocator_type::const_reference const_reference;
85 typedef size_t size_type;
87 typedef charT* iterator;
88 typedef const charT* const_iterator;
93 allocator_type m_allocator;
95 size_type m_capacity = 0;
97 typename allocator_type::pointer m_data = 0;
98 dynamic_info(const allocator_type& alloc):
102 dynamic_info(const dynamic_info& other):
103 m_allocator(other.m_allocator),
105 m_capacity(other.m_capacity),
108 m_data = m_allocator.allocate(m_capacity);
109 for( size_type i = 0; i < m_size; i ++ )
110 m_data[i] = other.m_data[i];
114 allocator_type m_allocator;
115 dynamic_info *m_content;
118 basic_string(const allocator_type& alloc = allocator_type()):
123 basic_string(const basic_string& str) throw():
124 basic_string(allocator_type())
129 basic_string(basic_string&& str):
130 m_allocator(str.m_allocator),
131 m_content(str.m_content)
134 ::_sys::debug("basic_string(move) %p %s", m_content, c_str());
137 basic_string(const basic_string& str, const allocator_type& alloc):
138 basic_string(str, 0, str.length(), alloc)
141 basic_string(const basic_string& str, size_type pos, size_type len = npos, const allocator_type& alloc = allocator_type()):
144 if( pos < str.length() )
146 if( len > str.length() - pos )
147 len = str.length() - pos;
149 for( size_type i = 0; i < len; i ++ )
150 m_content->m_data[i] = str.m_content->m_data[pos+i];
151 m_content->m_size = len;
154 basic_string(const charT *s, const allocator_type& alloc = allocator_type()):
155 basic_string(s, traits::length(s), alloc)
158 basic_string(const charT *s, size_type n, const allocator_type& alloc = allocator_type()):
164 for( size_type i = 0; i < n; i ++ )
165 m_content->m_data[i] = s[i];
166 m_content->m_data[n] = 0;
167 m_content->m_size = n;
170 basic_string(size_type n, charT c, const allocator_type& alloc = allocator_type()):
176 for( size_type i = 0; i < n; i ++ )
177 m_content->m_data[i] = c;
178 m_content->m_data[n] = 0;
179 m_content->m_size = n;
182 #if __cplusplus < 199711L
183 basic_string(basic_string&& str) noexcept:
184 basic_string(allocator_type())
187 basic_string(basic_string&& str, const allocator_type& alloc) noexcept:
190 m_content = str.m_content;
198 basic_string& operator=(const basic_string& str) throw() {
201 basic_string& operator=(const charT* s) {
204 basic_string& operator=(charT c) {
211 size_type size() const {
212 return m_content ? m_content->m_size : 0;
214 size_type length() const {
217 size_type max_size() const {
220 void resize(size_type size, charT c = 0) {
222 if( m_content->m_size < size ) {
223 for( size_type ofs = m_content->m_size; ofs < size; ofs ++ )
224 m_content->m_data[ofs] = c;
225 m_content->m_data[size] = 0;
227 m_content->m_size = size;
228 m_content->m_data[size] = 0;
230 size_type capacity() const {
231 return m_content ? m_content->m_capacity : 0;
233 void reserve(size_type size) {
235 size = (size+1 + 31) & ~31;
236 if( size > m_content->m_capacity ) {
237 auto new_area = m_allocator.allocate(size);
238 for( size_type i = 0; i < m_content->m_size; i ++ )
239 new_area[i] = m_content->m_data[i];
240 m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
241 m_content->m_data = new_area;
242 m_content->m_capacity = size;
247 m_content->m_size = 0;
250 return length() == 0;
253 void shrink_to_fit();
257 reference operator[] (size_type pos) {
259 return m_content->m_data[pos];
261 const_reference operator[] (size_type pos) const {
262 return (m_content ? m_content->m_data[pos] : *(const charT*)0);
264 reference at(size_type pos) {
266 if(pos >= m_content->m_size)
267 _throw_out_of_range("basic_string - at");
268 return m_content->m_data[pos];
270 const_reference at(size_type pos) const {
271 if(!m_content || pos >= m_content.m_size)
272 _throw_out_of_range("basic_string - at");
273 return m_content->m_data[pos];
278 return m_content->m_data[m_content->m_size];
280 const_reference back() const {
281 return m_content->m_data[m_content->m_size];
285 return m_content->m_data[0];
287 const_reference front() const {
288 return m_content->m_data[0];
293 basic_string& operator +=(const basic_string& str) {
296 basic_string& operator +=(const charT* s) {
299 basic_string& operator +=(charT c) {
303 basic_string& append(const basic_string& str) {
304 return append(str, 0, npos);
306 basic_string& append(const basic_string& str, size_type subpos, size_type sublen) {
307 if(subpos >= str.size())
308 _throw_out_of_range("basic_string - assign source");
309 if( sublen > str.size() - subpos )
310 sublen = str.size() - subpos;
311 append( str.data() + subpos, sublen );
314 basic_string& append(const charT* s) {
315 return append(s, traits::length(s));
317 basic_string& append(const charT* s, size_type n) {
319 for( size_type i = 0; i < n; i ++ )
320 m_content->m_data[size() + i] = s[i];
321 m_content->m_data[size()+n] = '\0';
322 m_content->m_size += n;
325 basic_string& append(size_type n, charT c) {
327 for( size_type i = 0; i < n; i ++ )
328 m_content->m_data[size() + i] = c;
329 m_content->m_data[size()+n] = '\0';
330 m_content->m_size += n;
333 void push_back(charT c) {
336 basic_string& assign(const basic_string& str) throw() {
337 // Special case, triggers copy-on-write.
339 m_content = str.m_content;
340 m_content->m_ref_count ++;
343 basic_string& assign(const basic_string& str, size_type subpos, size_type sublen) {
344 if(subpos >= str.size())
345 _throw_out_of_range("basic_string - assign source");
346 if( sublen > str.size() - subpos )
347 sublen = str.size() - subpos;
349 return assign(str.data() + subpos, sublen);
351 basic_string& assign(const charT* s) {
352 return assign(s, traits::length(s));
354 basic_string& assign(const charT* s, size_type n) {
357 for( size_type i = 0; i < n; i ++ )
358 m_content->m_data[i] = s[i];
359 m_content->m_data[n] = '\0';
360 m_content->m_size = n;
363 basic_string& assign(size_type n, charT c) {
366 for( size_type i = 0; i < n; i ++ )
367 m_content->m_data[i] = c;
368 m_content->m_data[n] = '\0';
369 m_content->m_size = n;
373 basic_string& insert(size_type pos, const basic_string& str);
374 basic_string& insert(size_type pos, const basic_string& str, size_type subpos, size_type sublen);
375 basic_string& insert(size_type pos, const charT& s);
376 basic_string& insert(size_type pos, const charT& s, size_type n);
377 basic_string& insert(size_type pos, size_type n, charT c);
378 iterator insert(const_iterator p, size_type n, charT c);
379 iterator insert(const_iterator p, charT c);
380 template <class InputIterator>
381 iterator insert(iterator p, InputIterator first, InputIterator last);
383 basic_string& insert(const_iterator p, initializer_list<charT> il);
386 basic_string& erase(size_type pos = 0, size_type len = npos);
387 iterator erase(const_iterator p);
388 iterator erase(const_iterator first, const_iterator last);
390 basic_string& replace(size_type pos, size_type len, const basic_string& str);
391 basic_string& replace(const_iterator i1, const_reference i2, const basic_string& str);
392 basic_string& replace(size_type pos, size_type len, const basic_string& str, size_type subpos, size_type sublen);
393 basic_string& replace(size_type pos, size_type len, const charT *s);
394 basic_string& replace(const_iterator i1, const_reference i2, const charT* s);
395 basic_string& replace(size_type pos, size_type len, const charT *s, size_type n);
396 basic_string& replace(const_iterator i1, const_reference i2, const charT* s, size_type n);
397 basic_string& replace(size_type pos, size_type len, size_type n, charT c);
398 basic_string& replace(const_iterator i1, const_reference i2, size_type n, charT c);
399 template <class InputIterator>
400 basic_string& replace(const_iterator i1, const_reference i2, InputIterator first, InputIterator last);
401 basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<charT> il);
403 void swap(basic_string& str)
405 auto tmp = m_content;
406 m_content = str.m_content;
415 const charT *c_str() const noexcept
417 // TODO: this is const, but also might need to do processing
419 _libcxx_assert(m_content->m_data[m_content->m_size] == '\0');
421 return (m_content ? m_content->m_data : "");
423 const charT *data() const
425 return (m_content ? m_content->m_data : NULL);
427 allocator_type get_allocator() const noexcept
431 size_type copy(charT* s, size_type len, size_type pos = 0) const;
433 size_type find(const basic_string& str, size_type pos = 0) const noexcept;
434 size_type find(const charT* s, size_type pos = 0) const;
435 size_type find(const charT* s, size_type pos, size_type n) const;
436 size_type find(charT c, size_type pos = 0) const noexcept;
438 size_type rfind(const basic_string& str, size_type pos = 0) const noexcept;
439 size_type rfind(const charT* s, size_type pos = 0) const;
440 size_type rfind(const charT* s, size_type pos, size_type n) const;
441 size_type rfind(charT c, size_type pos = 0) const noexcept;
443 size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept;
444 size_type find_first_of(const charT* s, size_type pos = 0) const;
445 size_type find_first_of(const charT* s, size_type pos, size_type n) const;
446 size_type find_first_of(charT c, size_type pos = 0) const noexcept;
448 size_type find_last_of(const basic_string& str, size_type pos = 0) const noexcept;
449 size_type find_last_of(const charT* s, size_type pos = 0) const;
450 size_type find_last_of(const charT* s, size_type pos, size_type n) const;
451 size_type find_last_of(charT c, size_type pos = 0) const noexcept;
453 size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept;
454 size_type find_first_not_of(const charT* s, size_type pos = 0) const;
455 size_type find_first_not_of(const charT* s, size_type pos, size_type n) const;
456 size_type find_first_not_of(charT c, size_type pos = 0) const noexcept;
458 size_type find_last_not_of(const basic_string& str, size_type pos = 0) const noexcept;
459 size_type find_last_not_of(const charT* s, size_type pos = 0) const;
460 size_type find_last_not_of(const charT* s, size_type pos, size_type n) const;
461 size_type find_last_not_of(charT c, size_type pos = 0) const noexcept;
463 basic_string substr(size_type pos = 0, size_type len = npos) const;
465 int compare(const basic_string& str) const noexcept {
466 return compare(0, size(), str.data(), str.size());
468 int compare(size_type pos, size_type len, const basic_string& str) const {
469 _libcxx_assert(pos <= size());
470 _libcxx_assert(len <= size());
471 _libcxx_assert(pos+len <= size());
472 return compare(pos, len, str.data(), str.size());
474 int compare(size_type pos, size_type len, const basic_string& str, size_type subpos, size_type sublen) const {
476 _libcxx_assert(subpos <= str.size());
477 _libcxx_assert(sublen <= str.size());
478 _libcxx_assert(subpos+sublen <= str.size());
479 return compare(pos, len, str.data()+subpos, sublen);
481 int compare(const charT* s) const {
482 return compare(0, npos, s, traits::length(s));
484 int compare(size_type pos, size_type len, const charT* s) const {
485 return compare(pos, len, s, traits::length(s));
487 int compare(size_type pos, size_type len, const charT* s, size_type n) const {
489 int rv = traits::compare(data()+pos, s, n);
490 if( rv == 0 && n < len ) {
496 int rv = traits::compare(data()+pos, s, len);
504 static const size_type npos = -1;
509 m_content = new dynamic_info(m_allocator);
511 else if( m_content->m_ref_count > 1 )
513 dynamic_info *new_cont = new dynamic_info(*m_content);
514 m_content->m_ref_count --;
515 m_content = new_cont;
522 void release_content() {
525 m_content->m_ref_count --;
526 if( m_content->m_ref_count == 0 ) {
527 m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
535 typedef basic_string<char> string;
537 #define _libcxx_str basic_string<charT,traits,Alloc>
539 template <class charT, class traits, class Alloc>
540 basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const basic_string<charT,traits,Alloc>& rhs)
542 basic_string<charT,traits,Alloc> ret;
543 ret.reserve(lhs.size() + rhs.size());
548 template <class charT, class traits, class Alloc>
549 basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const charT* rhs)
551 basic_string<charT,traits,Alloc> ret;
552 ret.reserve(lhs.size() + traits::length(rhs));
557 template <class charT, class traits, class Alloc>
558 basic_string<charT,traits,Alloc> operator+(const charT* lhs, const basic_string<charT,traits,Alloc>& rhs)
560 basic_string<charT,traits,Alloc> ret;
561 ret.reserve(traits::length(lhs) + rhs.size());
566 template <class charT, class traits, class Alloc>
567 basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const charT rhs)
569 basic_string<charT,traits,Alloc> ret;
570 ret.reserve(lhs.size() + 1);
575 template <class charT, class traits, class Alloc>
576 basic_string<charT,traits,Alloc> operator+(const charT lhs, const basic_string<charT,traits,Alloc>& rhs)
578 basic_string<charT,traits,Alloc> ret;
579 ret.reserve(1 + rhs.size());
585 // Three overloads each
586 // name: Actual operator, opp: reversed operator
587 #define _libcxx_string_def_cmp(name, opp) \
588 template <class charT, class traits, class Alloc> \
589 bool operator name(const _libcxx_str& lhs, const _libcxx_str& rhs) { return lhs.compare(rhs) name 0; } \
590 template <class charT, class traits, class Alloc> \
591 bool operator name(const charT* lhs, const _libcxx_str& rhs) { return rhs.compare(lhs) opp 0; } \
592 template <class charT, class traits, class Alloc> \
593 bool operator name(const _libcxx_str& lhs, const charT* rhs) { return lhs.compare(rhs) name 0; }
595 _libcxx_string_def_cmp(<, >)
596 _libcxx_string_def_cmp(<=, >=)
597 _libcxx_string_def_cmp(==, ==)
598 _libcxx_string_def_cmp(>=, <=)
599 _libcxx_string_def_cmp(>, <)