Usermode/libc++ - Tweaks to STL
[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         #if __cplusplus < 199711L
156         basic_string(basic_string&& str) noexcept:
157                 basic_string(allocator_type())
158         {
159         }
160         basic_string(basic_string&& str, const allocator_type& alloc) noexcept:
161                 basic_string(alloc)
162         {
163                 m_content = str.m_content;
164                 str.m_content = 0;
165         }
166         #endif
167         ~basic_string()
168         {
169                 release_content();
170         }
171         basic_string& operator=(const basic_string& str) throw() {
172                 return assign(str);
173         }
174         basic_string& operator=(const charT* s) {
175                 return assign(s);
176         }
177         basic_string& operator=(charT c) {
178                 return assign(c);
179         }
180         
181         // iterators
182         
183         // capacity
184         size_type size() const {
185                 return m_content ? m_content->m_size : 0;
186         }
187         size_type length() const {
188                 return size();
189         }
190         size_type max_size() const {
191                 return -1;
192         }
193         void resize(size_type size, charT c = 0) {
194                 reserve(size);
195                 if( m_content->m_size < size ) {
196                         for( size_type ofs = m_content->m_size; ofs < size; ofs ++ )
197                                 m_content->m_data[ofs] = c;
198                 }
199                 m_content->m_size = size;
200                 m_content->m_data[size] = 0;
201         }
202         size_type capacity() const {
203                 return m_content ? m_content->m_capacity : 0;
204         }
205         void reserve(size_type size) {
206                 own_content();
207                 size = (size+1 + 31) & ~31;
208                 if( size > m_content->m_capacity ) {
209                         auto new_area = m_allocator.allocate(size);
210                         for( size_type i = 0; i < m_content->m_size; i ++ )
211                                 new_area[i] = m_content->m_data[i];
212                         m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
213                         m_content->m_data = new_area;
214                         m_content->m_capacity = size;
215                 }
216         }
217         void clear() {
218                 own_content();
219                 m_content->m_size = 0;
220         }
221         bool empty() const {
222                 return length() == 0;
223         }
224         
225         // Access
226         reference operator[] (size_type pos) {
227                 own_content();
228                 return m_content->m_data[pos];
229         }
230         const_reference operator[] (size_type pos) const {
231                 return (m_content ? m_content->m_data[pos] : *(const charT*)0);
232         }
233         reference at(size_type pos) {
234                 own_content();
235                 if(pos >= m_content->m_size)
236                         _throw_out_of_range("basic_string - at");
237                 return m_content->m_data[pos];
238         }
239         const_reference at(size_type pos) const {
240                 if(!m_content || pos >= m_content.m_size)
241                         _throw_out_of_range("basic_string - at");
242                 return m_content->m_data[pos];
243         }
244         
245         // Modifiers
246         basic_string& operator +=(const basic_string& str) {
247                 return append(str);
248         }
249         basic_string& operator +=(const charT* s) {
250                 return append(s);
251         }
252         basic_string& operator +=(charT c) {
253                 push_back(c);
254                 return *this;
255         }
256         basic_string& append(const basic_string& str) {
257                 return append(str, 0, npos);
258         }
259         basic_string& append(const basic_string& str, size_type subpos, size_type sublen);
260         basic_string& append(const charT* s) {
261                 return append(s, traits::length(s));
262         }
263         basic_string& append(const charT* s, size_type n);
264         basic_string& append(size_type n, charT c);
265         void push_back(charT c);
266         basic_string& assign(const basic_string& str) throw() {
267                 // Special case, triggers copy-on-write.
268                 release_content();
269                 m_content = str.m_content;
270                 m_content->m_ref_count ++;
271                 return *this;
272         }
273         basic_string& assign(const basic_string& str, size_type subpos, size_type sublen);
274         
275         // String operations
276         const char *c_str() const {
277                 // TODO: this is const, but also might need to do processing
278                 return (m_content ? m_content->m_data : "");
279         }
280         const char *data() const {
281                 return (m_content ? m_content->m_data : NULL);
282         }
283         
284         static const size_type npos = -1;
285 private:
286         allocator_type  m_allocator;
287         dynamic_info    *m_content;
288
289         void own_content() {
290                 if(!m_content)
291                 {
292                         m_content = new dynamic_info(m_allocator);
293                 }
294                 else if( m_content->m_ref_count > 1 )
295                 {
296                         dynamic_info *new_cont = new dynamic_info(*m_content);
297                         m_content->m_ref_count --;
298                         m_content = new_cont;
299                 }
300                 else
301                 {
302                         // already owned
303                 }
304         }
305         void release_content() {
306                 if( m_content )
307                 {
308                         m_content->m_ref_count --;
309                         if( m_content->m_ref_count == 0 ) {
310                                 m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
311                                 delete m_content;
312                         }
313                         m_content = NULL;
314                 }
315         }
316 };
317
318 typedef basic_string<char>      string;
319
320 };
321
322 #endif
323
324 // vim: ft=cpp

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