Usermode/libc++ - Exception handling in progress (build broken)
[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 <allocator>
12
13 namespace std {
14
15 template <class charT>
16 struct char_traits
17 {
18 };
19
20 template <>
21 struct char_traits<char>
22 {
23         typedef char    char_type;
24         typedef int     int_type;
25         //typedef streamoff     off_type;
26         //typedef streampos     pos_type;
27         //typedef mbstate_t     state_type;
28         
29         static bool eq(const char_type& c, const char_type& d) {
30                 return c == d;
31         }
32         static bool lt(const char_type& c, const char_type& d) {
33                 return c < d;
34         }
35         static size_t length(const char_type* s) {
36                 size_t  ret = 0;
37                 while(*s++)     ret ++;
38                 return ret;
39         }
40 };
41
42 template <>
43 struct char_traits<wchar_t>
44 {
45         typedef wchar_t char_type;
46         typedef int     int_type;
47         //typedef streamoff     off_type;
48         //typedef streampos     pos_type;
49         //typedef mbstate_t     state_type;
50         
51         static size_t length(const char_type* s) {
52                 size_t  ret = 0;
53                 while(*s++)     ret ++;
54                 return ret;
55         }
56         static bool eq(const char_type& c, const char_type& d) {
57                 return c == d;
58         }
59         static bool lt(const char_type& c, const char_type& d) {
60                 return c < d;
61         }
62 };
63
64 extern void _throw_out_of_range(const char *message);
65
66 template < class charT, class traits=char_traits<charT>, class Alloc=allocator<charT> >
67 class basic_string
68 {
69 public:
70         typedef traits  traits_type;
71         typedef Alloc   allocator_type;
72         typedef charT   value_type;
73         typedef typename allocator_type::reference      reference;
74         typedef typename allocator_type::const_reference        const_reference;
75         typedef size_t  size_type;
76
77 private:
78         struct dynamic_info
79         {
80                 allocator_type  m_allocator;
81                  int    m_ref_count = 1;
82                 size_type       m_capacity = 0;
83                 size_type       m_size = 0;
84                 typename allocator_type::pointer m_data = 0;
85                 dynamic_info(const allocator_type& alloc):
86                         m_allocator(alloc)
87                 {
88                 }
89                 dynamic_info(const dynamic_info& other):
90                         m_allocator(other.m_allocator),
91                         m_ref_count(1),
92                         m_capacity(other.m_capacity),
93                         m_size(other.m_size)
94                 {
95                         m_data = m_allocator.allocate(m_capacity);
96                         for( size_type i = 0; i < m_size; i ++ )
97                                 m_data[i] = other.m_data[i];
98                 }
99         };
100
101 public:
102         basic_string(const allocator_type& alloc = allocator_type()):
103                 m_allocator(alloc),
104                 m_content(0)
105         {
106         }
107         basic_string(const basic_string& str) throw():
108                 basic_string(allocator_type())
109         {
110                 *this = str;
111         }
112         basic_string(const basic_string& str, const allocator_type& alloc):
113                 basic_string(str, 0, str.length(), alloc)
114         {
115         }
116         basic_string(const basic_string& str, size_type pos, size_type len = npos, const allocator_type& alloc = allocator_type()):
117                 basic_string(alloc)
118         {
119                 if( pos < str.length() )
120                 {
121                         if( len > str.length() - pos )
122                                 len = str.length() - pos;
123                         reserve(len);
124                         for( size_type i = 0; i < len; i ++ )
125                                 m_content->m_data[i] = str.m_content->m_data[pos+i];
126                         m_content->m_size = len;
127                 }
128         }
129         basic_string(const charT *s, const allocator_type& alloc = allocator_type()):
130                 basic_string(s, traits::length(s), alloc)
131         {
132         }
133         basic_string(const charT *s, size_type n, const allocator_type& alloc = allocator_type()):
134                 basic_string(alloc)
135         {
136                 if( n > 0 )
137                 {
138                         reserve(n);
139                         for( size_type i = 0; i < n; i ++ )
140                                 m_content->m_data[i] = s[i];
141                         m_content->m_size = n;
142                 }
143         }
144         basic_string(size_type n, charT c, const allocator_type& alloc = allocator_type()):
145                 basic_string(alloc)
146         {
147                 if( n > 0 )
148                 {
149                         reserve(n);
150                         for( size_type i = 0; i < n; i ++ )
151                                 m_content->m_data[i] = c;
152                         m_content->m_size = n;
153                 }
154         }
155         ~basic_string()
156         {
157                 release_content();
158         }
159         basic_string& operator=(const basic_string& str) throw() {
160                 return assign(str);
161         }
162         basic_string& operator=(const charT* s) {
163                 return assign(s);
164         }
165         basic_string& operator=(charT c) {
166                 return assign(c);
167         }
168         
169         // iterators
170         
171         // capacity
172         size_type size() const {
173                 return m_content ? m_content->m_size : 0;
174         }
175         size_type length() const {
176                 return size();
177         }
178         size_type max_size() const {
179                 return -1;
180         }
181         void resize(size_type size, charT c = 0) {
182                 reserve(size);
183                 if( m_content->m_size < size ) {
184                         for( size_type ofs = m_content->m_size; ofs < size; ofs ++ )
185                                 m_content->m_data[ofs] = c;
186                 }
187                 m_content->m_size = size;
188                 m_content->m_data[size] = 0;
189         }
190         size_type capacity() const {
191                 return m_content ? m_content->m_capacity : 0;
192         }
193         void reserve(size_type size) {
194                 own_content();
195                 size = (size+1 + 31) & ~31;
196                 if( size > m_content->m_capacity ) {
197                         auto new_area = m_allocator.allocate(size);
198                         for( size_type i = 0; i < m_content->m_size; i ++ )
199                                 new_area[i] = m_content->m_data[i];
200                         m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
201                         m_content->m_data = new_area;
202                         m_content->m_capacity = size;
203                 }
204         }
205         void clear() {
206                 own_content();
207                 m_content->m_size = 0;
208         }
209         bool empty() const {
210                 return length() == 0;
211         }
212         
213         // Access
214         reference operator[] (size_type pos) {
215                 own_content();
216                 return m_content->m_data[pos];
217         }
218         const_reference operator[] (size_type pos) const {
219                 return (m_content ? m_content->m_data[pos] : *(const charT*)0);
220         }
221         reference at(size_type pos) {
222                 own_content();
223                 if(pos >= m_content->m_size)
224                         _throw_out_of_range("basic_string - at");
225                 return m_content->m_data[pos];
226         }
227         const_reference at(size_type pos) const {
228                 if(!m_content || pos >= m_content.m_size)
229                         _throw_out_of_range("basic_string - at");
230                 return m_content->m_data[pos];
231         }
232         
233         // Modifiers
234         basic_string& operator +=(const basic_string& str) {
235                 return append(str);
236         }
237         basic_string& operator +=(const charT* s) {
238                 return append(s);
239         }
240         basic_string& operator +=(charT c) {
241                 push_back(c);
242                 return *this;
243         }
244         basic_string& append(const basic_string& str) {
245                 return append(str, 0, npos);
246         }
247         basic_string& append(const basic_string& str, size_type subpos, size_type sublen);
248         basic_string& append(const charT* s) {
249                 return append(s, traits::length(s));
250         }
251         basic_string& append(const charT* s, size_type n);
252         basic_string& append(size_type n, charT c);
253         void push_back(charT c);
254         basic_string& assign(const basic_string& str) throw() {
255                 // Special case, triggers copy-on-write.
256                 release_content();
257                 m_content = str.m_content;
258                 m_content->m_ref_count ++;
259                 return *this;
260         }
261         basic_string& assign(const basic_string& str, size_type subpos, size_type sublen);
262         
263         // String operations
264         const char *c_str() const {
265                 // TODO: this is const, but also might need to do processing
266                 return (m_content ? m_content->m_data : "");
267         }
268         const char *data() const {
269                 return (m_content ? m_content->m_data : NULL);
270         }
271         
272         static const size_type npos = -1;
273 private:
274         allocator_type  m_allocator;
275         dynamic_info    *m_content;
276
277         void own_content() {
278                 if(!m_content)
279                 {
280                         m_content = new dynamic_info(m_allocator);
281                 }
282                 else if( m_content->m_ref_count > 1 )
283                 {
284                         dynamic_info *new_cont = new dynamic_info(*m_content);
285                         m_content->m_ref_count --;
286                         m_content = new_cont;
287                 }
288                 else
289                 {
290                         // already owned
291                 }
292         }
293         void release_content() {
294                 if( m_content )
295                 {
296                         m_content->m_ref_count --;
297                         if( m_content->m_ref_count == 0 ) {
298                                 m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
299                                 delete m_content;
300                         }
301                         m_content = NULL;
302                 }
303         }
304 };
305
306 typedef basic_string<char>      string;
307
308 };
309
310 #endif
311
312 // vim: ft=cpp

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