/****************************************************************************** Trick Library 'ax' 補助文字列クラステンプレートヘッダファイル Copyright(C) 2008 Wraith. All rights reserved. Coded by Wraith in Jun 5, 2008. ******************************************************************************/ /////////////////////////////////////////////////////////////////////////////// // // ■ axstring.h // http://tricklib.com/cxx/ax/axstring.h // // □ 関連ファイル // http://tricklib.com/cxx/ax/axconfig.h // http://tricklib.com/cxx/ax/axexcept.h // http://tricklib.com/cxx/ax/axmemory.h // http://tricklib.com/cxx/ax/axiterat.h // // □ ライセンス情報 // http://tricklib.com/license.htm // // ★ このファイルはC++標準ライブラリの 相当のものになり、規格票 //  (ISO/IEC 14882, JIS X 3014)の 21 章に基づき実装されています。 // #if !defined(TRICKLIB_AX_AXSTRING_H) #define TRICKLIB_AX_AXSTRING_H #include "axconfig.h" #include "axiterat.h" #include "axmemory.h" #include #include #include #if !defined(TRICKLIB_ADJUST_TYPENAME) #if defined(__GNUC__) #define TRICKLIB_ADJUST_TYPENAME typename #else #define TRICKLIB_ADJUST_TYPENAME #endif #endif namespace tricklib { namespace ax { inline void ax_throw_out_of_range(const char * a_what = "Out Of Range Exception"); inline void ax_throw_length_error(const char * a_what = "Length Error Exception"); template struct larger_int { typedef int int_type; }; #if defined(__BORLANDC__) && 0x550 <= __BORLANDC__ # pragma warn -8027 #endif template struct char_traits { typedef char_T char_type; typedef typename larger_int::int_type int_type; //typedef streamoff off_type; //typedef streampos pos_type; // off type 及びpos type に対する要件は,27.1.2 で規定する。 //typedef mbstate_t state_type; // state type は,型CopyConstructible(20.1.3)に対する要件を満たしていなければならない。 static void assign(char_type & c1, const char_type & c2) { c1 = c2; } static bool eq(const char_type & c1, const char_type & c2) { return c1 == c2; } static bool lt(const char_type & c1, const char_type & c2) { return c1 < c2; } static int compare(const char_type * s1, const char_type * s2, size_t n) { assert(NULL != s1); assert(NULL != s2); for(size_t i = 0; i < n; ++i) { if (!eq(s1[i], s2[i])) { return lt(s1[i], s2[i]) ? -1: 1; } } return 0; } static size_t length(const char_type * s) { assert(NULL != s); size_t i = 0; while(char_type() != s[i]) { ++i; } return i; } static const char_type * find(const char_type * s, size_t n, const char_type & a) { assert(NULL != s); for(const char_type * i = s, * const end = s +n; i < end; ++i) { if (eq(*i, a)) { return i; } } return 0; } static char_type * move(char_type * s1, const char_type * s2, size_t n) { assert(NULL != s1); assert(NULL != s2); if (s1 < s2 || s2 +n < s1) { copy(s1, s2, n); } else { for(size_t i = 1; i <= n; ++i) { assign(s1[n -i], s2[n -i]); } } return s1; } static char_type * copy(char_type * s1, const char_type * s2, size_t n) { assert(NULL != s1); assert(NULL != s2); for(size_t i = 0; i < n; ++i) { assign(s1[i], s2[i]); } } static char_type * assign(char_type * s, size_t n, char_type a) { assert(NULL != s); for(size_t i = 0; i < n; ++i) { assign(s[i], a); } } static int_type not_eof(const int_type & c) { if (!eq_int_type(c, eof())) { return c; } else { return eof() +1; } } static char_type to_char_type(const int_type & c) { return static_cast(c); } static int_type to_int_type(const char_type & c) { return static_cast(c); } static bool eq_int_type(const int_type & c1, const int_type & c2) { switch((c1 == eof()) + (c2 == eof())) { case 0: return eq(to_char_type(c1), to_char_type(c2)); case 1: return false; case 2: return true; } } static int_type eof() { #if defined(_DEBUG) int static_assert[sizeof(char_type) < sizeof(int_type)]; // このアサーションに引っかかった場合は、char_type より大きな int_type // を larger_int<> の特殊化を定義することで指定してください。 #endif return -1; } }; #if defined(__BORLANDC__) && 0x550 <= __BORLANDC__ # pragma warn .8027 #endif template void call_destructor(const T * a) { a->~T(); } #if defined(TRICKLIB_AX_AVAILABLE_DEFAULT_TEMPLATE_ARGS) template, class allocator_T = allocator > #else template #endif class basic_string { public: // 型 typedef char_T char_type; #if defined(TRICKLIB_AX_AVAILABLE_DEFAULT_TEMPLATE_ARGS) typedef traits_T traits_type; typedef allocator_T allocator_type; typedef basic_string this_type; #else typedef char_traits traits_type; typedef allocator allocator_type; typedef basic_string this_type; #endif typedef typename traits_type::char_type value_type; typedef typename allocator_type::size_type size_type; typedef typename allocator_type::difference_type difference_type; typedef typename allocator_type::reference reference; typedef typename allocator_type::const_reference const_reference; typedef typename allocator_type::pointer pointer; typedef typename allocator_type::const_pointer const_pointer; typedef ax_array_iterator iterator; // 23.1 参照 typedef ax_array_iterator const_iterator; // 23.1 参照 typedef reverse_iterator const_reverse_iterator; typedef reverse_iterator reverse_iterator; static const size_type npos; // 21.3.1 構築/コピー/代入 explicit basic_string(const allocator_type & a = allocator_type()) :value(NULL) { init(default_reserve_size, a); set_content_size(0); } basic_string(const this_type & a) :value(NULL) { const size_type a_size = a.size(); init(calc_afforded_size(a_size)); traits_type::copy(value, a.value, a_size); set_content_size(a_size); } basic_string(const this_type & str, size_type pos, size_type n = npos, const allocator_type & a = allocator_type()) :value(NULL) { const size_type str_size = str.size(); if (str_size < pos) { ax_throw_out_of_range("Out Of Range in basic_string::basic_string()"); } size_type str_content_size = str_size -pos; if (npos != n && n < str_content_size) { str_content_size = n; } init(calc_afforded_size(str_content_size), a); traits_type::copy(value, str.value +pos, str_content_size); set_content_size(str_content_size); } basic_string(const char_type * s, size_type n, const allocator_type& a = allocator_type()) { assert(NULL != s); init(calc_afforded_size(n), a); traits_type::copy(value, s, n); set_content_size(n); } basic_string(const char_type * s, const allocator_type& a = allocator_type()) { assert(NULL != s); size_type n = traits_type::length(s); init(calc_afforded_size(n), a); traits_type::copy(value, s, n); set_content_size(n); } basic_string(size_type n, char_type c, const allocator_type& a = allocator_type()) { init(calc_afforded_size(n), a); traits_type::assign(value, n, c); set_content_size(n); } #if TRICKLIB_AX_AVAILABLE_MEMBER_TEMPLATES template basic_string(InputIterator a_begin, InputIterator a_end, const allocator_type& a = allocator_type()) { size_type n = distance(a_begin, a_end); init(calc_afforded_size(n), a); iterator i = begin(); while(a_begin != a_end) { *i = *a_begin; ++a_begin; } set_content_size(n); } #else basic_string(const_iterator a_begin, const_iterator a_end, const allocator_type& a = allocator_type()) { size_type n = tricklib::ax::distance(a_begin, a_end); init(calc_afforded_size(n), a); iterator i = begin(); while(a_begin != a_end) { *i = *a_begin; ++a_begin; } set_content_size(n); } basic_string(const_reverse_iterator a_begin, const_reverse_iterator a_end, const allocator_type& a = allocator_type()) { size_type n = tricklib::ax::distance(a_begin, a_end); init(calc_afforded_size(n), a); iterator i = begin(); while(a_begin != a_end) { *i = *a_begin; ++a_begin; } set_content_size(n); } #endif ~basic_string() { uninit(); } this_type & operator = (const this_type & a) { this_type temp(a); swap(temp); return *this; } this_type & operator = (const char_type * a) { this_type temp(a); swap(temp); return *this; } this_type & operator = (char_type a) { this_type temp(1, a); swap(temp); return *this; } // 21.3.2 反復子 iterator begin() { return iterator(value); } const_iterator begin() const { return const_iterator(value); } iterator end() { return iterator(value +size()); } const_iterator end() const { return const_iterator(value +size()); } reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } // 21.3.3 容量 size_type size() const { return content_size(); } size_type length() const { return size(); } size_type max_size() const { return my_allocator().max_size(); } void resize(size_type n, char_type c) { if (max_size() < n) { ax_throw_length_error("Length Error in basic_string::resize()"); } const size_type current_size = size(); if (current_size < n) { if (reserve_size() < calc_afforded_size(n)) { this_type temp(n, my_allocator()); traits_type::copy(temp.value, value, current_size +1); traits_type::assign(temp.value +current_size, n -current_size, c); swap(temp); } else { traits_type::assign(value +current_size, n -current_size, c); set_content_size(n); } } else if (current_size != n) { set_content_size(n); } } void resize(size_type n) { resize(n, char_type()); } size_type capacity() const { return reserve_size(); } void reserve(size_type res_arg = 0) { if (max_size() < res_arg) { ax_throw_length_error("Length Error in basic_string::reserve()"); } const size_type current_size = size(); if (current_size < res_arg) { this_type temp(res_arg, char_type(), my_allocator()); traits_type::copy(temp.value, value, current_size); swap(temp); } else if (calc_afforded_size(current_size) < reserve_size()) { this_type temp(data(), size(), my_allocator()); swap(temp); } } void clear() { set_content_size(0); } bool empty() const { return 0 == size(); } // 21.3.4 要素へのアクセス const_reference operator[](size_type pos) const { #if 0 // 規格上はこのディレクティブ内のコードのような処理を行うことになって // いるが、この basic_string の実装では常に char_type() == value[size()] // が成立するようになっているなっているのでこのようなコードは不要。 if (pos == size()) { return char_type(); } #endif return value[pos]; } reference operator[](size_type pos) { return value[pos]; } const_reference at(size_type pos) const { if (size() <= pos) { ax_throw_out_of_range("Out Of Range in basic_string::at()"); } return value[pos]; } reference at(size_type pos) { if (size() <= pos) { ax_throw_out_of_range("Out Of Range in basic_string::at()"); } return value[pos]; } // 21.3.5 変更子 this_type & operator += (const this_type & a) { return append(a); } this_type & operator += (const char_type * a) { return append(a); } this_type & operator += (char_type a) { return append(1, a); } this_type & append(const this_type & a) { size_type new_size = size() +a.size(); reserve(new_size); traits_type::copy(value, a.value, a.size()); set_content_size(new_size); return *this; } this_type & append(const this_type & a, size_type a_pos, size_type a_n) { if (size() < a_pos) { ax_throw_out_of_range("Out Of Range in basic_string::append()"); } size_type copy_size = a.size() -a_pos; if (a_n < copy_size) { copy_size = a_n; } if (npos -copy_size <= size()) { ax_throw_length_error("Length Error in basic_string::append()"); } reserve_for_append(size() +copy_size); traits_type::copy(value, a.value +a_pos, copy_size); return *this; } this_type & append(const char_type * s, size_type n) { return append(this_type(s, n)); } this_type & append(const char_type * s) { return append(this_type(s)); } this_type & append(size_type n, char_type c) { return append(this_type(n, c)); } #if TRICKLIB_AX_AVAILABLE_MEMBER_TEMPLATES template this_type & append(InputIterator first, InputIterator last) { return append(this_type(first, last)); } #else this_type & append(const_iterator first, const_iterator last) { return append(this_type(first, last)); } this_type & append(const_reverse_iterator first, const_reverse_iterator last) { return append(this_type(first, last)); } #endif void push_back(char_type c) { append(1, c); } this_type & assign(const this_type & a) { size_type copy_size = a.size(); reserve_for_assign(copy_size); traits_type::copy(value, a.value, copy_size); return *this; } this_type & assign(const basic_string& a, size_type a_pos, size_type a_n) { if (size() < a_pos) { ax_throw_out_of_range("Out Of Range in basic_string::append()"); } size_type copy_size = a.size() -a_pos; if (a_n < copy_size) { copy_size = a_n; } reserve_for_assign(copy_size); traits_type::copy(value, a.value +a_pos, copy_size); return *this; } this_type & assign(const char_type * a_value, size_type a_size) { reserve_for_assign(a_size); traits_type::copy(value, a_value, a_size); return *this; } this_type & assign(const char_type * s) { size_type copy_size = traits_type::length(s); reserve_for_assign(copy_size); traits_type::copy(value, s, copy_size); return *this; } this_type & assign(size_type a_size, char_type c) { reserve_for_assign(a_size); traits_type::assign(value, a_size, c); return *this; } #if TRICKLIB_AX_AVAILABLE_MEMBER_TEMPLATES template this_type & assign(InputIterator first, InputIterator last) { return assign(this_type(first, last)); } #else this_type & assign(const_iterator first, const_iterator last) { return assign(this_type(first, last)); } this_type & assign(const_reverse_iterator first, const_reverse_iterator last) { return assign(this_type(first, last)); } #endif this_type & insert(size_type this_pos, const this_type & a) { if (size() < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::insert()"); } size_type current_size = size(); size_type a_size = a.size(); size_type new_size = current_size +a_size; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::copy(temp.value +this_pos, a.value, a_size); traits_type::copy(temp.value +this_pos +a_size, value +this_pos, current_size -this_pos); swap(temp); } else { traits_type::copy(value +this_pos +a_size, value +this_pos, current_size -this_pos); traits_type::copy(value +this_pos, a.value, a_size); set_content_size(new_size); } return *this; } this_type & insert(size_type this_pos, const this_type & a, size_type a_pos, size_type a_n) { if (size() < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::insert()"); } size_type a_size = a.size(); if (a_size < a_pos) { ax_throw_out_of_range("Out Of Range in basic_string::insert()"); } size_type current_size = size(); size_type insert_size = a_size -a_pos; if (a_n < insert_size) { insert_size = a_n; } size_type new_size = current_size +insert_size; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::copy(temp.value +this_pos, a.value +a_pos, insert_size); traits_type::copy(temp.value +this_pos +insert_size, value +this_pos, current_size -this_pos); swap(temp); } else { traits_type::copy(value +this_pos +insert_size, value +this_pos, current_size -this_pos); traits_type::copy(value +this_pos, a.value +a_pos, insert_size); set_content_size(new_size); } return *this; } this_type & insert(size_type this_pos, const char_type * a_value, size_type a_n) { if (size() < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::insert()"); } size_type current_size = size(); size_type new_size = current_size +a_n; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::copy(temp.value +this_pos, a_value, a_n); traits_type::copy(temp.value +this_pos +a_n, value +this_pos, current_size -this_pos); swap(temp); } else { traits_type::copy(value +this_pos +a_n, value +this_pos, current_size -this_pos); traits_type::copy(value +this_pos, a_value, a_n); set_content_size(new_size); } return *this; } this_type & insert(size_type this_pos, const char_type * a_value) { return insert(this_pos, a_value, traits_type::length(a_value)); } this_type & insert(size_type this_pos, size_type a_n, char_type c) { if (size() < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::insert()"); } size_type current_size = size(); size_type new_size = current_size +a_n; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::assign(temp.value +this_pos, a_n, c); traits_type::copy(temp.value +this_pos +a_n, value +this_pos, current_size -this_pos); swap(temp); } else { traits_type::copy(value +this_pos +a_n, value +this_pos, current_size -this_pos); traits_type::assign(value +this_pos, a_n, c); set_content_size(new_size); } return *this; } iterator insert(iterator p, char_type c) { size_type this_pos = value -p.value; insert(this_pos, 1, c); return value +this_pos; } void insert(iterator p, size_type n, char_type c) { insert(value -p.value, n, c); } #if TRICKLIB_AX_AVAILABLE_MEMBER_TEMPLATES template void insert(iterator p, InputIterator first, InputIterator last) { insert(value -p.value, this_type(first, last)); } #else void insert(iterator p, const_iterator first, const_iterator last) { insert(value -p.value, this_type(first, last)); } void insert(iterator p, const_reverse_iterator first, const_reverse_iterator last) { insert(value -p.value, this_type(first, last)); } #endif this_type & erase(size_type a_pos = 0, size_type a_n = npos) { size_type current_size = size(); if (current_size < a_pos) { ax_throw_out_of_range("Out Of Range in basic_string::erase()"); } size_type erase_size = current_size -a_pos; if (a_n < erase_size) { erase_size = a_n; } traits_type::copy(value +a_pos, value +a_pos +erase_size, current_size -(a_pos +erase_size)); set_content_size(current_size -erase_size); return *this; } iterator erase(iterator p) { size_type current_size = size(); size_type a_pos = value -p.value; traits_type::copy(value +a_pos, value +a_pos +1, current_size -(a_pos +1)); set_content_size(current_size -1); return value +a_pos; } iterator erase(iterator first, iterator last) { size_type current_size = size(); size_type a_pos = value -first.value; size_type erase_size = last.value -first.value; traits_type::copy(value +a_pos, value +a_pos +erase_size, current_size -(a_pos +erase_size)); set_content_size(current_size -erase_size); return value +a_pos; } this_type & replace(size_type this_pos, size_type this_n, const this_type & a) { size_type current_size = size(); if (current_size < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::replace()"); } size_type erase_size = current_size -this_pos; if (this_n < erase_size) { erase_size = this_n; } size_type a_size = a.size(); size_type new_size = current_size +a_size -erase_size; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::copy(temp.value +this_pos, a.value, a_size); traits_type::copy(temp.value +this_pos +a_size, value +this_pos +erase_size, current_size -(this_pos +erase_size)); swap(temp); } else { traits_type::copy(value +this_pos +a_size, value +this_pos +erase_size, current_size -(this_pos +erase_size)); traits_type::copy(value +this_pos, a.value, a_size); set_content_size(new_size); } return *this; } this_type & replace(size_type this_pos, size_type this_n, const this_type & a, size_type a_pos, size_type a_n) { size_type current_size = size(); if (current_size < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::replace()"); } size_type a_size = a.size(); if (a_size < a_pos) { ax_throw_out_of_range("Out Of Range in basic_string::replace()"); } size_type erase_size = current_size -this_pos; if (a_n < erase_size) { erase_size = a_n; } size_type copy_size = a_size -a_pos; if (a_n < copy_size) { copy_size = a_n; } if (npos -copy_size <= current_size -erase_size) { ax_throw_length_error("Length Error in basic_string::replace()"); } size_type new_size = current_size +copy_size -erase_size; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::copy(temp.value +this_pos, a.value, copy_size); traits_type::copy(temp.value +this_pos +copy_size, value +this_pos +erase_size, current_size -(this_pos +erase_size)); swap(temp); } else { traits_type::copy(value +this_pos +copy_size, value +this_pos +erase_size, current_size -(this_pos +erase_size)); traits_type::copy(value +this_pos, a.value, copy_size); set_content_size(new_size); } return *this; } this_type & replace(size_type this_pos, size_type this_n, const char_type * a_value, size_type a_n) { size_type current_size = size(); if (current_size < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::replace()"); } size_type erase_size = current_size -this_pos; if (a_n < erase_size) { erase_size = a_n; } if (npos -a_n <= current_size -erase_size) { ax_throw_length_error("Length Error in basic_string::replace()"); } size_type new_size = current_size +a_n -erase_size; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::copy(temp.value +this_pos, a_value, a_n); traits_type::copy(temp.value +this_pos +a_n, value +this_pos +erase_size, current_size -(this_pos +erase_size)); swap(temp); } else { traits_type::copy(value +this_pos +a_n, value +this_pos +erase_size, current_size -(this_pos +erase_size)); traits_type::copy(value +this_pos, a_value, a_n); set_content_size(new_size); } return *this; } this_type & replace(size_type this_pos, size_type this_n, const char_type * a_value) { return replace(this_pos, this_n, a_value, traits_type::length(a_value)); } this_type & replace(size_type this_pos, size_type this_n, size_type a_n, char_type a_c) { size_type current_size = size(); if (current_size < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::replace()"); } size_type erase_size = current_size -this_pos; if (a_n < erase_size) { erase_size = a_n; } if (npos -a_n <= current_size -erase_size) { ax_throw_length_error("Length Error in basic_string::replace()"); } size_type new_size = current_size +a_n -erase_size; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::assign(temp.value +this_pos, a_n, a_c); traits_type::copy(temp.value +this_pos +a_n, value +this_pos +erase_size, current_size -(this_pos +erase_size)); swap(temp); } else { traits_type::copy(value +this_pos +a_n, value +this_pos +erase_size, current_size -(this_pos +erase_size)); traits_type::assign(value +this_pos, a_n, a_c); set_content_size(new_size); } return *this; } this_type & replace(iterator i1, iterator i2, const this_type & a) { size_type current_size = size(); size_type this_pos = i1.value - value; size_type erase_size = i2.value -i1.value; size_type a_size = a.size(); size_type new_size = current_size +a_size -erase_size; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::copy(temp.value +this_pos, a.value, a_size); traits_type::copy(temp.value +this_pos +a_size, value +this_pos +erase_size, current_size -(this_pos +erase_size)); swap(temp); } else { traits_type::copy(value +this_pos +a_size, value +this_pos +erase_size, current_size -(this_pos +erase_size)); traits_type::copy(value +this_pos, a.value, a_size); set_content_size(new_size); } return *this; } this_type & replace(iterator i1, iterator i2, const char_type * a_value, size_type a_n) { size_type current_size = size(); size_type this_pos = i1.value - value; size_type erase_size = i2.value -i1.value; size_type new_size = current_size +a_n -erase_size; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::copy(temp.value +this_pos, a_value, a_n); traits_type::copy(temp.value +this_pos +a_n, value +this_pos +erase_size, current_size -(this_pos +erase_size)); swap(temp); } else { traits_type::copy(value +this_pos +a_n, value +this_pos +erase_size, current_size -(this_pos +erase_size)); traits_type::copy(value +this_pos, a_value, a_n); set_content_size(new_size); } return *this; } this_type & replace(iterator i1, iterator i2, const char_type * a_value) { return replace(i1, i2, a_value, traits_type::length(a_value)); } this_type & replace(iterator i1, iterator i2, size_type a_n, char_type a_c) { size_type current_size = size(); size_type this_pos = i1.value - value; size_type erase_size = i2.value -i1.value; size_type new_size = current_size +a_n -erase_size; if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, this_pos); traits_type::assign(temp.value +this_pos, a_n, a_c); traits_type::copy(temp.value +this_pos +a_n, value +this_pos +erase_size, current_size -(this_pos +erase_size)); swap(temp); } else { traits_type::copy(value +this_pos +a_n, value +this_pos +erase_size, current_size -(this_pos +erase_size)); traits_type::assign(value +this_pos, a_n, a_c); set_content_size(new_size); } return *this; } #if TRICKLIB_AX_AVAILABLE_MEMBER_TEMPLATES template this_type & replace(iterator i1, iterator i2, InputIterator j1, InputIterator j2) { return replace(i1, i2, this_type(j1, j2)); } #else this_type & replace(iterator i1, iterator i2, const_iterator j1, const_iterator j2) { return replace(i1, i2, this_type(j1, j2)); } this_type & replace(iterator i1, iterator i2, const_reverse_iterator j1, const_reverse_iterator j2) { return replace(i1, i2, this_type(j1, j2)); } #endif size_type copy(char_type * a_value, size_type a_n, size_type this_pos = 0) const { size_type current_size = size(); if (current_size < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::copy()"); } size_type copy_size = current_size -this_pos; if (a_n < copy_size) { copy_size = a_n; } traits_type::copy(a_value, value, copy_size); return copy_size; } void swap(this_type & a) { char_type * const temp_value = value; value = a.value; a.value = temp_value; } // 21.3.6 文字列操作 const char_type * c_str() const { return value; } const char_type * data() const { return value; } allocator_type get_allocator() const { return my_allocator(); } size_type find(const this_type & a, size_type this_pos = 0) const { return find(a.value, this_pos, a.size()); } size_type find(const char_type * a_value, size_type this_pos, size_type a_n) const { for(size_type i = this_pos, end = size() -(a_n -1); i < end; ++i) { size_type j = 0; while(true) { if (a_n <= j) { return i; } if (!traits_type::eq(value[i +j], a_value[j])) { break; } ++j; } } return npos; } size_type find(const char_type * a_value, size_type this_pos = 0) const { return find(a_value, this_pos, traits_type::length(a_value)); } size_type find(char_type a_c, size_type this_pos = 0) const { return find(&a_c, this_pos, 1); } size_type rfind(const this_type & a, size_type this_pos = npos) const { return rfind(a.value, this_pos, a.size()); } size_type rfind(const char_type * a_value, size_type this_pos, size_type a_n) const { if (0 == a_n) { if (npos == this_pos) { return size(); } else { return this_pos; } } else if (a_n < size()) { return npos; } size_type i = size() -a_n; if (this_pos < i) { i = this_pos; } while(true) { size_type j = 0; while(true) { if (a_n <= j) { return i; } if (!traits_type::eq(value[i +j], a_value[j])) { break; } ++j; } if (0 == i) { break; } --i; } return npos; } size_type rfind(const char_type * a_value, size_type this_pos = npos) const { return rfind(a_value, this_pos, traits_type::length(a_value)); } size_type rfind(char_type a_c, size_type this_pos = npos) const { return rfind(&a_c, this_pos, 1); } size_type find_first_of(const this_type & a, size_type this_pos = 0) const { return find_first_of(a.value, this_pos, a.size()); } size_type find_first_of(const char_type * a_value, size_type this_pos, size_type a_n) const { for(size_type i = this_pos, end = size(); i < end; ++i) { char_type c = value[i]; for(size_type j = 0; j < a_n; ++j) { if (traits_type::eq(c, a_value[j])) { return i; } } } return npos; } size_type find_first_of(const char_type * a_value, size_type this_pos = 0) const { return find_first_of(a_value, this_pos, traits_type::length(a_value)); } size_type find_first_of(char_type a_c, size_type this_pos = 0) const { return find_first_of(&a_c, this_pos, 1); } size_type find_last_of(const this_type & a, size_type this_pos = npos) const { return find_last_of(a.value, this_pos, a.size()); } size_type find_last_of(const char_type * a_value, size_type this_pos, size_type a_n) const { size_type i = size(); if (this_pos < i) { i = this_pos; } while(i-- != 0) { char_type c = value[i]; for(size_type j = 0; j < a_n; ++j) { if (traits_type::eq(c, a_value[j])) { return i; } } } return npos; } size_type find_last_of(const char_type * a_value, size_type this_pos = npos) const { return find_last_of(a_value, this_pos, traits_type::length(a_value)); } size_type find_last_of(char_type a_c, size_type this_pos = npos) const { return find_last_of(&a_c, this_pos, 1); } size_type find_first_not_of(const this_type & a, size_type this_pos = 0) const { return find_first_not_of(a.value, this_pos, a.size()); } size_type find_first_not_of(const char_type * a_value, size_type this_pos, size_type a_n) const { for(size_type i = this_pos, end = size(); i < end; ++i) { char_type c = value[i]; for(size_type j = 0; j < a_n; ++j) { if (!traits_type::eq(c, a_value[j])) { return i; } } } return npos; } size_type find_first_not_of(const char_type * a_value, size_type this_pos = 0) const { return find_first_not_of(a_value, this_pos, traits_type::length(a_value)); } size_type find_first_not_of(char_type a_c, size_type this_pos = 0) const { return find_first_not_of(&a_c, this_pos, 1); } size_type find_last_not_of(const this_type & a, size_type this_pos = npos) const { return find_last_not_of(a.value, this_pos, a.size()); } size_type find_last_not_of(const char_type * a_value, size_type this_pos, size_type a_n) const { size_type i = size(); if (this_pos < i) { i = this_pos; } while(i-- != 0) { char_type c = value[i]; for(size_type j = 0; j < a_n; ++j) { if (!traits_type::eq(c, a_value[j])) { return i; } } } return npos; } size_type find_last_not_of(const char_type * a_value, size_type this_pos = npos) const { return find_last_not_of(a_value, this_pos, traits_type::length(a_value)); } size_type find_last_not_of(char_type a_c, size_type this_pos = npos) const { return find_last_not_of(&a_c, this_pos, 1); } this_type substr(size_type this_pos = 0, size_type a_n = npos) const { size_type current_size = size(); if (current_size < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::substr()"); } size_type copy_size = current_size -this_pos; if (a_n < copy_size) { copy_size = a_n; } return this_type(value +this_pos, copy_size); } int compare(const this_type & a) const { size_t current_size = size(); size_t a_size = a.size(); size_t common_size = current_size; if (a_size < common_size) { common_size = a_size; } int common_result = traits_type::compare(value, a.value, common_size); if (common_result) { return common_result; } if (current_size != common_size) { return 1; } else if (current_size == a_size) { return 0; } else { return -1; } } int compare(size_type this_pos, size_type this_n, const this_type & a) const { return compare(this_pos, this_n, a.value, a.size()); } int compare(size_type this_pos, size_type this_n, const this_type & a, size_type a_pos, size_type a_n) const { size_type compare_size = a.size(); if (a_n < compare_size) { compare_size = a_n; } return compare(this_pos, this_n, a.value +a_pos, compare_size); } int compare(const char_type * a_value) const { size_t current_size = size(); size_t a_size = traits_type::length(a_value); size_t common_size = current_size; if (a_size < common_size) { common_size = a_size; } int common_result = traits_type::compare(value, a_value, common_size); if (common_result) { return common_result; } if (current_size != common_size) { return 1; } else if (current_size == a_size) { return 0; } else { return -1; } } int compare(size_type this_pos, size_type this_n, const char_type * a_value) const { return compare(this_pos, this_n, a_value, traits_type::length(a_value)); } int compare(size_type this_pos, size_type this_n, const char_type * a_value, size_type a_n) const { size_t current_size = size(); if (current_size < this_pos) { ax_throw_out_of_range("Out Of Range in basic_string::compare()"); } size_t a_size = a_n; current_size -= this_pos; size_t common_size = current_size; if (a_size < common_size) { common_size = a_size; } int common_result = traits_type::compare(value +this_pos, a_value, common_size); if (common_result) { return common_result; } if (current_size != common_size) { return 1; } else if (current_size == a_size) { return 0; } else { return -1; } } private: char_type * value; static const size_type default_reserve_size; static const size_type buffersize_property_size; static const size_type datasize_property_size; static const size_type allocator_property_size; static const size_type properties_size; void init(size_type a_reserve_size = default_reserve_size, const allocator_type & a = allocator_type()) { // メモリの確保 value = allocator_type(a).allocate(properties_size +a_reserve_size) +properties_size; // 確保したメモリサイズの保存 reserve_size() = a_reserve_size; // 割り付け子のコピー new (reinterpret_cast(&my_allocator())) allocator_type(a); } void uninit() { if (value) { // 割り付け子のコピー allocator_type * value_allocator = &my_allocator(); allocator_type a(*value_allocator); // 割り付け子の削除 call_destructor(value_allocator); //value_allocator->~allocator_type(); // メモリの解放 a.deallocate(value -properties_size, reserve_size() +properties_size); } } static size_type calc_afforded_size(size_type a_size) { return a_size +default_reserve_size &~(default_reserve_size -1); } size_type & reserve_size() { return *reinterpret_cast(value -properties_size); } const size_type & reserve_size() const { return *reinterpret_cast(value -properties_size); } size_type & content_size() { return *reinterpret_cast(value -properties_size +buffersize_property_size); } const size_type & content_size() const { return *reinterpret_cast(value -properties_size +buffersize_property_size); } allocator_type & my_allocator() { return *reinterpret_cast(value -allocator_property_size); } const allocator_type & my_allocator() const { return *reinterpret_cast(value -allocator_property_size); } void set_content_size(size_type a_size) { content_size() = a_size; value[a_size] = 0; } basic_string(size_type n, const allocator_type& a) { init(calc_afforded_size(n), a); set_content_size(n); } void reserve_for_assign(size_type new_size) { if (max_size() < new_size) { ax_throw_length_error("Length Error in basic_string::reserve_for_assign()"); } if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); swap(temp); } } void reserve_for_append(size_type new_size) { if (max_size() < new_size) { ax_throw_length_error("Length Error in basic_string::reserve_for_append()"); } if (reserve_size() < calc_afforded_size(new_size)) { this_type temp(new_size, my_allocator()); traits_type::copy(temp.value, value, size()); swap(temp); } } }; #if defined(TRICKLIB_AX_AVAILABLE_DEFAULT_TEMPLATE_ARGS) // // 21.3.7.2 operator+ // template inline basic_string operator+(const basic_string & lhs, const basic_string & rhs) { return basic_string(lhs).append(rhs); } template inline basic_string operator+(const char_T * lhs, const basic_string & rhs) { return basic_string(lhs).append(rhs); } template inline basic_string operator+(char_T lhs, const basic_string & rhs) { return basic_string(1, lhs).append(rhs); } template inline basic_string operator+(const basic_string & lhs, const char_T * rhs) { return basic_string(lhs).append(rhs); } template inline basic_string operator+(const basic_string & lhs, char_T rhs) { return basic_string(lhs).append(1, rhs); } // // 21.3.7.2 operator== // template inline bool operator==(const basic_string & lhs, const basic_string & rhs) { return 0 == lhs.compare(rhs); } template inline bool operator==(const char_T * lhs, const basic_string & rhs) { return 0 == basic_string(lhs).compare(rhs); } template inline bool operator==(const basic_string & lhs, const char_T * rhs) { return 0 == lhs.compare(rhs); } // // 21.3.7.3 operator!= // template inline bool operator!=(const basic_string & lhs, const basic_string & rhs) { return !(lhs == rhs); } template inline bool operator!=(const char_T * lhs, const basic_string & rhs) { return !(lhs == rhs); } template inline bool operator!=(const basic_string & lhs, const char_T * rhs) { return !(lhs == rhs); } // // 21.3.7.4 operator< // template inline bool operator<(const basic_string & lhs, const basic_string & rhs) { return lhs.compare(rhs) < 0; } template inline bool operator< (const char_T * lhs, const basic_string & rhs) { return basic_string(lhs).compare(rhs) < 0; } template inline bool operator< (const basic_string & lhs, const char_T * rhs) { return lhs.compare(rhs) < 0; } // // 21.3.7.5 operator> // template inline bool operator>(basic_string & lhs, const basic_string & rhs) { return 0 < lhs.compare(rhs); } template inline bool operator> (const char_T * lhs, const basic_string & rhs) { return 0 < basic_string(lhs).compare(rhs); } template inline bool operator> (const basic_string & lhs, const char_T * rhs) { return 0 < lhs.compare(rhs); } // // 21.3.7.6 operator<= // template inline bool operator<=(const basic_string & lhs, const basic_string & rhs) { return lhs.compare(rhs) <= 0; } template inline bool operator<=(const char_T * lhs, const basic_string & rhs) { return basic_string(lhs).compare(rhs) <= 0; } template inline bool operator<=(const basic_string & lhs, const char_T * rhs) { return lhs.compare(rhs) <= 0; } // // 21.3.7.7 operator>= // template inline bool operator>=(const basic_string & lhs, const basic_string & rhs) { return 0 <= lhs.compare(rhs); } template inline bool operator>=(const char_T * lhs, const basic_string & rhs) { return 0 <= basic_string(lhs).compare(rhs); } template inline bool operator>=(const basic_string & lhs, const char_T * rhs) { return 0 <= lhs.compare(rhs); } // // 21.3.7.8 swap // template inline void swap(basic_string & lhs, basic_string & rhs) { lhs.swap(rhs); } #else // // 21.3.7.2 operator+ // template inline basic_string operator+(const basic_string & lhs, const basic_string & rhs) { return basic_string(lhs).append(rhs); } template inline basic_string operator+(const char_T * lhs, const basic_string & rhs) { return basic_string(lhs).append(rhs); } template inline basic_string operator+(char_T lhs, const basic_string & rhs) { return basic_string(1, lhs).append(rhs); } template inline basic_string operator+(const basic_string & lhs, const char_T * rhs) { return basic_string(lhs).append(rhs); } template inline basic_string operator+(const basic_string & lhs, char_T rhs) { return basic_string(lhs).append(1, rhs); } // // 21.3.7.2 operator== // template inline bool operator==(const basic_string & lhs, const basic_string & rhs) { return 0 == lhs.compare(rhs); } template inline bool operator==(const char_T * lhs, const basic_string & rhs) { return 0 == basic_string(lhs).compare(rhs); } template inline bool operator==(const basic_string & lhs, const char_T * rhs) { return 0 == lhs.compare(rhs); } // // 21.3.7.3 operator!= // template inline bool operator!=(const basic_string & lhs, const basic_string & rhs) { return !(lhs == rhs); } template inline bool operator!=(const char_T * lhs, const basic_string & rhs) { return !(lhs == rhs); } template inline bool operator!=(const basic_string & lhs, const char_T * rhs) { return !(lhs == rhs); } // // 21.3.7.4 operator< // template inline bool operator<(const basic_string & lhs, const basic_string & rhs) { return lhs.compare(rhs) < 0; } template inline bool operator< (const char_T * lhs, const basic_string & rhs) { return basic_string(lhs).compare(rhs) < 0; } template inline bool operator< (const basic_string & lhs, const char_T * rhs) { return lhs.compare(rhs) < 0; } // // 21.3.7.5 operator> // template inline bool operator>(basic_string & lhs, const basic_string & rhs) { return 0 < lhs.compare(rhs); } template inline bool operator> (const char_T * lhs, const basic_string & rhs) { return 0 < basic_string(lhs).compare(rhs); } template inline bool operator> (const basic_string & lhs, const char_T * rhs) { return 0 < lhs.compare(rhs); } // // 21.3.7.6 operator<= // template inline bool operator<=(const basic_string & lhs, const basic_string & rhs) { return lhs.compare(rhs) <= 0; } template inline bool operator<=(const char_T * lhs, const basic_string & rhs) { return basic_string(lhs).compare(rhs) <= 0; } template inline bool operator<=(const basic_string & lhs, const char_T * rhs) { return lhs.compare(rhs) <= 0; } // // 21.3.7.7 operator>= // template inline bool operator>=(const basic_string & lhs, const basic_string & rhs) { return 0 <= lhs.compare(rhs); } template inline bool operator>=(const char_T * lhs, const basic_string & rhs) { return 0 <= basic_string(lhs).compare(rhs); } template inline bool operator>=(const basic_string & lhs, const char_T * rhs) { return 0 <= lhs.compare(rhs); } // // 21.3.7.8 swap // template inline void swap(basic_string & lhs, basic_string & rhs) { lhs.swap(rhs); } #endif #if defined(TRICKLIB_AX_AVAILABLE_DEFAULT_TEMPLATE_ARGS) template const typename basic_string::size_type basic_string::npos = -1; template const typename basic_string::size_type basic_string::default_reserve_size = 16; template const typename basic_string::size_type basic_string::buffersize_property_size = sizeof(TRICKLIB_ADJUST_TYPENAME basic_string::size_type) /sizeof(char_T); template const typename basic_string::size_type basic_string::datasize_property_size = sizeof(TRICKLIB_ADJUST_TYPENAME basic_string::size_type) /sizeof(char_T); template const typename basic_string::size_type basic_string::allocator_property_size = sizeof(TRICKLIB_ADJUST_TYPENAME basic_string::allocator_type) /sizeof(char_T); template const typename basic_string::size_type basic_string::properties_size = basic_string::buffersize_property_size +basic_string::datasize_property_size +basic_string::allocator_property_size; #else template const typename basic_string::size_type basic_string::npos = -1; template const typename basic_string::size_type basic_string::default_reserve_size = 16; template const typename basic_string::size_type basic_string::buffersize_property_size = sizeof(TRICKLIB_ADJUST_TYPENAME basic_string::size_type) /sizeof(char_T); template const typename basic_string::size_type basic_string::datasize_property_size = sizeof(TRICKLIB_ADJUST_TYPENAME basic_string::size_type) /sizeof(char_T); template const typename basic_string::size_type basic_string::allocator_property_size = sizeof(TRICKLIB_ADJUST_TYPENAME basic_string::allocator_type) /sizeof(char_T); template const typename basic_string::size_type basic_string::properties_size = basic_string::buffersize_property_size +basic_string::datasize_property_size +basic_string::allocator_property_size; #endif typedef basic_string string; typedef basic_string wstring; } } #include "axexcept.h" inline void tricklib::ax::ax_throw_out_of_range(const char * a_what) { throw tricklib::ax::out_of_range(a_what); } inline void ax_throw_length_error(const char * a_what) { throw tricklib::ax::length_error(a_what); } #endif // !defined(TRICKLIB_AX_AXSTRING_H) /****************************************************************************** □■□■ Wraith the Trickster □■□■ ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ ******************************************************************************/