Free Electron
xstring.h
1 // Copyright (c) 2001 John Panzer
2 // Permission is granted to use this code without restriction as
3 // long as this copyright notice appears in all source files.
4 // Portions of interface Copyright (c) 1997-1999
5 // Silicon Graphics Computer Systems, Inc.
6 
7 #ifndef XSTRING_H_INCLUDED
8 #define XSTRING_H_INCLUDED
9 
10 #include <ctype.h>
11 #include <stddef.h>
12 #include <iterator>
13 #include <stdexcept>
14 #include <memory>
15 #include <algorithm>
16 #include <string> // For char_traits
17 
18 #include "xs_defs.h"
19 
20 XS_NAMESPACE(xstr)
21 
22 //----------------------------------------------------
23 // Helper classes:
24 
25 // Helper templates that wrap char_traits functions within
26 // STL predicate functors. This lets the string class use
27 // standard algorithms for much of its work.
28 
29 template <class Traits>
30 struct eq_traits
31  : public std::binary_function<typename Traits::char_type,
32  typename Traits::char_type,
33  bool> {
34  bool operator()(const typename Traits::char_type& x,
35  const typename Traits::char_type& y) const {
36  return Traits::eq(x, y);
37  }
38 };
39 
40 template <class Traits>
41 struct not_within_traits
42  : public std::unary_function<typename Traits::char_type, bool>
43 {
44  typedef typename Traits::char_type CharT;
45  const CharT* _first;
46  const CharT* _last;
47 
48  not_within_traits(const typename Traits::char_type* f,
49  const typename Traits::char_type* l)
50  : _first(f), _last(l) {}
51 
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;
55  }
56 };
57 
58 
59 // Helper template IsInteger: Does compile time type
60 // checking to tell if template type is an integer
61 // type (query is true_type) or something else
62 // (query is false_type). This is used for compile
63 // time dispatching of otherwise ambiguous overloads.
64 
65 struct true_type {};
66 struct false_type {};
67 
68 template <class T>
69 struct IsInteger {typedef false_type query;};
70 
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;};
79 
80 
81 //----------------------------------------------------
82 
83 // Wrapper that adds extended string interface on top of
84 // a minimal string implementation. Impl must
85 // provide a minimal random access string container interface.
86 
87 template <class Impl>
88 class xstring : public Impl {
89 public:
90  // Standard typedefs, taken from implementation:
91  typedef typename Impl::value_type value_type;
92  typedef typename Impl::traits_type traits_type;
93 
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;
100 
101  typedef typename Impl::const_iterator const_iterator;
102  typedef typename Impl::iterator iterator;
103 
104  typedef typename Impl::reverse_iterator reverse_iterator;
105  typedef typename Impl::const_reverse_iterator const_reverse_iterator;
106 
107  typedef typename Impl::allocator_type allocator_type;
108 
109  // --------- Constructors ----------
110 
111  xstring(allocator_type const &allocator = allocator_type())
112  : Impl(allocator) {
113  Impl::element_initialize(0,0);
114  }
115 
116  xstring(xstring const &s) : Impl(s) {}
117 
118  // Conversion from basic_string:
119  xstring(std::basic_string<value_type> const &s) {
120  Impl::range_initialize(s.begin(), s.end());
121  }
122 
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())
127  : Impl(a) {
128  if (pos > s.size())
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));
132  }
133 
134  xstring(const value_type* s, size_type n=(size_type)(-1),
135  const allocator_type& a = _default_allocator);
136 
137  xstring(size_type n, value_type c,
138  const allocator_type& a = _default_allocator)
139  : Impl(a) {
140  Impl::element_initialize(n,c);
141  }
142 
143  template <class PossibleInputIter>
144  xstring(PossibleInputIter f, PossibleInputIter l,
145  const allocator_type& a = _default_allocator)
146  : Impl(a) {
147  typedef typename IsInteger<PossibleInputIter>::query is_integer;
148  assign_dispatch(f, l, is_integer());
149  }
150 
151 private: // Dispatched implementation of assignment
152  template <class Integer>
153  void assign_dispatch(Integer n, Integer x, true_type) {
154  Impl::element_initialize(n,(value_type)x);
155  }
156 
157  template <class InputIter>
158  void assign_dispatch(InputIter f, InputIter l, false_type) {
159  Impl::range_initialize(f, l);
160  }
161 public:
162 
163  // Conversion to basic_string<value_type>. This will only
164  // work if everyone is using the default char_traits.
165  operator std::basic_string<value_type>() {
166  return std::basic_string<value_type>(this->c_str());
167  }
168 
169  size_type length() const {return size();}
170 
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()); }
179 
180  void resize(size_type n, value_type c = value_type()) {
181  if (n <= size())
182  erase(begin() + n, end());
183  else
184  append(n - size(), c);
185  }
186 
187  void push_back(value_type c) {
188  insert(end(),c);
189  }
190 
191  void pop_back() {
192  erase(end()-1, end());
193  }
194 
195  // Assignment
196 
197  template <class PossibleInputIter>
198  xstring &assign(PossibleInputIter first, PossibleInputIter last) {
199  clear();
200  typedef typename IsInteger<PossibleInputIter>::query is_integer;
201  assign_dispatch(first, last, is_integer());
202  return *this;
203  }
204 
205  xstring &operator=(const xstring &s) {
206  if (&s != this)
207  assign(s.begin(), s.end());
208  return *this;
209  }
210 
211  xstring& operator=(const value_type* s) {
212  assign_dispatch(s, s + traits_type::length(s), false_type());
213  return *this;
214  }
215 
216  xstring& operator=(value_type c) {
217  assign_dispatch(static_cast<size_type>(1),
218  static_cast<size_type>(c),
219  true_type());
220  return *this;
221  }
222 
223  // Append
224 
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; }
228 
229  template <class InputIter>
230  xstring &append(InputIter first, InputIter last) {
231  insert(begin()+size(), first, last);
232  return *this;
233  }
234 
235  xstring& append(const xstring& s)
236  { return append(s.begin(), s.end()); }
237 
238  xstring& append(const xstring& s,
239  size_type pos, size_type n) {
240  if (pos > s.size())
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));
244  }
245 
246  xstring& append(const value_type* s, size_type n)
247  { return append(s, s+n); }
248 
249  xstring& append(const value_type* s)
250  { return append(s, s + traits_type::length(s)); }
251 
252  xstring& append(size_type n, value_type c)
253  { return insert(size(), n, c); }
254 
255  // Insertion
256 
257  // Need to define these just so we can overload
258  // the function in this class.
259  iterator insert(iterator p, value_type c) {
260  insert<value_type*>(p,&c,1+&c);
261  return ++p;
262  }
263 
264  template <class InputIter>
265  void insert(iterator pos, InputIter first, InputIter last) {
266  Impl::insert(pos,first,last);
267  }
268 
269  xstring& insert(size_type pos, const xstring& s) {
270  if (pos > size())
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());
275  return *this;
276  }
277 
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);
287  return *this;
288  }
289 
290  xstring& insert(size_type pos, const value_type* s, size_type n) {
291  if (pos > size())
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);
296  return *this;
297  }
298 
299  xstring& insert(size_type pos, const value_type* s) {
300  if (pos > size())
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);
306  return *this;
307  }
308 
309  xstring& insert(size_type pos, size_type n, value_type c) {
310  if (pos > size())
311  throw std::out_of_range("Out of range");
312  if (size() > max_size() - n)
313  throw std::out_of_range("Out of range");
314  // TODO: Replace with less brain-dead implementation.
315  for (size_type i=0;i<n;++i)
316  insert(begin()+pos+i, c);
317  return *this;
318  }
319 
320  xstring& insert(iterator p, size_type n, value_type c) {
321  return insert(p-begin(), n, c);
322  }
323 
324  // Erase
325  iterator erase(iterator first, iterator last) {
326  return Impl::erase(first,last);
327  }
328 
329  xstring& erase(size_type pos = 0, size_type n = npos) {
330  if (pos > size())
331  throw std::out_of_range("Out of range");
332  erase(begin() + pos,
333  begin() + std::min(n, size() - pos));
334  return *this;
335  }
336  iterator erase(iterator pos) {return erase(pos,pos+1);}
337 
338  // Replace
339  xstring& replace(size_type pos, size_type n,
340  const xstring& s) {
341  if (pos > size())
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,
347  s.begin(), s.end());
348  }
349 
350  xstring& replace(size_type pos1, size_type n1,
351  const xstring& s,
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);
361  }
362 
363  xstring& replace(size_type pos, size_type n1,
364  const value_type* s, size_type n2) {
365  if (pos > size())
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,
371  s, s + n2);
372  }
373 
374  xstring& replace(size_type pos, size_type n1,
375  const value_type* s) {
376  if (pos > size())
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));
384  }
385 
386  xstring& replace(size_type pos, size_type n1,
387  size_type n2, value_type c) {
388  if (pos > size())
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);
394  }
395 
396  xstring& replace(iterator first, iterator last,
397  const xstring& s)
398  { return replace(first, last, s.begin(), s.end()); }
399 
400  xstring& replace(iterator first, iterator last,
401  const value_type* s, size_type n)
402  { return replace(first, last, s, s + n); }
403 
404  xstring& replace(iterator first, iterator last,
405  const value_type* s) {
406  return replace(first, last, s, s + traits_type::length(s));
407  }
408 
409  xstring& replace(iterator first, iterator last,
410  size_type n, value_type c);
411 
412 
413  template <class InputIter>
414  xstring& replace (iterator first, iterator last, size_type n,
415  value_type c);
416 
417 //#ifdef STL_MEMBER_TEMPLATES
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());
423  }
424 //#endif /* STL_MEMBER_TEMPLATES */
425 
426 //#ifdef STL_MEMBER_ TEMPLATES
427 private:
428  template <class IntegerType>
429  xstring& replace_dispatch(iterator first, iterator last,
430  IntegerType n, IntegerType x,
431  true_type) {
432  return replace(first, last, (size_type) n, (value_type) x);
433  }
434 
435  template <class InputIter>
436  xstring& replace_dispatch(iterator first, iterator last,
437  InputIter f, InputIter l,
438  false_type) {
439  typedef typename std::iterator_traits<InputIter>::iterator_category Category;
440  return replace(first, last, f, l, Category());
441  }
442 
443 private:
444  template <class InputIter>
445  xstring& replace(iterator first, iterator last,
446  InputIter f, InputIter l, std::input_iterator_tag);
447 
448  template <class ForwardIter>
449  xstring& replace(iterator first, iterator last,
450  ForwardIter f, ForwardIter l,
451  std::forward_iterator_tag);
452 public:
453 
454 //#endif /* STL_MEMBER_TEMPLATES */
455 
456 // Other modifier member functions.
457 
458  size_type copy(value_type* s, size_type n, size_type pos = 0) const {
459  if (pos > size())
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);
463  return len;
464  }
465 
466 
467  // Misc
468 
469  const_reference operator[](size_type n) const {
470  return *(begin()+n);
471  }
472  reference operator[](size_type n) {
473  return *(begin()+n);
474  }
475  const_reference at(size_type n) const {
476  if (n >= size())
477  throw std::out_of_range("Out of range");
478  return *(begin()+n);
479  }
480  reference at(size_type n) {
481  if (n >= size())
482  throw std::out_of_range("Out of range");
483  return *(begin()+n);
484  }
485 
486  // find
487 
488  size_type find(const xstring& s, size_type pos = 0) const
489  { return find(s.begin(), pos, s.size()); }
490 
491  size_type find(const value_type* s, size_type pos = 0) const
492  { return find(s, pos, traits_type::length(s)); }
493 
494  size_type find(const value_type* s, size_type pos, size_type n) const;
495 
496  size_type find(value_type c, size_type pos = 0) const;
497 
498  // rfind
499  size_type rfind(const xstring& s, size_type pos = npos) const
500  { return rfind(s.begin(), pos, s.size()); }
501 
502  size_type rfind(const value_type* s, size_type pos = npos) const
503  { return rfind(s, pos, traits_type::length(s)); }
504 
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;
507 
508  // find_first_of
509  size_type find_first_of(const xstring& s, size_type pos = 0) const
510  { return find_first_of(s.begin(), pos, s.size()); }
511 
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)); }
514 
515  size_type find_first_of(const value_type* s, size_type pos,
516  size_type n) const;
517 
518  size_type find_first_of(value_type c, size_type pos = 0) const
519  { return find(c, pos); }
520 
521  // find_last_of
522 
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()); }
526 
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)); }
529 
530  size_type find_last_of(const value_type* s, size_type pos,
531  size_type n) const;
532 
533  size_type find_last_of(value_type c, size_type pos = npos) const {
534  return rfind(c, pos);
535  }
536 
537  // find_first_not_of
538 
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()); }
542 
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)); }
545 
546  size_type find_first_not_of(const value_type* s, size_type pos,
547  size_type n) const;
548 
549  size_type find_first_not_of(value_type c, size_type pos = 0) const;
550 
551  // find_last_not_of
552 
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()); }
556 
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)); }
559 
560  size_type find_last_not_of(const value_type* s, size_type pos,
561  size_type n) const;
562 
563  size_type find_last_not_of(value_type c, size_type pos = npos) const;
564 
565  // Substring.
566 
567  xstring substr(size_type pos = 0, size_type n = npos) const {
568  if (pos > size())
569  throw std::out_of_range("Out of range");
570  return xstring(begin() + pos,
571  begin() + pos + std::min(n, size() - pos));
572  }
573 
574  int compare(xstring const &s) const {
575  return m_compare(begin(),end(),s.begin(),s.end());
576  }
577 
578 private:
579  // Default allocator instance used for initialization
580  static const allocator_type _default_allocator;
581 
582 public:
583  // Helper function for compare and relational operators
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));
590  }
591 };
592 
593 // -------- Out of line definitions
594 
595 // Definition of a default allocator instance to use
596 // in initializing the base class (saves instantiating
597 // a default allocator object each time)
598 template <class Impl>
599 const xstring<Impl>::allocator_type
600  xstring<Impl>::_default_allocator;
601 
602 
603 template <class Impl>
604 //inline
605 xstring<Impl>
606  ::xstring(const value_type* s, size_type n,
607  const allocator_type& a)
608  : Impl(a) {
609  Impl::range_initialize(s, (n!=(size_type)-1) ? s+n : s+traits_type::length(s));
610 }
611 
612 //#ifdef STL_MEMBER_TEMPLATES
613 
614 template <class Impl>
615 template <class InputIter>
616 xstring<Impl>&
617 xstring<Impl>
618  ::replace(iterator first, iterator last, InputIter f, InputIter l,
619  std::input_iterator_tag)
620 {
621  for ( ; first != last && f != l; ++first, ++f)
622  traits_type::assign(*first, *f);
623 
624  if (f == l)
625  erase(first, last);
626  else
627  insert(last, f, l);
628  return *this;
629 }
630 
631 template <class Impl>
632 template <class ForwardIter>
633 xstring<Impl>&
634 xstring<Impl>
635  ::replace(iterator first, iterator last,
636  ForwardIter f, ForwardIter l,
637  std::forward_iterator_tag)
638 {
639  difference_type n = 0;
640  std::distance(f, l, n);
641  const difference_type len = last - first;
642  if (len >= n) {
643  std::copy(f, l, first);
644  erase(first + n, last);
645  }
646  else {
647  ForwardIter m = f;
648  std::advance(m, len);
649  std::copy(f, m, first);
650  insert(last, m, l);
651  }
652  return *this;
653 }
654 
655 //#endif /* STL_MEMBER_TEMPLATES */
656 
657 
658 template <class Impl>
659 xstring<Impl>::size_type
660 xstring<Impl>
661  ::find(const typename Impl::value_type* s, size_type pos, size_type n) const
662 {
663  if (pos + n > size())
664  return npos;
665  else {
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;
670  }
671 }
672 
673 template <class Impl>
674 xstring<Impl>::size_type
675 xstring<Impl>
676  ::find(typename Impl::value_type c, size_type pos) const
677 {
678  if (pos >= size())
679  return npos;
680  else {
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;
685  }
686 }
687 
688 template <class Impl>
689 xstring<Impl>::size_type
690 xstring<Impl>
691  ::rfind(const typename Impl::value_type* s, size_type pos, size_type n) const
692 {
693  const size_t len = size();
694 
695  if (n > len)
696  return npos;
697  else if (n == 0)
698  return std::min(len, pos);
699  else {
700  const const_iterator last = begin() + std::min(len - n, pos) + n;
701  const const_iterator result = std::find_end(begin(), last,
702  s, s + n,
703  eq_traits<traits_type>());
704  return result != last ? result - begin() : npos;
705  }
706 }
707 
708 template <class Impl>
709 xstring<Impl>::size_type
710 xstring<Impl>
711  ::rfind(typename Impl::value_type c, size_type pos) const
712 {
713  const size_type len = size();
714 
715  if (len < 1)
716  return npos;
717  else {
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;
723  }
724 }
725 
726 template <class Impl>
727 xstring<Impl>::size_type
728 xstring<Impl>
729  ::find_first_of(const typename Impl::value_type* s, size_type pos, size_type n) const
730 {
731  if (pos >= size())
732  return npos;
733  else {
734  const_iterator result = std::find_first_of(begin() + pos, end(),
735  s, s + n,
736  eq_traits<traits_type>());
737  return result != end() ? result - begin() : npos;
738  }
739 }
740 
741 
742 template <class Impl>
743 xstring<Impl>::size_type
744 xstring<Impl>
745  ::find_last_of(const typename Impl::value_type* s, size_type pos, size_type n) const
746 {
747  const size_type len = size();
748 
749  if (len < 1)
750  return npos;
751  else {
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(),
755  s, s + n,
756  eq_traits<traits_type>());
757  return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
758  }
759 }
760 
761 
762 template <class Impl>
763 xstring<Impl>::size_type
764 xstring<Impl>
765  ::find_first_not_of(const typename Impl::value_type* s, size_type pos, size_type n) const
766 {
767  if (pos > size())
768  return npos;
769  else {
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;
773  }
774 }
775 
776 template <class Impl>
777 xstring<Impl>::size_type
778 xstring<Impl>
779  ::find_first_not_of(typename Impl::value_type c, size_type pos) const
780 {
781  if (pos > size())
782  return npos;
783  else {
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;
788  }
789 }
790 
791 template <class Impl>
792 xstring<Impl>::size_type
793 xstring<Impl>
794  ::find_last_not_of(const typename Impl::value_type* s, size_type pos, size_type n) const
795 {
796 
797  const size_type len = size();
798 
799  if (len < 1)
800  return npos;
801  else {
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;
807  }
808 }
809 
810 template <class Impl>
811 xstring<Impl>::size_type
812 xstring<Impl>
813  ::find_last_not_of(typename Impl::value_type c, size_type pos) const
814 {
815  const size_type len = size();
816 
817  if (len < 1)
818  return npos;
819  else {
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;
825  }
826 }
827 
828 
829 
830 // ------------------------------------------------------------
831 // Non-member functions.
832 
833 // Operator+
834 
835 template <class Impl>
836 inline xstring<Impl>
837 operator+(const xstring<Impl>& x,
838  const xstring<Impl>& y)
839 {
840  typedef xstring<Impl> Str;
841  Str result(x);
842  result.append(y);
843  return result;
844 }
845 
846 template <class Impl>
847 inline xstring<Impl>
848 operator+(const typename Impl::value_type* s,
849  const xstring<Impl>& y) {
850  typedef xstring<Impl> Str;
851  Str result(s);
852  result.append(y);
853  return result;
854 }
855 
856 template <class Impl>
857 inline xstring<Impl>
858 operator+(typename Impl::value_type c,
859  const xstring<Impl>& y) {
860  typedef xstring<Impl> Str;
861  Str result(&c, 1);
862  result.append(y);
863  return result;
864 }
865 
866 template <class Impl>
867 inline xstring<Impl>
868 operator+(const xstring<Impl>& x,
869  const typename Impl::value_type * s) {
870  typedef xstring<Impl> Str;
871  Str result(x);
872  result.append(s);
873  return result;
874 }
875 
876 template <class Impl>
877 inline xstring<Impl>
878 operator+(const xstring<Impl>& x,
879  const typename Impl::value_type c) {
880  typedef xstring<Impl> Str;
881  Str result(x);
882  result.push_back(c);
883  return result;
884 }
885 
886 // Operator== and operator!=
887 
888 template <class Impl>
889 inline bool
890 operator==(const xstring<Impl>& x,
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;
895 }
896 
897 template <class Impl>
898 inline bool
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;
904 }
905 
906 template <class Impl>
907 inline bool
908 operator==(const xstring<Impl>& x,
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;
913 }
914 
915 //#ifdef STL_FUNCTION_TMPL_PARTIAL_ORDER
916 
917 template <class Impl>
918 inline bool
919 operator!=(const xstring<Impl>& x,
920  const xstring<Impl>& y) {
921  return !(x == y);
922 }
923 
924 template <class Impl>
925 inline bool
926 operator!=(const typename Impl::value_type* s,
927  const xstring<Impl>& y) {
928  return !(s == y);
929 }
930 
931 template <class Impl>
932 inline bool
933 operator!=(const xstring<Impl>& x,
934  const typename Impl::value_type* s) {
935  return !(x == s);
936 }
937 
938 //#endif /* STL_FUNCTION_TMPL_PARTIAL_ORDER */
939 
940 // Operator< (and also >, <=, and >=).
941 
942 template <class Impl>
943 inline bool
944 operator<(const xstring<Impl>& x,
945  const xstring<Impl>& y) {
946  return xstring<Impl>
947  ::m_compare(x.begin(), x.end(), y.begin(), y.end()) < 0;
948 }
949 
950 template <class Impl>
951 inline bool
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);
956  return xstring<Impl>
957  ::m_compare(s, s + n, y.begin(), y.end()) < 0;
958 }
959 
960 template <class Impl>
961 inline bool
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);
966  return xstring<Impl>
967  ::m_compare(x.begin(), x.end(), s, s + n) < 0;
968 }
969 
970 //#ifdef STL_FUNCTION_TMPL_PARTIAL_ORDER
971 
972 template <class Impl>
973 inline bool
974 operator>(const xstring<Impl>& x,
975  const xstring<Impl>& y) {
976  return y < x;
977 }
978 
979 template <class Impl>
980 inline bool
981 operator>(const typename Impl::value_type* s,
982  const xstring<Impl>& y) {
983  return y < s;
984 }
985 
986 template <class Impl>
987 inline bool
988 operator>(const xstring<Impl>& x,
989  const typename Impl::value_type* s) {
990  return s < x;
991 }
992 
993 template <class Impl>
994 inline bool
995 operator<=(const xstring<Impl>& x,
996  const xstring<Impl>& y) {
997  return !(y < x);
998 }
999 
1000 template <class Impl>
1001 inline bool
1002 operator<=(const typename Impl::value_type* s,
1003  const xstring<Impl>& y) {
1004  return !(y < s);
1005 }
1006 
1007 template <class Impl>
1008 inline bool
1009 operator<=(const xstring<Impl>& x,
1010  const typename Impl::value_type* s) {
1011  return !(s < x);
1012 }
1013 
1014 template <class Impl>
1015 inline bool
1016 operator>=(const xstring<Impl>& x,
1017  const xstring<Impl>& y) {
1018  return !(x < y);
1019 }
1020 
1021 template <class Impl>
1022 inline bool
1023 operator>=(const typename Impl::value_type* s,
1024  const xstring<Impl>& y) {
1025  return !(s < y);
1026 }
1027 
1028 template <class Impl>
1029 inline bool
1030 operator>=(const xstring<Impl>& x,
1031  const typename Impl::value_type* s) {
1032  return !(x < s);
1033 }
1034 
1035 //#endif STL_FUNCTION_TMPL_PARTIAL_ORDER
1036 
1037 
1038 
1039 XS_END_NAMESPACE;
1040 
1041 /*
1042  * Copyright (c) 1997-1999
1043  * Silicon Graphics Computer Systems, Inc.
1044  *
1045  * Permission to use, copy, modify, distribute and sell this software
1046  * and its documentation for any purpose is hereby granted without fee,
1047  * provided that the above copyright notice appear in all copies and
1048  * that both that copyright notice and this permission notice appear
1049  * in supporting documentation. Silicon Graphics makes no
1050  * representations about the suitability of this software for any
1051  * purpose. It is provided "as is" without express or implied warranty.
1052  */
1053 
1054 #endif
BWORD operator!=(const DualString &s1, const DualString &s2)
Compare two DualString&#39;s (reverse logic)
Definition: DualString.h:229
BWORD operator==(const DualString &s1, const DualString &s2)
Compare two DualString&#39;s.
Definition: DualString.h:208