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