Home | History | Annotate | Download | only in stl
      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*/
     24 template <class _CharT>
     25 struct __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 
     38 private:
     39   _CharT _Val;
     40 };
     41 
     42 /*C string wrapper to simulate basic_string*/
     43 template <class _CharT>
     44 struct __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 
     56 private:
     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*/
     62 template <class _CharT, class _Traits, class _Alloc>
     63 struct __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 
     76 private:
     77   _BString const& _BStr;
     78 };
     79 
     80 struct __on_left {};
     81 struct __on_right {};
     82 
     83 template <class _CharT, class _Traits, class _Alloc,
     84           class _Left, class _Right,
     85           class _StorageDirection>
     86 class __bstr_sum {
     87 public:
     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 
    290 private:
    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  */
    298 template <class _CharT, class _Traits, class _Alloc,
    299           class _Lh1, class _Rh1, class _StoreDir1,
    300           class _Lh2, class _Rh2, class _StoreDir2>
    301 inline __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
    305 operator + (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 
    313 template <class _CharT, class _Traits, class _Alloc,
    314           class _Lh1, class _Rh1, class _StoreDir1,
    315           class _Lh2, class _Rh2, class _StoreDir2>
    316 inline bool _STLP_CALL
    317 operator == (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 
    321 template <class _CharT, class _Traits, class _Alloc,
    322           class _Lh1, class _Rh1, class _StoreDir1,
    323           class _Lh2, class _Rh2, class _StoreDir2>
    324 inline bool _STLP_CALL
    325 operator < (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 
    331 template <class _CharT, class _Traits, class _Alloc,
    332           class _Lh1, class _Rh1, class _StoreDir1,
    333           class _Lh2, class _Rh2, class _StoreDir2>
    334 inline bool _STLP_CALL
    335 operator != (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 
    339 template <class _CharT, class _Traits, class _Alloc,
    340           class _Lh1, class _Rh1, class _StoreDir1,
    341           class _Lh2, class _Rh2, class _StoreDir2>
    342 inline bool _STLP_CALL
    343 operator > (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 
    347 template <class _CharT, class _Traits, class _Alloc,
    348           class _Lh1, class _Rh1, class _StoreDir1,
    349           class _Lh2, class _Rh2, class _StoreDir2>
    350 inline bool _STLP_CALL
    351 operator <= (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 
    355 template <class _CharT, class _Traits, class _Alloc,
    356           class _Lh1, class _Rh1, class _StoreDir1,
    357           class _Lh2, class _Rh2, class _StoreDir2>
    358 inline bool _STLP_CALL
    359 operator >= (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 
    371 template <class _CharT, class _Traits, class _Alloc>
    372 struct __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 
    405 private:
    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