1/*
2 * Copyright (c) 2003
3 * Francois Dumont
4 *
5 * This material is provided "as is", with absolutely no warranty expressed
6 * or implied. Any use is at your own risk.
7 *
8 * Permission to use or copy this software for any purpose is hereby granted
9 * without fee, provided the above notices are retained on all copies.
10 * Permission to modify the code and to distribute modified code is granted,
11 * provided the above notices are retained, and a notice that the code was
12 * modified is included with the above copyright notice.
13 *
14 */
15
16#ifndef _STLP_STRING_SUM_H
17#define _STLP_STRING_SUM_H
18
19_STLP_BEGIN_NAMESPACE
20
21_STLP_MOVE_TO_PRIV_NAMESPACE
22
23/*char wrapper to simulate basic_string*/
24template <class _CharT>
25struct __char_wrapper {
26  typedef const _CharT& const_reference;
27
28  __char_wrapper(_CharT __val) : _Val(__val) {}
29
30  _CharT getValue() const { return _Val; }
31  size_t size() const { return 1; }
32
33  const_reference operator[] (size_t __n) const {
34    //To avoid a check on __n we use this strange implementation
35    return (&_Val)[__n];
36  }
37
38private:
39  _CharT _Val;
40};
41
42/*C string wrapper to simulate basic_string*/
43template <class _CharT>
44struct __cstr_wrapper {
45  typedef const _CharT& const_reference;
46
47  __cstr_wrapper(const _CharT *__cstr, size_t __size) :
48    _CStr(__cstr), _Size(__size) {}
49
50  const _CharT* c_str() const { return _CStr; }
51
52  size_t size() const { return _Size; }
53
54  const_reference operator[] (size_t __n) const { return _CStr[__n]; }
55
56private:
57  const _CharT *_CStr;
58  size_t _Size;
59};
60
61/*basic_string wrapper to ensure that we only store a reference to the original string and not copy it*/
62template <class _CharT, class _Traits, class _Alloc>
63struct __bstr_wrapper {
64  typedef const _CharT& const_reference;
65  typedef basic_string<_CharT, _Traits, _Alloc> _BString;
66
67  __bstr_wrapper (_BString const& __s) :
68    _BStr(__s) {}
69
70  size_t size() const { return _BStr.size(); }
71
72  const_reference operator[] (size_t __n) const { return _BStr[__n]; }
73
74  _BString const& b_str() const { return _BStr; }
75
76private:
77  _BString const& _BStr;
78};
79
80struct __on_left {};
81struct __on_right {};
82
83template <class _CharT, class _Traits, class _Alloc,
84          class _Left, class _Right,
85          class _StorageDirection>
86class __bstr_sum {
87public:
88  typedef basic_string<_CharT, _Traits, _Alloc> _BString;
89  typedef typename _BString::const_reference const_reference;
90  typedef typename _BString::const_iterator const_iterator;
91  typedef typename _BString::const_reverse_iterator const_reverse_iterator;
92  typedef typename _BString::size_type size_type;
93  typedef typename _BString::allocator_type allocator_type;
94  typedef __bstr_sum<_CharT, _Traits, _Alloc, _Left, _Right, _StorageDirection> _Self;
95
96  __bstr_sum (_Left const& lhs, _Right const& rhs) :
97    _lhs(lhs), _rhs(rhs) {}
98
99  _Left const& getLhs() const { return _lhs; }
100  _Right const& getRhs() const { return _rhs; }
101
102  allocator_type get_allocator() const { return _M_get_storage(false).get_allocator(); }
103
104  const_iterator begin() const { return _M_get_storage().begin(); }
105  const_iterator end()   const { return _M_get_storage().end(); }
106  const_reverse_iterator rbegin() const { return _M_get_storage().rbegin(); }
107  const_reverse_iterator rend()   const { return _M_get_storage().rend(); }
108
109  size_type size() const { return _lhs.size() + _rhs.size(); }
110  size_type length() const { return size(); }
111
112  size_t max_size() const { return _M_get_storage().max_size(); }
113  size_type capacity() const { return size(); }
114  bool empty() const { return size() == 0; }
115
116  const_reference operator[](size_t __n) const
117  { return (__n < _lhs.size())?_lhs[__n]:_rhs[__n - _lhs.size()]; }
118
119  const_reference at(size_type __n) const
120  { return _M_get_storage().at(__n); }
121
122  //operator +=
123  typedef __bstr_sum<_CharT, _Traits, _Alloc, _Self, __bstr_wrapper<_CharT, _Traits, _Alloc>, __on_left> _BStrOnLeft;
124  _BStrOnLeft operator += (const _BString& __s) { return append(__s); }
125
126  typedef __bstr_sum<_CharT, _Traits, _Alloc, _Self, __cstr_wrapper<_CharT>, __on_left> _CStrOnLeft;
127  _CStrOnLeft operator += (const _CharT* __s) { return append(__s); }
128
129  typedef __bstr_sum<_CharT, _Traits, _Alloc, _Self, __char_wrapper<_CharT>, __on_left> _CharOnLeft;
130  _CharOnLeft operator += (_CharT __c) { return _CharOnLeft(*this, __c); }
131
132  //append
133  _BStrOnLeft append (const _BString& __s)
134  { return _BStrOnLeft(*this, __s); }
135  _BString& append(const _BString& __s, size_type __pos, size_type __n)
136  { return _M_get_storage().append(__s, __pos, __n); }
137  _CStrOnLeft append(const _CharT* __s) {
138    const size_type __n = _Traits::length(__s);
139    return _CStrOnLeft(*this, __cstr_wrapper<_CharT>(__s, __n));
140  }
141  _CStrOnLeft append(const _CharT* __s, size_type __n)
142  { return _CStrOnLeft(*this, __cstr_wrapper<_CharT>(__s, __n)); }
143  _BString& append(size_type __n, _CharT __c)
144  {return _M_get_storage().append(__n, __c);}
145  template <class _InputIter>
146  _BString& append(_InputIter __first, _InputIter __last)
147  {return _M_get_storage().append(__first, __last);}
148
149  //assign
150  _BString& assign(const _BString& __s) {return _M_get_storage().assign(__s);}
151  _BString& assign(const _BString& __s, size_type __pos, size_type __n) {return _M_get_storage().assign(__s, __pos, __n);}
152  _BString& assign(const _CharT* __s, size_type __n) {return _M_get_storage().assign(__s, __n);}
153  _BString& assign(const _CharT* __s) {return _M_get_storage().assign(__s); }
154  _BString& assign(size_type __n, _CharT __c) {return _M_get_storage().assign(__n, __c);}
155
156  //insert
157  _BString& insert(size_type __pos, const _BString& __s) {return _M_get_storage().insert(__pos, __s);}
158  _BString& insert(size_type __pos, const _BString& __s, size_type __beg, size_type __n)
159  {return _M_get_storage().insert(__pos, __s, __beg, __n);}
160  _BString& insert(size_type __pos, const _CharT* __s, size_type __n) {return _M_get_storage().insert(__pos, __s, __n);}
161  _BString& insert(size_type __pos, const _CharT* __s) {return _M_get_storage().insert(__pos, __s);}
162  _BString& insert(size_type __pos, size_type __n, _CharT __c) {return _M_get_storage().insert(__pos, __n, __c);}
163
164  //erase
165  _BString& erase(size_type __pos = 0, size_type __n =_BString::npos) {return _M_get_storage().erase(__pos, __n);}
166
167  //replace
168  _BString& replace(size_type __pos, size_type __n, const _BString& __s)
169  {return _M_get_storage().replace(__pos, __n, __s);}
170  _BString& replace(size_type __pos1, size_type __n1, const _BString& __s, size_type __pos2, size_type __n2)
171  {return _M_get_storage().replace(__pos1, __n1, __s, __pos2, __n2);}
172  _BString& replace(size_type __pos, size_type __n1, const _CharT* __s, size_type __n2)
173  {return _M_get_storage().replace(__pos, __n1, __s, __n2);}
174  _BString& replace(size_type __pos, size_type __n1, const _CharT* __s)
175  {return _M_get_storage().replace(__pos, __n1, __s);}
176  _BString& replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
177  {return _M_get_storage().replace(__pos, __n1, __n2, __c);}
178
179  size_type copy(_CharT* __s, size_type __n, size_type __pos = 0) const
180  {return _M_get_storage().copy(__s, __n, __pos);}
181
182  void swap(_BString& __s)
183  {_M_get_storage().swap(__s);}
184
185  const _CharT* c_str() const { return _M_get_storage().c_str(); }
186  const _CharT* data()  const { return _M_get_storage().data(); }
187
188  //find family
189  size_type find(const _BString& __s, size_type __pos = 0) const { return _M_get_storage().find(__s, __pos); }
190  size_type find(const _CharT* __s, size_type __pos = 0) const { return _M_get_storage().find(__s, __pos); }
191  size_type find(const _CharT* __s, size_type __pos, size_type __n) const { return _M_get_storage().find(__s, __pos, __n); }
192  size_type find(_CharT __c, size_type __pos = 0) const { return _M_get_storage().find(__c, __pos); }
193
194  size_type rfind(const _BString& __s, size_type __pos = _BString::npos) const { return _M_get_storage().rfind(__s, __pos); }
195  size_type rfind(const _CharT* __s, size_type __pos = _BString::npos) const { return _M_get_storage().rfind(__s, __pos); }
196  size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const { return _M_get_storage().rfind(__s, __pos, __n); }
197  size_type rfind(_CharT __c, size_type __pos = _BString::npos) const { return _M_get_storage().rfind(__c, __pos); }
198
199  size_type find_first_of(const _BString& __s, size_type __pos = 0) const
200  { return _M_get_storage().find_first_of(__s, __pos); }
201  size_type find_first_of(const _CharT* __s, size_type __pos = 0) const
202  { return _M_get_storage().find_first_of(__s, __pos); }
203  size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
204  { return _M_get_storage().find_first_of(__s, __pos, __n); }
205  size_type find_first_of(_CharT __c, size_type __pos = 0) const
206  { return _M_get_storage().find(__c, __pos); }
207
208  size_type find_last_of(const _BString& __s, size_type __pos = _BString::npos) const
209  { return _M_get_storage().find_last_of(__s, __pos); }
210  size_type find_last_of(const _CharT* __s, size_type __pos = _BString::npos) const
211  { return _M_get_storage().find_last_of(__s, __pos); }
212  size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
213  { return _M_get_storage().find_last_of(__s, __pos, __n); }
214  size_type find_last_of(_CharT __c, size_type __pos = _BString::npos) const
215  { return _M_get_storage().rfind(__c, __pos); }
216
217  size_type find_first_not_of(const _BString& __s, size_type __pos = 0) const
218  { return _M_get_storage().find_first_not_of(__s, __pos); }
219  size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const
220  { return _M_get_storage().find_first_not_of(__s, __pos); }
221  size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
222  { return _M_get_storage().find_first_not_of(__s, __pos, __n); }
223  size_type find_first_not_of(_CharT __c, size_type __pos = 0) const
224  { return _M_get_storage().find_first_not_of(__c, __pos); }
225
226  size_type find_last_not_of(const _BString& __s, size_type __pos = _BString::npos) const
227  { return _M_get_storage().find_last_not_of(__s, __pos); }
228  size_type find_last_not_of(const _CharT* __s, size_type __pos =_BString:: npos) const
229  { return _M_get_storage().find_last_not_of(__s, __pos); }
230  size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
231  { return _M_get_storage().find_last_not_of(__s, __pos, __n); }
232  size_type find_last_not_of(_CharT __c, size_type __pos = _BString::npos) const
233  { return _M_get_storage().find_last_not_of(__c, __pos); }
234
235  _BString substr(size_type __pos = 0, size_type __n = _BString::npos) const
236  { return _M_get_storage().substr(__pos, __n); }
237
238  //compare
239  int compare(const _BString& __s) const
240  { return _M_get_storage().compare(__s); }
241  int compare(size_type __pos1, size_type __n1, const _Self& __s) const
242  { return _M_get_storage().compare(__pos1, __n1, __s); }
243  int compare(size_type __pos1, size_type __n1, const _Self& __s, size_type __pos2, size_type __n2) const
244  { return _M_get_storage().compare(__pos1, __n1, __s, __pos2, __n2); }
245  int compare(const _CharT* __s) const
246  { return _M_get_storage().compare(__s); }
247  int compare(size_type __pos1, size_type __n1, const _CharT* __s) const
248  { return _M_get_storage().compare(__pos1, __n1, __s); }
249  int compare(size_type __pos1, size_type __n1, const _CharT* __s, size_type __n2) const
250  { return _M_get_storage().compare(__pos1, __n1, __s, __n2); }
251
252  //Returns the underlying basic_string representation of the template expression
253  //The non const method will always initialise it.
254  _BString& _M_get_storage()
255  { return _rhs._M_get_storage(*this, _StorageDirection()); }
256
257  template <class _Lhs, class _Rhs, class _StorageDir>
258  _BString& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir>  const& __ref,
259                           __on_left const& /*StorageDir*/)
260  { return _lhs._M_get_storage(__ref); }
261
262  template <class _Lhs, class _Rhs, class _StorageDir>
263  _BString& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir>  const& __ref,
264                           __on_right const& /*StorageDir*/)
265  { return _rhs._M_get_storage(__ref); }
266
267  template <class _Lhs, class _Rhs, class _StorageDir>
268  _BString& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir>  const& __ref)
269  { return _M_get_storage(__ref, _StorageDirection()); }
270
271  //The const method can be invoked without initialising the basic_string so avoiding dynamic allocation.
272  _BString const& _M_get_storage(bool __do_init = true) const
273  { return _M_get_storage(*this, __do_init, _StorageDirection()); }
274
275  template <class _Lhs, class _Rhs, class _StorageDir>
276  _BString const& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir>  const& __ref,
277                                 bool __do_init, __on_left const& /*StorageDir*/) const
278  { return _lhs._M_get_storage(__ref, __do_init); }
279
280  template <class _Lhs, class _Rhs, class _StorageDir>
281  _BString const& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir>  const& __ref,
282                                 bool __do_init, __on_right const& /*StorageDir*/) const
283  { return _rhs._M_get_storage(__ref, __do_init); }
284
285  template <class _Lhs, class _Rhs, class _StorageDir>
286  _BString const& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir>  const& __ref,
287                                 bool __do_init) const
288  { return _M_get_storage(__ref, __do_init, _StorageDirection()); }
289
290private:
291  _Left  _lhs;
292  _Right _rhs;
293};
294
295/*
296 * For this operator we choose to use the right part as the storage part
297 */
298template <class _CharT, class _Traits, class _Alloc,
299          class _Lh1, class _Rh1, class _StoreDir1,
300          class _Lh2, class _Rh2, class _StoreDir2>
301inline __bstr_sum<_CharT, _Traits, _Alloc,
302                  __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1>,
303                  __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2>,
304                  __on_right> _STLP_CALL
305operator + (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs,
306            const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs) {
307  return __bstr_sum<_CharT, _Traits, _Alloc,
308                    __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1>,
309                    __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2>,
310                    __on_right>(__lhs, __rhs);
311}
312
313template <class _CharT, class _Traits, class _Alloc,
314          class _Lh1, class _Rh1, class _StoreDir1,
315          class _Lh2, class _Rh2, class _StoreDir2>
316inline bool _STLP_CALL
317operator == (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs,
318             const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs)
319{ return (__lhs.size() == __rhs.size()) && (__lhs._M_get_storage() == __rhs._M_get_storage()); }
320
321template <class _CharT, class _Traits, class _Alloc,
322          class _Lh1, class _Rh1, class _StoreDir1,
323          class _Lh2, class _Rh2, class _StoreDir2>
324inline bool _STLP_CALL
325operator < (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs,
326            const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs)
327{ return __lhs._M_get_storage() < __rhs._M_get_storage(); }
328
329#ifdef _STLP_USE_SEPARATE_RELOPS_NAMESPACE
330
331template <class _CharT, class _Traits, class _Alloc,
332          class _Lh1, class _Rh1, class _StoreDir1,
333          class _Lh2, class _Rh2, class _StoreDir2>
334inline bool _STLP_CALL
335operator != (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs,
336             const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs)
337{ return !(__lhs == __rhs); }
338
339template <class _CharT, class _Traits, class _Alloc,
340          class _Lh1, class _Rh1, class _StoreDir1,
341          class _Lh2, class _Rh2, class _StoreDir2>
342inline bool _STLP_CALL
343operator > (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs,
344            const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs)
345{ return __rhs < __lhs; }
346
347template <class _CharT, class _Traits, class _Alloc,
348          class _Lh1, class _Rh1, class _StoreDir1,
349          class _Lh2, class _Rh2, class _StoreDir2>
350inline bool _STLP_CALL
351operator <= (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs,
352             const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs)
353{ return !(__rhs < __lhs); }
354
355template <class _CharT, class _Traits, class _Alloc,
356          class _Lh1, class _Rh1, class _StoreDir1,
357          class _Lh2, class _Rh2, class _StoreDir2>
358inline bool _STLP_CALL
359operator >= (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs,
360             const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs)
361{ return !(__lhs < __rhs); }
362
363#endif /* _STLP_USE_SEPARATE_RELOPS_NAMESPACE */
364
365
366/*
367 * This class will be used to simulate a temporary string that is required for
368 * a call to the c_str method on the __bstr_sum class.
369 */
370
371template <class _CharT, class _Traits, class _Alloc>
372struct __sum_storage_elem {
373  typedef __sum_storage_elem<_CharT, _Traits, _Alloc> _Self;
374  typedef basic_string<_CharT, _Traits, _Alloc> _BString;
375
376  __sum_storage_elem(_Alloc __alloc) : _M_init(false), _M_storage(__alloc)
377  {}
378
379  template <class _Left, class _Right, class _StorageDir>
380  void _M_Init(__bstr_sum<_CharT, _Traits, _Alloc, _Left, _Right, _StorageDir>  const& __ref) const {
381    if (!_M_init) {
382      _STLP_MUTABLE(_Self, _M_storage) = __ref;
383      _STLP_MUTABLE(_Self, _M_init) = true;
384    }
385  }
386
387  template <class _Left, class _Right, class _StorageDir>
388  _BString const& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Left, _Right, _StorageDir>  const& __ref,
389                                 bool __do_init) const {
390    if (__do_init) {
391      _M_Init(__ref);
392    }
393    return _M_storage;
394  }
395  template <class _Left, class _Right, class _StorageDir>
396  _BString& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Left, _Right, _StorageDir>  const& __ref) {
397    _M_Init(__ref);
398    return _M_storage;
399  }
400
401  size_t size() const { return 0; }
402  _CharT const& operator[](size_t __n) const
403  { return __STATIC_CAST(_CharT*, 0)[__n]; }
404
405private:
406  mutable bool _M_init;
407  mutable basic_string<_CharT, _Traits, _Alloc> _M_storage;
408};
409
410_STLP_MOVE_TO_STD_NAMESPACE
411
412_STLP_END_NAMESPACE
413
414#endif /*_STLP_STRING_SUM_H*/
415