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;
159 basic_string& operator=(const basic_string& str) throw() {
162 basic_string& operator=(const charT* s) {
165 basic_string& operator=(charT c) {
172 size_type size() const {
173 return m_content ? m_content->m_size : 0;
175 size_type length() const {
178 size_type max_size() const {
181 void resize(size_type size, charT c = 0) {
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;
187 m_content->m_size = size;
188 m_content->m_data[size] = 0;
190 size_type capacity() const {
191 return m_content ? m_content->m_capacity : 0;
193 void reserve(size_type size) {
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;
207 m_content->m_size = 0;
210 return length() == 0;
214 reference operator[] (size_type pos) {
216 return m_content->m_data[pos];
218 const_reference operator[] (size_type pos) const {
219 return (m_content ? m_content->m_data[pos] : *(const charT*)0);
221 reference at(size_type pos) {
223 if(pos >= m_content->m_size)
224 _throw_out_of_range("basic_string - at");
225 return m_content->m_data[pos];
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];
234 basic_string& operator +=(const basic_string& str) {
237 basic_string& operator +=(const charT* s) {
240 basic_string& operator +=(charT c) {
244 basic_string& append(const basic_string& str) {
245 return append(str, 0, npos);
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));
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.
257 m_content = str.m_content;
258 m_content->m_ref_count ++;
261 basic_string& assign(const basic_string& str, size_type subpos, size_type sublen);
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 : "");
268 const char *data() const {
269 return (m_content ? m_content->m_data : NULL);
272 static const size_type npos = -1;
274 allocator_type m_allocator;
275 dynamic_info *m_content;
280 m_content = new dynamic_info(m_allocator);
282 else if( m_content->m_ref_count > 1 )
284 dynamic_info *new_cont = new dynamic_info(*m_content);
285 m_content->m_ref_count --;
286 m_content = new_cont;
293 void release_content() {
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);
306 typedef basic_string<char> string;