Usermode/libc++ - STL Fix string termination, silence map debug
[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
14 namespace std {
15
16 template <class charT>
17 struct char_traits
18 {
19 };
20
21 template <>
22 struct char_traits<char>
23 {
24         typedef char    char_type;
25         typedef int     int_type;
26         //typedef streamoff     off_type;
27         //typedef streampos     pos_type;
28         //typedef mbstate_t     state_type;
29         
30         static bool eq(const char_type& c, const char_type& d) {
31                 return c == d;
32         }
33         static bool lt(const char_type& c, const char_type& d) {
34                 return c < d;
35         }
36         static size_t length(const char_type* s) {
37                 size_t  ret = 0;
38                 while(*s++)     ret ++;
39                 return ret;
40         }
41 };
42
43 template <>
44 struct char_traits<wchar_t>
45 {
46         typedef wchar_t char_type;
47         typedef int     int_type;
48         //typedef streamoff     off_type;
49         //typedef streampos     pos_type;
50         //typedef mbstate_t     state_type;
51         
52         static size_t length(const char_type* s) {
53                 size_t  ret = 0;
54                 while(*s++)     ret ++;
55                 return ret;
56         }
57         static bool eq(const char_type& c, const char_type& d) {
58                 return c == d;
59         }
60         static bool lt(const char_type& c, const char_type& d) {
61                 return c < d;
62         }
63 };
64
65 extern void _throw_out_of_range(const char *message);
66
67 template < class charT, class traits=char_traits<charT>, class Alloc=allocator<charT> >
68 class basic_string
69 {
70 public:
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;
77
78 private:
79         struct dynamic_info
80         {
81                 allocator_type  m_allocator;
82                  int    m_ref_count = 1;
83                 size_type       m_capacity = 0;
84                 size_type       m_size = 0;
85                 typename allocator_type::pointer m_data = 0;
86                 dynamic_info(const allocator_type& alloc):
87                         m_allocator(alloc)
88                 {
89                 }
90                 dynamic_info(const dynamic_info& other):
91                         m_allocator(other.m_allocator),
92                         m_ref_count(1),
93                         m_capacity(other.m_capacity),
94                         m_size(other.m_size)
95                 {
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];
99                 }
100         };
101
102         allocator_type  m_allocator;
103         dynamic_info    *m_content;
104
105 public:
106         basic_string(const allocator_type& alloc = allocator_type()):
107                 m_allocator(alloc),
108                 m_content(0)
109         {
110         }
111         basic_string(const basic_string& str) throw():
112                 basic_string(allocator_type())
113         {
114                 *this = str;
115         }
116         #if _CXX11_AVAIL
117         basic_string(basic_string&& str):
118                 m_allocator(str.m_allocator),
119                 m_content(str.m_content)
120         {
121                 str.m_content = 0;
122                 ::_sys::debug("basic_string(move) %p %s", m_content, c_str());
123         }
124         #endif
125         basic_string(const basic_string& str, const allocator_type& alloc):
126                 basic_string(str, 0, str.length(), alloc)
127         {
128         }
129         basic_string(const basic_string& str, size_type pos, size_type len = npos, const allocator_type& alloc = allocator_type()):
130                 basic_string(alloc)
131         {
132                 if( pos < str.length() )
133                 {
134                         if( len > str.length() - pos )
135                                 len = str.length() - pos;
136                         reserve(len);
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;
140                 }
141         }
142         basic_string(const charT *s, const allocator_type& alloc = allocator_type()):
143                 basic_string(s, traits::length(s), alloc)
144         {
145         }
146         basic_string(const charT *s, size_type n, const allocator_type& alloc = allocator_type()):
147                 basic_string(alloc)
148         {
149                 if( n > 0 )
150                 {
151                         reserve(n);
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;
156                 }
157         }
158         basic_string(size_type n, charT c, 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] = c;
166                         m_content->m_data[n] = 0;
167                         m_content->m_size = n;
168                 }
169         }
170         #if __cplusplus < 199711L
171         basic_string(basic_string&& str) noexcept:
172                 basic_string(allocator_type())
173         {
174         }
175         basic_string(basic_string&& str, const allocator_type& alloc) noexcept:
176                 basic_string(alloc)
177         {
178                 m_content = str.m_content;
179                 str.m_content = 0;
180         }
181         #endif
182         ~basic_string()
183         {
184                 release_content();
185         }
186         basic_string& operator=(const basic_string& str) throw() {
187                 return assign(str);
188         }
189         basic_string& operator=(const charT* s) {
190                 return assign(s);
191         }
192         basic_string& operator=(charT c) {
193                 return assign(c);
194         }
195         
196         // iterators
197         
198         // capacity
199         size_type size() const {
200                 return m_content ? m_content->m_size : 0;
201         }
202         size_type length() const {
203                 return size();
204         }
205         size_type max_size() const {
206                 return -1;
207         }
208         void resize(size_type size, charT c = 0) {
209                 reserve(size);
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;
214                 }
215                 m_content->m_size = size;
216                 m_content->m_data[size] = 0;
217         }
218         size_type capacity() const {
219                 return m_content ? m_content->m_capacity : 0;
220         }
221         void reserve(size_type size) {
222                 own_content();
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;
231                 }
232         }
233         void clear() {
234                 own_content();
235                 m_content->m_size = 0;
236         }
237         bool empty() const {
238                 return length() == 0;
239         }
240         
241         // Access
242         reference operator[] (size_type pos) {
243                 own_content();
244                 return m_content->m_data[pos];
245         }
246         const_reference operator[] (size_type pos) const {
247                 return (m_content ? m_content->m_data[pos] : *(const charT*)0);
248         }
249         reference at(size_type pos) {
250                 own_content();
251                 if(pos >= m_content->m_size)
252                         _throw_out_of_range("basic_string - at");
253                 return m_content->m_data[pos];
254         }
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];
259         }
260         
261         // Modifiers
262         basic_string& operator +=(const basic_string& str) {
263                 return append(str);
264         }
265         basic_string& operator +=(const charT* s) {
266                 return append(s);
267         }
268         basic_string& operator +=(charT c) {
269                 push_back(c);
270                 return *this;
271         }
272         basic_string& append(const basic_string& str) {
273                 return append(str, 0, npos);
274         }
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 );
281                 return *this;
282         }
283         basic_string& append(const charT* s) {
284                 return append(s, traits::length(s));
285         }
286         basic_string& append(const charT* s, size_type n) {
287                 reserve(size() + 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;
292                 return *this;
293         }
294         basic_string& append(size_type n, charT c) {
295                 reserve(size() + n);
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;
300                 return *this;
301         }
302         void push_back(charT c) {
303                 append(1, c);
304         }
305         basic_string& assign(const basic_string& str) throw() {
306                 // Special case, triggers copy-on-write.
307                 release_content();
308                 m_content = str.m_content;
309                 m_content->m_ref_count ++;
310                 return *this;
311         }
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;
317                 
318                 return assign(str.data() + subpos, sublen);
319         }
320         basic_string& assign(const charT* s) {
321                 return assign(s, traits::length(s));
322         }
323         basic_string& assign(const charT* s, size_type n) {
324                 release_content();
325                 reserve(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;
330                 return *this;
331         }
332         basic_string& assign(size_type n, charT c) {
333                 release_content();
334                 reserve(n);
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;
339                 return *this;
340         }
341         
342         // String operations
343         const char *c_str() const {
344                 // TODO: this is const, but also might need to do processing
345                 if(m_content) {
346                         _libcxx_assert(m_content->m_data[m_content->m_size] == '\0');
347                 }
348                 return (m_content ? m_content->m_data : "");
349         }
350         const char *data() const {
351                 return (m_content ? m_content->m_data : NULL);
352         }
353         
354         static const size_type npos = -1;
355 private:
356         void own_content() {
357                 if(!m_content)
358                 {
359                         m_content = new dynamic_info(m_allocator);
360                 }
361                 else if( m_content->m_ref_count > 1 )
362                 {
363                         dynamic_info *new_cont = new dynamic_info(*m_content);
364                         m_content->m_ref_count --;
365                         m_content = new_cont;
366                 }
367                 else
368                 {
369                         // already owned
370                 }
371         }
372         void release_content() {
373                 if( m_content )
374                 {
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);
378                                 delete m_content;
379                         }
380                         m_content = NULL;
381                 }
382         }
383 };
384
385 typedef basic_string<char>      string;
386
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)
389 {
390         basic_string<charT,traits,Alloc>        ret;
391         ret.reserve(lhs.size() + rhs.size());
392         ret += lhs;
393         ret += rhs;
394         return ret;
395 }
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)
398 {
399         basic_string<charT,traits,Alloc>        ret;
400         ret.reserve(lhs.size() + traits::length(rhs));
401         ret += lhs;
402         ret += rhs;
403         return ret;
404 }
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)
407 {
408         basic_string<charT,traits,Alloc>        ret;
409         ret.reserve(traits::length(lhs) + rhs.size());
410         ret += lhs;
411         ret += rhs;
412         return ret;
413 }
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)
416 {
417         basic_string<charT,traits,Alloc>        ret;
418         ret.reserve(lhs.size() + 1);
419         ret += lhs;
420         ret += rhs;
421         return ret;
422 }
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)
425 {
426         basic_string<charT,traits,Alloc>        ret;
427         ret.reserve(1 + rhs.size());
428         ret += lhs;
429         ret += rhs;
430         return ret;
431 }
432
433 };
434
435 #endif
436
437 // vim: ft=cpp

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