7 #ifndef XSTRING_H_INCLUDED 8 #define XSTRING_H_INCLUDED 29 template <
class Traits>
31 :
public std::binary_function<typename Traits::char_type,
32 typename Traits::char_type,
34 bool operator()(
const typename Traits::char_type& x,
35 const typename Traits::char_type& y)
const {
36 return Traits::eq(x, y);
40 template <
class Traits>
41 struct not_within_traits
42 :
public std::unary_function<typename Traits::char_type, bool>
44 typedef typename Traits::char_type CharT;
48 not_within_traits(
const typename Traits::char_type* f,
49 const typename Traits::char_type* l)
50 : _first(f), _last(l) {}
52 bool operator()(
const typename Traits::char_type& x)
const {
53 return find_if((CharT*)_first, (CharT*)_last,
54 bind1st(eq_traits<Traits>(), x)) == (CharT*)_last;
69 struct IsInteger {
typedef false_type query;};
71 template <>
struct IsInteger<char> {
typedef true_type query;};
72 template <>
struct IsInteger<unsigned char> {
typedef true_type query;};
73 template <>
struct IsInteger<short> {
typedef true_type query;};
74 template <>
struct IsInteger<unsigned short> {
typedef true_type query;};
75 template <>
struct IsInteger<int> {
typedef true_type query;};
76 template <>
struct IsInteger<unsigned> {
typedef true_type query;};
77 template <>
struct IsInteger<long> {
typedef true_type query;};
78 template <>
struct IsInteger<unsigned long> {
typedef true_type query;};
88 class xstring :
public Impl {
91 typedef typename Impl::value_type value_type;
92 typedef typename Impl::traits_type traits_type;
94 typedef typename Impl::pointer pointer;
95 typedef typename Impl::const_pointer const_pointer;
96 typedef typename Impl::reference reference;
97 typedef typename Impl::const_reference const_reference;
98 typedef typename Impl::size_type size_type;
99 typedef typename Impl::difference_type difference_type;
101 typedef typename Impl::const_iterator const_iterator;
102 typedef typename Impl::iterator iterator;
104 typedef typename Impl::reverse_iterator reverse_iterator;
105 typedef typename Impl::const_reverse_iterator const_reverse_iterator;
107 typedef typename Impl::allocator_type allocator_type;
111 xstring(allocator_type
const &allocator = allocator_type())
113 Impl::element_initialize(0,0);
116 xstring(xstring
const &s) : Impl(s) {}
119 xstring(std::basic_string<value_type>
const &s) {
120 Impl::range_initialize(s.begin(), s.end());
123 xstring(xstring
const &s,
124 typename Impl::size_type pos,
125 typename Impl::size_type n = npos,
126 const typename Impl::allocator_type& a = allocator_type())
129 throw std::out_of_range(
"Out of range");
130 Impl::range_initialize(s.begin() + pos,
131 s.begin() + pos + std::min(n,s.size() - pos));
134 xstring(
const value_type* s, size_type n=(size_type)(-1),
135 const allocator_type& a = _default_allocator);
137 xstring(size_type n, value_type c,
138 const allocator_type& a = _default_allocator)
140 Impl::element_initialize(n,c);
143 template <
class PossibleInputIter>
144 xstring(PossibleInputIter f, PossibleInputIter l,
145 const allocator_type& a = _default_allocator)
147 typedef typename IsInteger<PossibleInputIter>::query is_integer;
148 assign_dispatch(f, l, is_integer());
152 template <
class Integer>
153 void assign_dispatch(Integer n, Integer x, true_type) {
154 Impl::element_initialize(n,(value_type)x);
157 template <
class InputIter>
158 void assign_dispatch(InputIter f, InputIter l, false_type) {
159 Impl::range_initialize(f, l);
165 operator std::basic_string<value_type>() {
166 return std::basic_string<value_type>(this->c_str());
169 size_type length()
const {
return size();}
171 reverse_iterator rbegin()
172 {
return reverse_iterator(end()); }
173 reverse_iterator rend()
174 {
return reverse_iterator(begin()); }
175 const_reverse_iterator rbegin()
const 176 {
return const_reverse_iterator(end()); }
177 const_reverse_iterator rend()
const 178 {
return const_reverse_iterator(begin()); }
180 void resize(size_type n, value_type c = value_type()) {
182 erase(begin() + n, end());
184 append(n - size(), c);
187 void push_back(value_type c) {
192 erase(end()-1, end());
197 template <
class PossibleInputIter>
198 xstring &assign(PossibleInputIter first, PossibleInputIter last) {
200 typedef typename IsInteger<PossibleInputIter>::query is_integer;
201 assign_dispatch(first, last, is_integer());
205 xstring &operator=(
const xstring &s) {
207 assign(s.begin(), s.end());
211 xstring& operator=(
const value_type* s) {
212 assign_dispatch(s, s + traits_type::length(s), false_type());
216 xstring& operator=(value_type c) {
217 assign_dispatch(static_cast<size_type>(1),
218 static_cast<size_type>(c),
225 xstring& operator+=(
const xstring& s) {
return append(s); }
226 xstring& operator+=(
const value_type* s) {
return append(s); }
227 xstring& operator+=(value_type c) { push_back(c);
return *
this; }
229 template <
class InputIter>
230 xstring &append(InputIter first, InputIter last) {
231 insert(begin()+size(), first, last);
235 xstring& append(
const xstring& s)
236 {
return append(s.begin(), s.end()); }
238 xstring& append(
const xstring& s,
239 size_type pos, size_type n) {
241 throw std::out_of_range(
"Out of range");
242 return append(s.begin() + pos,
243 s.begin() + pos + std::min(n, s.size() - pos));
246 xstring& append(
const value_type* s, size_type n)
247 {
return append(s, s+n); }
249 xstring& append(
const value_type* s)
250 {
return append(s, s + traits_type::length(s)); }
252 xstring& append(size_type n, value_type c)
253 {
return insert(size(), n, c); }
259 iterator insert(iterator p, value_type c) {
260 insert<value_type*>(p,&c,1+&c);
264 template <
class InputIter>
265 void insert(iterator pos, InputIter first, InputIter last) {
266 Impl::insert(pos,first,last);
269 xstring& insert(size_type pos,
const xstring& s) {
271 throw std::out_of_range(
"Out of range");
272 if (size() > max_size() - s.size())
273 throw std::length_error(
"Length error");
274 insert(begin() + pos, s.begin(), s.end());
278 xstring& insert(size_type pos,
const xstring& s,
279 size_type beg, size_type n) {
280 if (pos > size() || beg > s.size())
281 throw std::out_of_range(
"Out of range");
282 size_type len = std::min(n, s.size() - beg);
283 if (size() > max_size() - len)
284 throw std::out_of_range(
"Out of range");
285 insert(begin() + pos,
286 s.begin() + beg, s.begin() + beg + len);
290 xstring& insert(size_type pos,
const value_type* s, size_type n) {
292 throw std::out_of_range(
"Out of range");
293 if (size() > max_size() - n)
294 throw std::out_of_range(
"Out of range");
295 insert(begin() + pos, s, s + n);
299 xstring& insert(size_type pos,
const value_type* s) {
301 throw std::out_of_range(
"Out of range");
302 size_type len = traits_type::length(s);
303 if (size() > max_size() - len)
304 throw std::out_of_range(
"Out of range");
305 insert(begin() + pos, s, s + len);
309 xstring& insert(size_type pos, size_type n, value_type c) {
311 throw std::out_of_range(
"Out of range");
312 if (size() > max_size() - n)
313 throw std::out_of_range(
"Out of range");
315 for (size_type i=0;i<n;++i)
316 insert(begin()+pos+i, c);
320 xstring& insert(iterator p, size_type n, value_type c) {
321 return insert(p-begin(), n, c);
325 iterator erase(iterator first, iterator last) {
326 return Impl::erase(first,last);
329 xstring& erase(size_type pos = 0, size_type n = npos) {
331 throw std::out_of_range(
"Out of range");
333 begin() + std::min(n, size() - pos));
336 iterator erase(iterator pos) {
return erase(pos,pos+1);}
339 xstring& replace(size_type pos, size_type n,
342 throw std::out_of_range(
"Out of range");
343 const size_type len = std::min(n, size() - pos);
344 if (size() - len >= max_size() - s.size())
345 throw std::length_error(
"Too long");
346 return replace(begin() + pos, begin() + pos + len,
350 xstring& replace(size_type pos1, size_type n1,
352 size_type pos2, size_type n2) {
353 if (pos1 > size() || pos2 > s.size())
354 throw std::out_of_range(
"Out of range");
355 const size_type len1 = std::min(n1, size() - pos1);
356 const size_type len2 = std::min(n2, s.size() - pos2);
357 if (size() - len1 >= max_size() - len2)
358 throw std::length_error(
"Too long");
359 return replace(begin() + pos1, begin() + pos1 + len1,
360 s.begin() + pos2, s.begin() + pos2 + len2);
363 xstring& replace(size_type pos, size_type n1,
364 const value_type* s, size_type n2) {
366 throw std::out_of_range(
"Out of range");
367 const size_type len = std::min(n1, size() - pos);
368 if (n2 > max_size() || size() - len >= max_size() - n2)
369 throw std::length_error(
"Too long");
370 return replace(begin() + pos, begin() + pos + len,
374 xstring& replace(size_type pos, size_type n1,
375 const value_type* s) {
377 throw std::out_of_range(
"Out of range");
378 const size_type len = std::min(n1, size() - pos);
379 const size_type n2 = traits_type::length(s);
380 if (n2 > max_size() || size() - len >= max_size() - n2)
381 throw std::length_error(
"Too long");
382 return replace(begin() + pos, begin() + pos + len,
383 s, s + traits_type::length(s));
386 xstring& replace(size_type pos, size_type n1,
387 size_type n2, value_type c) {
389 throw std::out_of_range(
"Out of range");
390 const size_type len = std::min(n1, size() - pos);
391 if (n2 > max_size() || size() - len >= max_size() - n2)
392 throw std::length_error(
"Too long");
393 return replace(begin() + pos, begin() + pos + len, n2, c);
396 xstring& replace(iterator first, iterator last,
398 {
return replace(first, last, s.begin(), s.end()); }
400 xstring& replace(iterator first, iterator last,
401 const value_type* s, size_type n)
402 {
return replace(first, last, s, s + n); }
404 xstring& replace(iterator first, iterator last,
405 const value_type* s) {
406 return replace(first, last, s, s + traits_type::length(s));
409 xstring& replace(iterator first, iterator last,
410 size_type n, value_type c);
413 template <
class InputIter>
414 xstring& replace (iterator first, iterator last, size_type n,
418 template <
class ParamType>
419 xstring& replace(iterator first, iterator last,
420 ParamType x, ParamType y) {
421 typedef typename IsInteger<ParamType>::query is_integer;
422 return replace_dispatch(first, last, x, y, is_integer());
428 template <
class IntegerType>
429 xstring& replace_dispatch(iterator first, iterator last,
430 IntegerType n, IntegerType x,
432 return replace(first, last, (size_type) n, (value_type) x);
435 template <
class InputIter>
436 xstring& replace_dispatch(iterator first, iterator last,
437 InputIter f, InputIter l,
439 typedef typename std::iterator_traits<InputIter>::iterator_category Category;
440 return replace(first, last, f, l, Category());
444 template <
class InputIter>
445 xstring& replace(iterator first, iterator last,
446 InputIter f, InputIter l, std::input_iterator_tag);
448 template <
class ForwardIter>
449 xstring& replace(iterator first, iterator last,
450 ForwardIter f, ForwardIter l,
451 std::forward_iterator_tag);
458 size_type copy(value_type* s, size_type n, size_type pos = 0)
const {
460 throw std::out_of_range(
"Out of range");
461 const size_type len = std::min(n, size() - pos);
462 traits_type::copy(s, begin() + pos, len);
469 const_reference operator[](size_type n)
const {
472 reference operator[](size_type n) {
475 const_reference at(size_type n)
const {
477 throw std::out_of_range(
"Out of range");
480 reference at(size_type n) {
482 throw std::out_of_range(
"Out of range");
488 size_type find(
const xstring& s, size_type pos = 0)
const 489 {
return find(s.begin(), pos, s.size()); }
491 size_type find(
const value_type* s, size_type pos = 0)
const 492 {
return find(s, pos, traits_type::length(s)); }
494 size_type find(
const value_type* s, size_type pos, size_type n)
const;
496 size_type find(value_type c, size_type pos = 0)
const;
499 size_type rfind(
const xstring& s, size_type pos = npos)
const 500 {
return rfind(s.begin(), pos, s.size()); }
502 size_type rfind(
const value_type* s, size_type pos = npos)
const 503 {
return rfind(s, pos, traits_type::length(s)); }
505 size_type rfind(
const value_type* s, size_type pos, size_type n)
const;
506 size_type rfind(value_type c, size_type pos = npos)
const;
509 size_type find_first_of(
const xstring& s, size_type pos = 0)
const 510 {
return find_first_of(s.begin(), pos, s.size()); }
512 size_type find_first_of(
const value_type* s, size_type pos = 0)
const 513 {
return find_first_of(s, pos, traits_type::length(s)); }
515 size_type find_first_of(
const value_type* s, size_type pos,
518 size_type find_first_of(value_type c, size_type pos = 0)
const 519 {
return find(c, pos); }
523 size_type find_last_of(
const xstring& s,
524 size_type pos = npos)
const 525 {
return find_last_of(s.begin(), pos, s.size()); }
527 size_type find_last_of(
const value_type* s, size_type pos = npos)
const 528 {
return find_last_of(s, pos, traits_type::length(s)); }
530 size_type find_last_of(
const value_type* s, size_type pos,
533 size_type find_last_of(value_type c, size_type pos = npos)
const {
534 return rfind(c, pos);
539 size_type find_first_not_of(
const xstring& s,
540 size_type pos = 0)
const 541 {
return find_first_not_of(s.begin(), pos, s.size()); }
543 size_type find_first_not_of(
const value_type* s, size_type pos = 0)
const 544 {
return find_first_not_of(s, pos, traits_type::length(s)); }
546 size_type find_first_not_of(
const value_type* s, size_type pos,
549 size_type find_first_not_of(value_type c, size_type pos = 0)
const;
553 size_type find_last_not_of(
const xstring& s,
554 size_type pos = npos)
const 555 {
return find_last_not_of(s.begin(), pos, s.size()); }
557 size_type find_last_not_of(
const value_type* s, size_type pos = npos)
const 558 {
return find_last_not_of(s, pos, traits_type::length(s)); }
560 size_type find_last_not_of(
const value_type* s, size_type pos,
563 size_type find_last_not_of(value_type c, size_type pos = npos)
const;
567 xstring substr(size_type pos = 0, size_type n = npos)
const {
569 throw std::out_of_range(
"Out of range");
570 return xstring(begin() + pos,
571 begin() + pos + std::min(n, size() - pos));
574 int compare(xstring
const &s)
const {
575 return m_compare(begin(),end(),s.begin(),s.end());
580 static const allocator_type _default_allocator;
584 static int m_compare(
const value_type* f1,
const value_type* l1,
585 const value_type* f2,
const value_type* l2) {
586 const ptrdiff_t n1 = l1 - f1;
587 const ptrdiff_t n2 = l2 - f2;
588 const int cmp = traits_type::compare(f1, f2, std::min(n1, n2));
589 return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
598 template <
class Impl>
599 const xstring<Impl>::allocator_type
600 xstring<Impl>::_default_allocator;
603 template <
class Impl>
606 ::xstring(
const value_type* s, size_type n,
607 const allocator_type& a)
609 Impl::range_initialize(s, (n!=(size_type)-1) ? s+n : s+traits_type::length(s));
614 template <
class Impl>
615 template <
class InputIter>
618 ::replace(iterator first, iterator last, InputIter f, InputIter l,
619 std::input_iterator_tag)
621 for ( ; first != last && f != l; ++first, ++f)
622 traits_type::assign(*first, *f);
631 template <
class Impl>
632 template <
class ForwardIter>
635 ::replace(iterator first, iterator last,
636 ForwardIter f, ForwardIter l,
637 std::forward_iterator_tag)
639 difference_type n = 0;
640 std::distance(f, l, n);
641 const difference_type len = last - first;
643 std::copy(f, l, first);
644 erase(first + n, last);
648 std::advance(m, len);
649 std::copy(f, m, first);
658 template <
class Impl>
659 xstring<Impl>::size_type
661 ::find(
const typename Impl::value_type* s, size_type pos, size_type n)
const 663 if (pos + n > size())
666 const const_iterator result =
667 search(begin() + pos, end(),
668 s, s + n, eq_traits<traits_type>());
669 return result != end() ? result - begin() : npos;
673 template <
class Impl>
674 xstring<Impl>::size_type
676 ::find(
typename Impl::value_type c, size_type pos)
const 681 const const_iterator result =
682 find_if(begin() + pos, end(),
683 bind2nd(eq_traits<traits_type>(), c));
684 return result != end() ? result - begin() : npos;
688 template <
class Impl>
689 xstring<Impl>::size_type
691 ::rfind(
const typename Impl::value_type* s, size_type pos, size_type n)
const 693 const size_t len = size();
698 return std::min(len, pos);
700 const const_iterator last = begin() + std::min(len - n, pos) + n;
701 const const_iterator result = std::find_end(begin(), last,
703 eq_traits<traits_type>());
704 return result != last ? result - begin() : npos;
708 template <
class Impl>
709 xstring<Impl>::size_type
711 ::rfind(
typename Impl::value_type c, size_type pos)
const 713 const size_type len = size();
718 const const_iterator last = begin() + std::min(len - 1, pos) + 1;
719 const_reverse_iterator rresult =
720 find_if(const_reverse_iterator(last), rend(),
721 bind2nd(eq_traits<traits_type>(), c));
722 return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
726 template <
class Impl>
727 xstring<Impl>::size_type
729 ::find_first_of(
const typename Impl::value_type* s, size_type pos, size_type n)
const 734 const_iterator result = std::find_first_of(begin() + pos, end(),
736 eq_traits<traits_type>());
737 return result != end() ? result - begin() : npos;
742 template <
class Impl>
743 xstring<Impl>::size_type
745 ::find_last_of(
const typename Impl::value_type* s, size_type pos, size_type n)
const 747 const size_type len = size();
752 const const_iterator last = begin() + std::min(len - 1, pos) + 1;
753 const const_reverse_iterator rresult =
754 std::find_first_of(const_reverse_iterator(last), rend(),
756 eq_traits<traits_type>());
757 return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
762 template <
class Impl>
763 xstring<Impl>::size_type
765 ::find_first_not_of(
const typename Impl::value_type* s, size_type pos, size_type n)
const 770 const_iterator result = find_if(begin() + pos, end(),
771 not_within_traits<traits_type>(s, s + n));
772 return result != end() ? result - begin() : npos;
776 template <
class Impl>
777 xstring<Impl>::size_type
779 ::find_first_not_of(
typename Impl::value_type c, size_type pos)
const 784 const_iterator result
785 = find_if(begin() + pos, end(),
786 not1(bind2nd(eq_traits<traits_type>(), c)));
787 return result != end() ? result - begin() : npos;
791 template <
class Impl>
792 xstring<Impl>::size_type
794 ::find_last_not_of(
const typename Impl::value_type* s, size_type pos, size_type n)
const 797 const size_type len = size();
802 const const_iterator last = begin() + std::min(len - 1, pos) + 1;
803 const const_reverse_iterator rresult =
804 find_if(const_reverse_iterator(last), rend(),
805 not_within_traits<traits_type>(s, s + n));
806 return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
810 template <
class Impl>
811 xstring<Impl>::size_type
813 ::find_last_not_of(
typename Impl::value_type c, size_type pos)
const 815 const size_type len = size();
820 const const_iterator last = begin() + std::min(len - 1, pos) + 1;
821 const_reverse_iterator rresult =
822 find_if(const_reverse_iterator(last), rend(),
823 not1(bind2nd(eq_traits<traits_type>(), c)));
824 return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
835 template <
class Impl>
837 operator+(
const xstring<Impl>& x,
838 const xstring<Impl>& y)
840 typedef xstring<Impl> Str;
846 template <
class Impl>
848 operator+(
const typename Impl::value_type* s,
849 const xstring<Impl>& y) {
850 typedef xstring<Impl> Str;
856 template <
class Impl>
858 operator+(
typename Impl::value_type c,
859 const xstring<Impl>& y) {
860 typedef xstring<Impl> Str;
866 template <
class Impl>
868 operator+(
const xstring<Impl>& x,
869 const typename Impl::value_type * s) {
870 typedef xstring<Impl> Str;
876 template <
class Impl>
878 operator+(
const xstring<Impl>& x,
879 const typename Impl::value_type c) {
880 typedef xstring<Impl> Str;
888 template <
class Impl>
891 const xstring<Impl>& y) {
892 typedef typename Impl::traits_type Traits;
893 return x.size() == y.size() &&
894 Traits::compare(x.data(), y.data(), x.size()) == 0;
897 template <
class Impl>
899 operator==(
const typename Impl::value_type* s,
900 const xstring<Impl>& y) {
901 typedef typename Impl::traits_type Traits;
902 size_t n = Traits::length(s);
903 return n == y.size() && Traits::compare(s, y.data(), n) == 0;
906 template <
class Impl>
909 const typename Impl::value_type* s) {
910 typedef typename Impl::traits_type Traits;
911 size_t n = Traits::length(s);
912 return x.size() == n && Traits::compare(x.data(), s, n) == 0;
917 template <
class Impl>
920 const xstring<Impl>& y) {
924 template <
class Impl>
926 operator!=(
const typename Impl::value_type* s,
927 const xstring<Impl>& y) {
931 template <
class Impl>
934 const typename Impl::value_type* s) {
942 template <
class Impl>
944 operator<(const xstring<Impl>& x,
945 const xstring<Impl>& y) {
947 ::m_compare(x.begin(), x.end(), y.begin(), y.end()) < 0;
950 template <
class Impl>
952 operator<(
const typename Impl::value_type* s,
953 const xstring<Impl>& y) {
954 typedef typename Impl::traits_type Traits;
955 size_t n = Traits::length(s);
957 ::m_compare(s, s + n, y.begin(), y.end()) < 0;
960 template <
class Impl>
962 operator<(const xstring<Impl>& x,
963 const typename Impl::value_type* s) {
964 typedef typename Impl::traits_type Traits;
965 size_t n = Traits::length(s);
967 ::m_compare(x.begin(), x.end(), s, s + n) < 0;
972 template <
class Impl>
974 operator>(
const xstring<Impl>& x,
975 const xstring<Impl>& y) {
979 template <
class Impl>
981 operator>(
const typename Impl::value_type* s,
982 const xstring<Impl>& y) {
986 template <
class Impl>
988 operator>(
const xstring<Impl>& x,
989 const typename Impl::value_type* s) {
993 template <
class Impl>
995 operator<=(const xstring<Impl>& x,
996 const xstring<Impl>& y) {
1000 template <
class Impl>
1002 operator<=(
const typename Impl::value_type* s,
1003 const xstring<Impl>& y) {
1007 template <
class Impl>
1009 operator<=(const xstring<Impl>& x,
1010 const typename Impl::value_type* s) {
1014 template <
class Impl>
1016 operator>=(
const xstring<Impl>& x,
1017 const xstring<Impl>& y) {
1021 template <
class Impl>
1023 operator>=(
const typename Impl::value_type* s,
1024 const xstring<Impl>& y) {
1028 template <
class Impl>
1030 operator>=(
const xstring<Impl>& x,
1031 const typename Impl::value_type* s) {
BWORD operator!=(const DualString &s1, const DualString &s2)
Compare two DualString's (reverse logic)
Definition: DualString.h:229
BWORD operator==(const DualString &s1, const DualString &s2)
Compare two DualString's.
Definition: DualString.h:208