3 * - By John Hodge (thePowersGang)
8 #ifndef _LIBCXX_STRING_
9 #define _LIBCXX_STRING_
15 template <class charT>
21 struct char_traits<char>
23 typedef char char_type;
25 //typedef streamoff off_type;
26 //typedef streampos pos_type;
27 //typedef mbstate_t state_type;
29 static bool eq(const char_type& c, const char_type& d) {
32 static bool lt(const char_type& c, const char_type& d) {
35 static size_t length(const char_type* s) {
43 struct char_traits<wchar_t>
45 typedef wchar_t char_type;
47 //typedef streamoff off_type;
48 //typedef streampos pos_type;
49 //typedef mbstate_t state_type;
51 static size_t length(const char_type* s) {
56 static bool eq(const char_type& c, const char_type& d) {
59 static bool lt(const char_type& c, const char_type& d) {
64 extern void _throw_out_of_range(const char *message);
66 template < class charT, class traits=char_traits<charT>, class Alloc=allocator<charT> >
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;
80 allocator_type m_allocator;
82 size_type m_capacity = 0;
84 typename allocator_type::pointer m_data = 0;
85 dynamic_info(const allocator_type& alloc):
89 dynamic_info(const dynamic_info& other):
90 m_allocator(other.m_allocator),
92 m_capacity(other.m_capacity),
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];
102 basic_string(const allocator_type& alloc = allocator_type()):
107 basic_string(const basic_string& str) throw():
108 basic_string(allocator_type())
112 basic_string(const basic_string& str, const allocator_type& alloc):
113 basic_string(str, 0, str.length(), alloc)
116 basic_string(const basic_string& str, size_type pos, size_type len = npos, const allocator_type& alloc = allocator_type()):
119 if( pos < str.length() )
121 if( len > str.length() - pos )
122 len = str.length() - pos;
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;
129 basic_string(const charT *s, const allocator_type& alloc = allocator_type()):
130 basic_string(s, traits::length(s), alloc)
133 basic_string(const charT *s, size_type n, const allocator_type& alloc = allocator_type()):
139 for( size_type i = 0; i < n; i ++ )
140 m_content->m_data[i] = s[i];
141 m_content->m_size = n;
144 basic_string(size_type n, charT c, const allocator_type& alloc = allocator_type()):
150 for( size_type i = 0; i < n; i ++ )
151 m_content->m_data[i] = c;
152 m_content->m_size = n;
155 #if __cplusplus < 199711L
156 basic_string(basic_string&& str) noexcept:
157 basic_string(allocator_type())
160 basic_string(basic_string&& str, const allocator_type& alloc) noexcept:
163 m_content = str.m_content;
171 basic_string& operator=(const basic_string& str) throw() {
174 basic_string& operator=(const charT* s) {
177 basic_string& operator=(charT c) {
184 size_type size() const {
185 return m_content ? m_content->m_size : 0;
187 size_type length() const {
190 size_type max_size() const {
193 void resize(size_type size, charT c = 0) {
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;
199 m_content->m_size = size;
200 m_content->m_data[size] = 0;
202 size_type capacity() const {
203 return m_content ? m_content->m_capacity : 0;
205 void reserve(size_type size) {
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;
219 m_content->m_size = 0;
222 return length() == 0;
226 reference operator[] (size_type pos) {
228 return m_content->m_data[pos];
230 const_reference operator[] (size_type pos) const {
231 return (m_content ? m_content->m_data[pos] : *(const charT*)0);
233 reference at(size_type pos) {
235 if(pos >= m_content->m_size)
236 _throw_out_of_range("basic_string - at");
237 return m_content->m_data[pos];
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];
246 basic_string& operator +=(const basic_string& str) {
249 basic_string& operator +=(const charT* s) {
252 basic_string& operator +=(charT c) {
256 basic_string& append(const basic_string& str) {
257 return append(str, 0, npos);
259 basic_string& append(const basic_string& str, size_type subpos, size_type sublen) {
260 if(subpos >= str.size())
261 _throw_out_of_range("basic_string - assign source");
262 if( sublen > str.size() - subpos )
263 sublen = str.size() - subpos;
264 append( str.data() + subpos, sublen );
267 basic_string& append(const charT* s) {
268 return append(s, traits::length(s));
270 basic_string& append(const charT* s, size_type n) {
272 for( size_type i = 0; i < n; i ++ )
273 m_content->m_data[size() + i] = s[i];
274 m_content->m_data[size()+n] = '\0';
275 m_content->m_size += n;
278 basic_string& append(size_type n, charT c) {
280 for( size_type i = 0; i < n; i ++ )
281 m_content->m_data[size() + i] = c;
282 m_content->m_data[size()+n] = '\0';
283 m_content->m_size += n;
286 void push_back(charT c) {
289 basic_string& assign(const basic_string& str) throw() {
290 // Special case, triggers copy-on-write.
292 m_content = str.m_content;
293 m_content->m_ref_count ++;
296 basic_string& assign(const basic_string& str, size_type subpos, size_type sublen) {
297 if(subpos >= str.size())
298 _throw_out_of_range("basic_string - assign source");
299 if( sublen > str.size() - subpos )
300 sublen = str.size() - subpos;
302 return assign(str.data() + subpos, sublen);
304 basic_string& assign(const charT* s) {
305 return assign(s, traits::length(s));
307 basic_string& assign(const charT* s, size_type n) {
310 for( size_type i = 0; i < n; i ++ )
311 m_content->m_data[i] = s[i];
312 m_content->m_data[n] = '\0';
313 m_content->m_size = n;
316 basic_string& assign(size_type n, charT c) {
319 for( size_type i = 0; i < n; i ++ )
320 m_content->m_data[i] = c;
321 m_content->m_data[n] = '\0';
322 m_content->m_size = n;
327 const char *c_str() const {
328 // TODO: this is const, but also might need to do processing
329 return (m_content ? m_content->m_data : "");
331 const char *data() const {
332 return (m_content ? m_content->m_data : NULL);
335 static const size_type npos = -1;
337 allocator_type m_allocator;
338 dynamic_info *m_content;
343 m_content = new dynamic_info(m_allocator);
345 else if( m_content->m_ref_count > 1 )
347 dynamic_info *new_cont = new dynamic_info(*m_content);
348 m_content->m_ref_count --;
349 m_content = new_cont;
356 void release_content() {
359 m_content->m_ref_count --;
360 if( m_content->m_ref_count == 0 ) {
361 m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
369 typedef basic_string<char> string;
371 template <class charT, class traits, class Alloc>
372 basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const basic_string<charT,traits,Alloc>& rhs)
374 basic_string<charT,traits,Alloc> ret;
375 ret.reserve(lhs.size() + rhs.size());
380 template <class charT, class traits, class Alloc>
381 basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const charT* rhs)
383 basic_string<charT,traits,Alloc> ret;
384 ret.reserve(lhs.size() + traits::length(rhs));
389 template <class charT, class traits, class Alloc>
390 basic_string<charT,traits,Alloc> operator+(const charT* lhs, const basic_string<charT,traits,Alloc>& rhs)
392 basic_string<charT,traits,Alloc> ret;
393 ret.reserve(traits::length(lhs) + rhs.size());
398 template <class charT, class traits, class Alloc>
399 basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const charT rhs)
401 basic_string<charT,traits,Alloc> ret;
402 ret.reserve(lhs.size() + 1);
407 template <class charT, class traits, class Alloc>
408 basic_string<charT,traits,Alloc> operator+(const charT lhs, const basic_string<charT,traits,Alloc>& rhs)
410 basic_string<charT,traits,Alloc> ret;
411 ret.reserve(1 + rhs.size());