Usermode/libc++ - Many fixes and cleanups
[tpg/acess2.git] / Usermode / Libraries / libc++.so_src / include_exp / string
1 /*
2  * Acess2 C++ Library
3  * - By John Hodge (thePowersGang)
4  *
5  * string (header)
6  * - C++'s String type
7  */
8 #ifndef _LIBCXX_STRING_
9 #define _LIBCXX_STRING_
10
11 #include "_libcxx_helpers.h"
12 #include <allocator>
13 #include <initializer_list>
14
15 namespace std {
16
17 template <class charT>
18 struct char_traits
19 {
20 };
21
22 template <>
23 struct char_traits<char>
24 {
25         typedef char    char_type;
26         typedef int     int_type;
27         //typedef streamoff     off_type;
28         //typedef streampos     pos_type;
29         //typedef mbstate_t     state_type;
30         
31         static bool eq(const char_type& c, const char_type& d) {
32                 return c == d;
33         }
34         static bool lt(const char_type& c, const char_type& d) {
35                 return c < d;
36         }
37         static size_t length(const char_type* s) {
38                 size_t  ret = 0;
39                 while(*s++)     ret ++;
40                 return ret;
41         }
42         static int compare (const char_type* p, const char_type* q, size_t n) {
43                 while (n--) {
44                         if( !eq(*p,*q) )
45                                 return lt(*p,*q) ? -1 : 1;
46                         ++p; ++q;
47                 }
48                 return 0;
49         }
50 };
51
52 template <>
53 struct char_traits<wchar_t>
54 {
55         typedef wchar_t char_type;
56         typedef int     int_type;
57         //typedef streamoff     off_type;
58         //typedef streampos     pos_type;
59         //typedef mbstate_t     state_type;
60         
61         static size_t length(const char_type* s) {
62                 size_t  ret = 0;
63                 while(*s++)     ret ++;
64                 return ret;
65         }
66         static bool eq(const char_type& c, const char_type& d) {
67                 return c == d;
68         }
69         static bool lt(const char_type& c, const char_type& d) {
70                 return c < d;
71         }
72 };
73
74 extern void _throw_out_of_range(const char *message);
75
76 template < class charT, class traits=char_traits<charT>, class Alloc=allocator<charT> >
77 class basic_string
78 {
79 public:
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;
86         
87         typedef charT*  iterator;
88         typedef const charT*    const_iterator;
89
90 private:
91         struct dynamic_info
92         {
93                 allocator_type  m_allocator;
94                  int    m_ref_count = 1;
95                 size_type       m_capacity = 0;
96                 size_type       m_size = 0;
97                 typename allocator_type::pointer m_data = 0;
98                 dynamic_info(const allocator_type& alloc):
99                         m_allocator(alloc)
100                 {
101                 }
102                 dynamic_info(const dynamic_info& other):
103                         m_allocator(other.m_allocator),
104                         m_ref_count(1),
105                         m_capacity(other.m_capacity),
106                         m_size(other.m_size)
107                 {
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];
111                 }
112         };
113
114         allocator_type  m_allocator;
115         dynamic_info    *m_content;
116
117 public:
118         basic_string(const allocator_type& alloc = allocator_type()):
119                 m_allocator(alloc),
120                 m_content(0)
121         {
122         }
123         basic_string(const basic_string& str) throw():
124                 basic_string(allocator_type())
125         {
126                 *this = str;
127         }
128         #if _CXX11_AVAIL
129         basic_string(basic_string&& str):
130                 m_allocator(str.m_allocator),
131                 m_content(str.m_content)
132         {
133                 str.m_content = 0;
134                 ::_sys::debug("basic_string(move) %p %s", m_content, c_str());
135         }
136         #endif
137         basic_string(const basic_string& str, const allocator_type& alloc):
138                 basic_string(str, 0, str.length(), alloc)
139         {
140         }
141         basic_string(const basic_string& str, size_type pos, size_type len = npos, const allocator_type& alloc = allocator_type()):
142                 basic_string(alloc)
143         {
144                 if( pos < str.length() )
145                 {
146                         if( len > str.length() - pos )
147                                 len = str.length() - pos;
148                         reserve(len);
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;
152                 }
153         }
154         basic_string(const charT *s, const allocator_type& alloc = allocator_type()):
155                 basic_string(s, traits::length(s), alloc)
156         {
157         }
158         basic_string(const charT *s, size_type n, const allocator_type& alloc = allocator_type()):
159                 basic_string(alloc)
160         {
161                 if( n > 0 )
162                 {
163                         reserve(n);
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;
168                 }
169         }
170         basic_string(size_type n, charT c, const allocator_type& alloc = allocator_type()):
171                 basic_string(alloc)
172         {
173                 if( n > 0 )
174                 {
175                         reserve(n);
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;
180                 }
181         }
182         #if __cplusplus < 199711L
183         basic_string(basic_string&& str) noexcept:
184                 basic_string(allocator_type())
185         {
186         }
187         basic_string(basic_string&& str, const allocator_type& alloc) noexcept:
188                 basic_string(alloc)
189         {
190                 m_content = str.m_content;
191                 str.m_content = 0;
192         }
193         #endif
194         ~basic_string()
195         {
196                 release_content();
197         }
198         basic_string& operator=(const basic_string& str) throw() {
199                 return assign(str);
200         }
201         basic_string& operator=(const charT* s) {
202                 return assign(s);
203         }
204         basic_string& operator=(charT c) {
205                 return assign(c);
206         }
207         
208         // iterators
209         
210         // capacity
211         size_type size() const {
212                 return m_content ? m_content->m_size : 0;
213         }
214         size_type length() const {
215                 return size();
216         }
217         size_type max_size() const {
218                 return -1;
219         }
220         void resize(size_type size, charT c = 0) {
221                 reserve(size);
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;
226                 }
227                 m_content->m_size = size;
228                 m_content->m_data[size] = 0;
229         }
230         size_type capacity() const {
231                 return m_content ? m_content->m_capacity : 0;
232         }
233         void reserve(size_type size) {
234                 own_content();
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;
243                 }
244         }
245         void clear() {
246                 own_content();
247                 m_content->m_size = 0;
248         }
249         bool empty() const {
250                 return length() == 0;
251         }
252         #if _CXX11_AVAIL
253         void shrink_to_fit();
254         #endif
255         
256         // Access
257         reference operator[] (size_type pos) {
258                 own_content();
259                 return m_content->m_data[pos];
260         }
261         const_reference operator[] (size_type pos) const {
262                 return (m_content ? m_content->m_data[pos] : *(const charT*)0);
263         }
264         reference at(size_type pos) {
265                 own_content();
266                 if(pos >= m_content->m_size)
267                         _throw_out_of_range("basic_string - at");
268                 return m_content->m_data[pos];
269         }
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];
274         }
275         #if _CXX11_AVAIL
276         reference back() {
277                 own_content();
278                 return m_content->m_data[m_content->m_size];
279         }
280         const_reference back() const {
281                 return m_content->m_data[m_content->m_size];
282         }
283         reference front() {
284                 own_content();
285                 return m_content->m_data[0];
286         }
287         const_reference front() const {
288                 return m_content->m_data[0];
289         }
290         #endif
291         
292         // Modifiers
293         basic_string& operator +=(const basic_string& str) {
294                 return append(str);
295         }
296         basic_string& operator +=(const charT* s) {
297                 return append(s);
298         }
299         basic_string& operator +=(charT c) {
300                 push_back(c);
301                 return *this;
302         }
303         basic_string& append(const basic_string& str) {
304                 return append(str, 0, npos);
305         }
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 );
312                 return *this;
313         }
314         basic_string& append(const charT* s) {
315                 return append(s, traits::length(s));
316         }
317         basic_string& append(const charT* s, size_type n) {
318                 reserve(size() + 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;
323                 return *this;
324         }
325         basic_string& append(size_type n, charT c) {
326                 reserve(size() + n);
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;
331                 return *this;
332         }
333         void push_back(charT c) {
334                 append(1, c);
335         }
336         basic_string& assign(const basic_string& str) throw() {
337                 // Special case, triggers copy-on-write.
338                 release_content();
339                 m_content = str.m_content;
340                 m_content->m_ref_count ++;
341                 return *this;
342         }
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;
348                 
349                 return assign(str.data() + subpos, sublen);
350         }
351         basic_string& assign(const charT* s) {
352                 return assign(s, traits::length(s));
353         }
354         basic_string& assign(const charT* s, size_type n) {
355                 release_content();
356                 reserve(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;
361                 return *this;
362         }
363         basic_string& assign(size_type n, charT c) {
364                 release_content();
365                 reserve(n);
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;
370                 return *this;
371         }
372         
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);
382         #if _CXX11_AVAIL
383         basic_string& insert(const_iterator p, initializer_list<charT> il);
384         #endif
385         
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);
389         
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);
402         
403         void swap(basic_string& str)
404         {
405                 auto tmp = m_content;
406                 m_content = str.m_content;
407                 str.m_content = tmp;
408         }
409         
410         #if _CXX11_AVAIL
411         void pop_back();
412         #endif
413         
414         // String operations
415         const charT *c_str() const noexcept
416         {
417                 // TODO: this is const, but also might need to do processing
418                 if(m_content) {
419                         _libcxx_assert(m_content->m_data[m_content->m_size] == '\0');
420                 }
421                 return (m_content ? m_content->m_data : "");
422         }
423         const charT *data() const
424         {
425                 return (m_content ? m_content->m_data : NULL);
426         }
427         allocator_type get_allocator() const noexcept
428         {
429                 return m_allocator;
430         }
431         size_type copy(charT* s, size_type len, size_type pos = 0) const;
432         
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;
437         
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;
442         
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;
447         
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;
452
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;
457
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;
462
463         basic_string substr(size_type pos = 0, size_type len = npos) const;
464         
465         int compare(const basic_string& str) const noexcept {
466                 return compare(0, size(), str.data(), str.size());
467         }
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());
473         }
474         int compare(size_type pos, size_type len, const basic_string& str, size_type subpos, size_type sublen) const {
475                 // TODO: check
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);
480         }
481         int compare(const charT* s) const {
482                 return compare(0, npos, s, traits::length(s));
483         }
484         int compare(size_type pos, size_type len, const charT* s) const {
485                 return compare(pos, len, s, traits::length(s));
486         }
487         int compare(size_type pos, size_type len, const charT* s, size_type n) const {
488                 if( n <= len ) {
489                         int rv = traits::compare(data()+pos, s, n);
490                         if( rv == 0 && n < len ) {
491                                 rv = -1;
492                         }
493                         return rv;
494                 }
495                 else {
496                         int rv = traits::compare(data()+pos, s, len);
497                         if(rv == 0) {
498                                 rv = 1;
499                         }
500                         return rv;
501                 }
502         }
503         
504         static const size_type npos = -1;
505 private:
506         void own_content() {
507                 if(!m_content)
508                 {
509                         m_content = new dynamic_info(m_allocator);
510                 }
511                 else if( m_content->m_ref_count > 1 )
512                 {
513                         dynamic_info *new_cont = new dynamic_info(*m_content);
514                         m_content->m_ref_count --;
515                         m_content = new_cont;
516                 }
517                 else
518                 {
519                         // already owned
520                 }
521         }
522         void release_content() {
523                 if( m_content )
524                 {
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);
528                                 delete m_content;
529                         }
530                         m_content = NULL;
531                 }
532         }
533 };
534
535 typedef basic_string<char>      string;
536
537 #define _libcxx_str     basic_string<charT,traits,Alloc>
538
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)
541 {
542         basic_string<charT,traits,Alloc>        ret;
543         ret.reserve(lhs.size() + rhs.size());
544         ret += lhs;
545         ret += rhs;
546         return ret;
547 }
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)
550 {
551         basic_string<charT,traits,Alloc>        ret;
552         ret.reserve(lhs.size() + traits::length(rhs));
553         ret += lhs;
554         ret += rhs;
555         return ret;
556 }
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)
559 {
560         basic_string<charT,traits,Alloc>        ret;
561         ret.reserve(traits::length(lhs) + rhs.size());
562         ret += lhs;
563         ret += rhs;
564         return ret;
565 }
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)
568 {
569         basic_string<charT,traits,Alloc>        ret;
570         ret.reserve(lhs.size() + 1);
571         ret += lhs;
572         ret += rhs;
573         return ret;
574 }
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)
577 {
578         basic_string<charT,traits,Alloc>        ret;
579         ret.reserve(1 + rhs.size());
580         ret += lhs;
581         ret += rhs;
582         return ret;
583 }
584
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; }
594
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(>, <)
600 };
601
602 #endif
603
604 // vim: ft=cpp

UCC git Repository :: git.ucc.asn.au