9 #include "cstdio" // for EOF
16 template <class T, class Spc>
17 struct __basic_char_traits: public Spc {
19 typedef streamoff off_type;
20 typedef streampos pos_type;
21 typedef mbstate_t state_type;
22 static void assign(char_type &c1, const char_type &c2){ c1 = c2; }
23 static bool eq(const char_type &c1, const char_type &c2){ return c1 == c2; }
24 static bool lt(const char_type &c1, const char_type &c2){ return c1 < c2; }
26 static int compare(const char_type *s1, const char_type *s2, size_t n)
28 for (size_t i=0; i<n; ++i){
29 if (lt(s1[i], s2[i])){
31 } else if (lt(s2[i], s1[i])){
38 static size_t length(const char_type *s)
47 static const char_type find(const char_type *s, size_t n, const char_type &a)
49 for (size_t i=0; i<n; ++i){
57 static char_type *move(char_type *s1, const char_type *s2, size_t n)
59 return static_cast<char_type *>(__builtin_memmove(s1, s2, n * sizeof(char_type)));
62 static char_type *copy(char_type *s1, const char_type *s2, size_t n)
64 std::copy(s2, s2 + n, s1);
68 static char_type *assign(char_type *s, size_t n, char_type a)
74 static char_type to_char_type(const typename Spc::int_type &c)
79 static typename Spc::int_type to_int_type(const char_type &c)
81 return typename Spc::int_type(c);
84 static bool eq_int_type(const typename Spc::int_type &c1, const typename Spc::int_type &c2)
89 static typename Spc::int_type not_eof(const typename Spc::int_type &c)
91 return eq_int_type(c, Spc::eof()) ? 0 : c;
96 struct __spc_char_traits;
99 struct __spc_char_traits<char> {
100 typedef int int_type;
102 static int_type eof()
109 struct __spc_char_traits<wchar_t> {
110 typedef wint_t int_type;
112 static int_type eof()
120 struct char_traits<char>: public __basic_char_traits<char, __spc_char_traits<char> > { };
123 struct char_traits<wchar_t>: public __basic_char_traits<wchar_t, __spc_char_traits<wchar_t> > { };
128 typedef char_traits<T> traits;
129 typedef allocator<T> allocator_type;
133 allocator_type allocator_;
142 void shift_(size_t pos, size_t n)
153 std::copy_backward(data_ + pos, data_ + size_, data_ + size_ + n);
157 void unshift_(size_t pos, size_t n)
167 std::copy(data_ + pos + n, data_ + size_, data_ + pos);
171 void bcheck_(const basic_string &str, size_t pos, size_t n)
173 if (pos + n > str.size()){
178 static void throw_exc();
181 static const size_t npos = -1; // O_o
183 typedef const T *const_iterator;
184 typedef std::reverse_iterator<iterator> reverse_iterator;
185 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
187 explicit basic_string()
192 basic_string(const basic_string &str)
198 basic_string(const basic_string &str, size_t pos, size_t n = npos)
204 basic_string(const T *s, size_t n)
210 basic_string(const T *s)
216 basic_string(size_t n, T c)
222 template <class InputIterator>
223 basic_string(InputIterator begin, InputIterator end)
231 allocator_.deallocate(data_, capacity_);
234 basic_string &operator = (const basic_string &str)
239 basic_string &operator = (const T *s)
244 basic_string &operator = (T c)
249 iterator begin(){ return data_; }
250 iterator end(){ return data_ + size_; }
251 reverse_iterator rbegin(){ return reverse_iterator(end()); }
252 reverse_iterator rend(){ return reverse_iterator(begin()); }
254 const_iterator begin() const { return data_; }
255 const_iterator end() const { return data_ + size_; }
256 const_reverse_iterator rbegin() const { return reverse_iterator(end()); }
257 const_reverse_iterator rend() const { return reverse_iterator(begin()); }
259 size_t size() const { return size_; }
260 size_t length() const { return size_; }
261 size_t max_size() const { return numeric_limits<size_t>::max() / sizeof(T); }
262 size_t capacity() const { return capacity_; }
263 bool empty() const { return size_ == 0; }
265 void reserve(size_t res_arg = 0)
267 if (res_arg > capacity_){
268 T *new_data = allocator_.allocate(res_arg + 1, data_);
269 std::copy(data_, data_ + size_, new_data);
270 new_data[res_arg] = T();
271 allocator_.deallocate(data_, capacity_);
277 void resize(size_t n, T c)
282 std::fill_n(data_ + size_, n - size_, c);
290 void resize(size_t n)
300 const T &operator [] (size_t pos) const
305 T &operator [] (size_t pos)
310 const char &at(size_t pos) const
312 if (pos >= 0 && pos < size_){
319 basic_string &operator += (const basic_string &str)
324 basic_string &operator += (const T *s)
329 basic_string &operator += (T c)
334 // string operations - iterator forms
336 template <class InputIterator>
337 basic_string &append(InputIterator first, InputIterator last)
339 size_t n = distance(first, last);
341 std::copy(first, last, data_ + size_);
346 template <class InputIterator>
347 basic_string &assign(InputIterator begin, InputIterator end)
349 size_t s_len = distance(begin, end);
351 std::copy(begin, end, data_);
356 template <class InputIterator>
357 void insert(iterator p, InputIterator first, InputIterator last)
359 size_t pos = p - begin();
360 shift_(pos, distance(first, last));
361 std::copy(first, last, data_ + pos);
364 iterator erase(iterator first, iterator last)
366 size_t pos = first = begin();
367 unshift_(pos, distance(first, last));
368 return begin() + pos;
371 template <class InputIterator>
372 basic_string &replace(iterator i1, iterator i2, InputIterator j1, InputIterator j2)
374 size_t i_len = distance(i1, i2),
375 j_len = distance(j1, j2),
376 i1_pos = i1 - begin(),
377 i2_pos = i2 - begin();
380 shift_(i2_pos, j_len - i_len);
383 unshift_(i1_pos + j_len, i_len - j_len);
385 std::copy(j1, j2, data_ + i1_pos);
389 // other forms of the same operations
391 basic_string &append(const basic_string &str)
393 return append(str.begin(), str.end());
396 basic_string &append(const basic_string &str, size_t pos, size_t n)
398 bcheck_(str, pos, n);
399 return append(str.begin() + pos, str.begin() + pos + n);
402 basic_string &append(const T *s, size_t n)
404 return append(s, s + n);
407 basic_string &append(const T *s)
409 return append(s, s + traits::length(s));
412 basic_string &append(size_t n, char c)
414 return append(value_iterator<T>(c, 0), value_iterator<T>(c, n));
422 basic_string &assign(const basic_string &str)
424 return assign(str.begin(), str.end());
427 basic_string &assign(const basic_string &str, size_t pos, size_t n)
429 bcheck_(str, pos, n);
430 return assign(str.begin() + pos, str.begin() + pos + n);
433 basic_string &assign(const T *s, size_t n)
435 return assign(s, s + n);
438 basic_string &assign(const T *s)
440 return assign(s, s + traits::length(s));
443 basic_string &assign(size_t n, T c)
445 return assign(value_iterator<T>(c, 0), value_iterator<T>(c, n));
448 basic_string &insert(size_t pos, const basic_string &str)
450 insert(begin() + pos, str.begin(), str.end());
454 basic_string &insert(size_t pos, const basic_string &str, size_t pos2, size_t n)
456 bcheck_(str, pos2, n);
457 insert(begin() + pos, str.begin() + pos2, str.begin() + pos2 + n);
461 basic_string &insert(size_t pos, const T *s, size_t n)
463 insert(begin() + pos, s, s + n);
467 basic_string &insert(size_t pos, const T *s)
469 insert(begin() + pos, s, s + traits::length(s));
473 basic_string &insert(size_t pos, size_t n, T c)
475 insert(begin() + pos, value_iterator<T>(c, 0), value_iterator<T>(c, n));
479 iterator insert(iterator p, char c)
481 size_t pos = p - begin();
482 insert(p, value_iterator<T>(c, 0), value_iterator<T>(c, 1));
483 return begin() + pos;
486 void insert(iterator p, size_t n, char c)
488 insert(p, value_iterator<T>(c, 0), value_iterator<T>(c, n));
491 basic_string &erase(size_t pos = 0, size_t n = npos)
496 erase(begin() + pos, begin() + pos + n);
500 iterator erase(iterator position)
502 size_t pos = position - begin();
503 erase(position, position + 1);
504 return begin() + pos;
507 basic_string &replace(size_t pos1, size_t n1, const basic_string &str)
509 return replace(begin() + pos1, begin() + pos1 + n1, str.begin(), str.end());
512 basic_string &replace(iterator i1, iterator i2, const basic_string &str)
514 return replace(i1, i2, str.begin(), str.end());
517 basic_string &replace(size_t pos1, size_t n1, const basic_string &str, size_t pos2, size_t n2)
519 bcheck_(str, pos2, n2);
520 return replace(begin() + pos1, begin() + pos1 + n1, str.begin() + pos2, str.begin() + pos2 + n2);
523 basic_string &replace(size_t pos1, size_t n1, const T *s, size_t n2)
525 return replace(begin() + pos1, begin() + pos1 + n1, s, s + n2);
528 basic_string &replace(iterator i1, iterator i2, const T *s, size_t n2)
530 return replace(i1, i2, s, s + n2);
533 basic_string &replace(size_t pos1, size_t n1, const T *s)
535 return replace(begin() + pos1, begin() + pos1 + n1, s, s + traits::length(s));
538 basic_string &replace(iterator i1, iterator i2, const T *s)
540 return replace(i1, i2, s, s + traits::length(s));
543 basic_string &replace(size_t pos1, size_t n1, size_t n2, T c)
545 return replace(begin() + pos1, begin() + pos1 + n1,
546 value_iterator<T>(c, 0), value_iterator<T>(c, n2));
549 basic_string &replace(iterator i1, iterator i2, size_t n2, T c)
551 return replace(i1, i2, value_iterator<T>(c, 0), value_iterator<T>(c, n2));
554 size_t copy(T *s, size_t n, size_t pos = 0) const
556 if (n > size_ - pos){
559 std::copy(begin() + pos, begin() + pos + n, s);
563 void swap(basic_string &str)
565 T *data_copy = data_;
566 size_t size_copy = size_;
567 size_t capacity_copy = capacity_;
571 capacity_ = str.capacity_;
573 str.data_ = data_copy;
574 str.size_ = size_copy;
575 str.capacity_ = capacity_copy;
578 const T *c_str() const
580 // NOTE: string is always
581 // kept null-terminated anyway
585 const T *data() const
590 allocator<T> get_allocator() const
595 // TODO: find, substr, etc. etc.
599 typedef basic_string<char> string;