williamr@2: /* williamr@2: * Copyright (c) 2003 williamr@2: * Francois Dumont williamr@2: * williamr@2: * This material is provided "as is", with absolutely no warranty expressed williamr@2: * or implied. Any use is at your own risk. williamr@2: * williamr@2: * Permission to use or copy this software for any purpose is hereby granted williamr@2: * without fee, provided the above notices are retained on all copies. williamr@2: * Permission to modify the code and to distribute modified code is granted, williamr@2: * provided the above notices are retained, and a notice that the code was williamr@2: * modified is included with the above copyright notice. williamr@2: * williamr@2: */ williamr@2: williamr@2: #ifndef _STLP_STRING_SUM_H williamr@2: #define _STLP_STRING_SUM_H williamr@2: williamr@2: _STLP_BEGIN_NAMESPACE williamr@2: williamr@2: _STLP_MOVE_TO_PRIV_NAMESPACE williamr@2: williamr@2: /*char wrapper to simulate basic_string*/ williamr@2: template williamr@2: struct __char_wrapper { williamr@2: typedef const _CharT& const_reference; williamr@2: williamr@2: __char_wrapper(_CharT __val) : _Val(__val) {} williamr@2: williamr@2: _CharT getValue() const { return _Val; } williamr@2: size_t size() const { return 1; } williamr@2: williamr@2: const_reference operator[] (size_t __n) const { williamr@2: //To avoid a check on __n we use this strange implementation williamr@2: return (&_Val)[__n]; williamr@2: } williamr@2: williamr@2: private: williamr@2: _CharT _Val; williamr@2: }; williamr@2: williamr@2: /*C string wrapper to simulate basic_string*/ williamr@2: template williamr@2: struct __cstr_wrapper { williamr@2: typedef const _CharT& const_reference; williamr@2: williamr@2: __cstr_wrapper(const _CharT *__cstr, size_t __size) : williamr@2: _CStr(__cstr), _Size(__size) {} williamr@2: williamr@2: const _CharT* c_str() const { return _CStr; } williamr@2: williamr@2: size_t size() const { return _Size; } williamr@2: williamr@2: const_reference operator[] (size_t __n) const { return _CStr[__n]; } williamr@2: williamr@2: private: williamr@2: const _CharT *_CStr; williamr@2: size_t _Size; williamr@2: }; williamr@2: williamr@2: /*basic_string wrapper to ensure that we only store a reference to the original string and not copy it*/ williamr@2: template williamr@2: struct __bstr_wrapper { williamr@2: typedef const _CharT& const_reference; williamr@2: typedef basic_string<_CharT, _Traits, _Alloc> _BString; williamr@2: williamr@2: __bstr_wrapper (_BString const& __s) : williamr@2: _BStr(__s) {} williamr@2: williamr@2: size_t size() const { return _BStr.size(); } williamr@2: williamr@2: const_reference operator[] (size_t __n) const { return _BStr[__n]; } williamr@2: williamr@2: _BString const& b_str() const { return _BStr; } williamr@2: williamr@2: private: williamr@2: _BString const& _BStr; williamr@2: }; williamr@2: williamr@2: struct __on_left {}; williamr@2: struct __on_right {}; williamr@2: williamr@2: template williamr@2: class __bstr_sum { williamr@2: public: williamr@2: typedef basic_string<_CharT, _Traits, _Alloc> _BString; williamr@2: typedef typename _BString::const_reference const_reference; williamr@2: typedef typename _BString::const_iterator const_iterator; williamr@2: typedef typename _BString::const_reverse_iterator const_reverse_iterator; williamr@2: typedef typename _BString::size_type size_type; williamr@2: typedef typename _BString::allocator_type allocator_type; williamr@2: typedef __bstr_sum<_CharT, _Traits, _Alloc, _Left, _Right, _StorageDirection> _Self; williamr@2: williamr@2: __bstr_sum (_Left const& lhs, _Right const& rhs) : williamr@2: _lhs(lhs), _rhs(rhs) {} williamr@2: williamr@2: _Left const& getLhs() const { return _lhs; } williamr@2: _Right const& getRhs() const { return _rhs; } williamr@2: williamr@2: allocator_type get_allocator() const { return _M_get_storage(false).get_allocator(); } williamr@2: williamr@2: const_iterator begin() const { return _M_get_storage().begin(); } williamr@2: const_iterator end() const { return _M_get_storage().end(); } williamr@2: const_reverse_iterator rbegin() const { return _M_get_storage().rbegin(); } williamr@2: const_reverse_iterator rend() const { return _M_get_storage().rend(); } williamr@2: williamr@2: size_type size() const { return _lhs.size() + _rhs.size(); } williamr@2: size_type length() const { return size(); } williamr@2: williamr@2: size_t max_size() const { return _M_get_storage().max_size(); } williamr@2: size_type capacity() const { return size(); } williamr@2: bool empty() const { return size() == 0; } williamr@2: williamr@2: const_reference operator[](size_t __n) const williamr@2: { return (__n < _lhs.size())?_lhs[__n]:_rhs[__n - _lhs.size()]; } williamr@2: williamr@2: const_reference at(size_type __n) const williamr@2: { return _M_get_storage().at(__n); } williamr@2: williamr@2: //operator += williamr@2: typedef __bstr_sum<_CharT, _Traits, _Alloc, _Self, __bstr_wrapper<_CharT, _Traits, _Alloc>, __on_left> _BStrOnLeft; williamr@2: _BStrOnLeft operator += (const _BString& __s) { return append(__s); } williamr@2: williamr@2: typedef __bstr_sum<_CharT, _Traits, _Alloc, _Self, __cstr_wrapper<_CharT>, __on_left> _CStrOnLeft; williamr@2: _CStrOnLeft operator += (const _CharT* __s) { return append(__s); } williamr@2: williamr@2: typedef __bstr_sum<_CharT, _Traits, _Alloc, _Self, __char_wrapper<_CharT>, __on_left> _CharOnLeft; williamr@2: _CharOnLeft operator += (_CharT __c) { return _CharOnLeft(*this, __c); } williamr@2: williamr@2: //append williamr@2: _BStrOnLeft append (const _BString& __s) williamr@2: { return _BStrOnLeft(*this, __s); } williamr@2: _BString& append(const _BString& __s, size_type __pos, size_type __n) williamr@2: { return _M_get_storage().append(__s, __pos, __n); } williamr@2: _CStrOnLeft append(const _CharT* __s) { williamr@2: const size_type __n = _Traits::length(__s); williamr@2: return _CStrOnLeft(*this, __cstr_wrapper<_CharT>(__s, __n)); williamr@2: } williamr@2: _CStrOnLeft append(const _CharT* __s, size_type __n) williamr@2: { return _CStrOnLeft(*this, __cstr_wrapper<_CharT>(__s, __n)); } williamr@2: _BString& append(size_type __n, _CharT __c) williamr@2: {return _M_get_storage().append(__n, __c);} williamr@2: template williamr@2: _BString& append(_InputIter __first, _InputIter __last) williamr@2: {return _M_get_storage().append(__first, __last);} williamr@2: williamr@2: //assign williamr@2: _BString& assign(const _BString& __s) {return _M_get_storage().assign(__s);} williamr@2: _BString& assign(const _BString& __s, size_type __pos, size_type __n) {return _M_get_storage().assign(__s, __pos, __n);} williamr@2: _BString& assign(const _CharT* __s, size_type __n) {return _M_get_storage().assign(__s, __n);} williamr@2: _BString& assign(const _CharT* __s) {return _M_get_storage().assign(__s); } williamr@2: _BString& assign(size_type __n, _CharT __c) {return _M_get_storage().assign(__n, __c);} williamr@2: williamr@2: //insert williamr@2: _BString& insert(size_type __pos, const _BString& __s) {return _M_get_storage().insert(__pos, __s);} williamr@2: _BString& insert(size_type __pos, const _BString& __s, size_type __beg, size_type __n) williamr@2: {return _M_get_storage().insert(__pos, __s, __beg, __n);} williamr@2: _BString& insert(size_type __pos, const _CharT* __s, size_type __n) {return _M_get_storage().insert(__pos, __s, __n);} williamr@2: _BString& insert(size_type __pos, const _CharT* __s) {return _M_get_storage().insert(__pos, __s);} williamr@2: _BString& insert(size_type __pos, size_type __n, _CharT __c) {return _M_get_storage().insert(__pos, __n, __c);} williamr@2: williamr@2: //erase williamr@2: _BString& erase(size_type __pos = 0, size_type __n =_BString::npos) {return _M_get_storage().erase(__pos, __n);} williamr@2: williamr@2: //replace williamr@2: _BString& replace(size_type __pos, size_type __n, const _BString& __s) williamr@2: {return _M_get_storage().replace(__pos, __n, __s);} williamr@2: _BString& replace(size_type __pos1, size_type __n1, const _BString& __s, size_type __pos2, size_type __n2) williamr@2: {return _M_get_storage().replace(__pos1, __n1, __s, __pos2, __n2);} williamr@2: _BString& replace(size_type __pos, size_type __n1, const _CharT* __s, size_type __n2) williamr@2: {return _M_get_storage().replace(__pos, __n1, __s, __n2);} williamr@2: _BString& replace(size_type __pos, size_type __n1, const _CharT* __s) williamr@2: {return _M_get_storage().replace(__pos, __n1, __s);} williamr@2: _BString& replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c) williamr@2: {return _M_get_storage().replace(__pos, __n1, __n2, __c);} williamr@2: williamr@2: size_type copy(_CharT* __s, size_type __n, size_type __pos = 0) const williamr@2: {return _M_get_storage().copy(__s, __n, __pos);} williamr@2: williamr@2: void swap(_BString& __s) williamr@2: {_M_get_storage().swap(__s);} williamr@2: williamr@2: const _CharT* c_str() const { return _M_get_storage().c_str(); } williamr@2: const _CharT* data() const { return _M_get_storage().data(); } williamr@2: williamr@2: //find family williamr@2: size_type find(const _BString& __s, size_type __pos = 0) const { return _M_get_storage().find(__s, __pos); } williamr@2: size_type find(const _CharT* __s, size_type __pos = 0) const { return _M_get_storage().find(__s, __pos); } williamr@2: size_type find(const _CharT* __s, size_type __pos, size_type __n) const { return _M_get_storage().find(__s, __pos, __n); } williamr@2: size_type find(_CharT __c, size_type __pos = 0) const { return _M_get_storage().find(__c, __pos); } williamr@2: williamr@2: size_type rfind(const _BString& __s, size_type __pos = _BString::npos) const { return _M_get_storage().rfind(__s, __pos); } williamr@2: size_type rfind(const _CharT* __s, size_type __pos = _BString::npos) const { return _M_get_storage().rfind(__s, __pos); } williamr@2: size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const { return _M_get_storage().rfind(__s, __pos, __n); } williamr@2: size_type rfind(_CharT __c, size_type __pos = _BString::npos) const { return _M_get_storage().rfind(__c, __pos); } williamr@2: williamr@2: size_type find_first_of(const _BString& __s, size_type __pos = 0) const williamr@2: { return _M_get_storage().find_first_of(__s, __pos); } williamr@2: size_type find_first_of(const _CharT* __s, size_type __pos = 0) const williamr@2: { return _M_get_storage().find_first_of(__s, __pos); } williamr@2: size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const williamr@2: { return _M_get_storage().find_first_of(__s, __pos, __n); } williamr@2: size_type find_first_of(_CharT __c, size_type __pos = 0) const williamr@2: { return _M_get_storage().find(__c, __pos); } williamr@2: williamr@2: size_type find_last_of(const _BString& __s, size_type __pos = _BString::npos) const williamr@2: { return _M_get_storage().find_last_of(__s, __pos); } williamr@2: size_type find_last_of(const _CharT* __s, size_type __pos = _BString::npos) const williamr@2: { return _M_get_storage().find_last_of(__s, __pos); } williamr@2: size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const williamr@2: { return _M_get_storage().find_last_of(__s, __pos, __n); } williamr@2: size_type find_last_of(_CharT __c, size_type __pos = _BString::npos) const williamr@2: { return _M_get_storage().rfind(__c, __pos); } williamr@2: williamr@2: size_type find_first_not_of(const _BString& __s, size_type __pos = 0) const williamr@2: { return _M_get_storage().find_first_not_of(__s, __pos); } williamr@2: size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const williamr@2: { return _M_get_storage().find_first_not_of(__s, __pos); } williamr@2: size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const williamr@2: { return _M_get_storage().find_first_not_of(__s, __pos, __n); } williamr@2: size_type find_first_not_of(_CharT __c, size_type __pos = 0) const williamr@2: { return _M_get_storage().find_first_not_of(__c, __pos); } williamr@2: williamr@2: size_type find_last_not_of(const _BString& __s, size_type __pos = _BString::npos) const williamr@2: { return _M_get_storage().find_last_not_of(__s, __pos); } williamr@2: size_type find_last_not_of(const _CharT* __s, size_type __pos =_BString:: npos) const williamr@2: { return _M_get_storage().find_last_not_of(__s, __pos); } williamr@2: size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const williamr@2: { return _M_get_storage().find_last_not_of(__s, __pos, __n); } williamr@2: size_type find_last_not_of(_CharT __c, size_type __pos = _BString::npos) const williamr@2: { return _M_get_storage().find_last_not_of(__c, __pos); } williamr@2: williamr@2: _BString substr(size_type __pos = 0, size_type __n = _BString::npos) const williamr@2: { return _M_get_storage().substr(__pos, __n); } williamr@2: williamr@2: //compare williamr@2: int compare(const _BString& __s) const williamr@2: { return _M_get_storage().compare(__s); } williamr@2: int compare(size_type __pos1, size_type __n1, const _Self& __s) const williamr@2: { return _M_get_storage().compare(__pos1, __n1, __s); } williamr@2: int compare(size_type __pos1, size_type __n1, const _Self& __s, size_type __pos2, size_type __n2) const williamr@2: { return _M_get_storage().compare(__pos1, __n1, __s, __pos2, __n2); } williamr@2: int compare(const _CharT* __s) const williamr@2: { return _M_get_storage().compare(__s); } williamr@2: int compare(size_type __pos1, size_type __n1, const _CharT* __s) const williamr@2: { return _M_get_storage().compare(__pos1, __n1, __s); } williamr@2: int compare(size_type __pos1, size_type __n1, const _CharT* __s, size_type __n2) const williamr@2: { return _M_get_storage().compare(__pos1, __n1, __s, __n2); } williamr@2: williamr@2: //Returns the underlying basic_string representation of the template expression williamr@2: //The non const method will always initialise it. williamr@2: _BString& _M_get_storage() williamr@2: { return _rhs._M_get_storage(*this, _StorageDirection()); } williamr@2: williamr@2: template williamr@2: _BString& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir> const& __ref, williamr@2: __on_left const& /*StorageDir*/) williamr@2: { return _lhs._M_get_storage(__ref); } williamr@2: williamr@2: template williamr@2: _BString& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir> const& __ref, williamr@2: __on_right const& /*StorageDir*/) williamr@2: { return _rhs._M_get_storage(__ref); } williamr@2: williamr@2: template williamr@2: _BString& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir> const& __ref) williamr@2: { return _M_get_storage(__ref, _StorageDirection()); } williamr@2: williamr@2: //The const method can be invoked without initialising the basic_string so avoiding dynamic allocation. williamr@2: _BString const& _M_get_storage(bool __do_init = true) const williamr@2: { return _M_get_storage(*this, __do_init, _StorageDirection()); } williamr@2: williamr@2: template williamr@2: _BString const& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir> const& __ref, williamr@2: bool __do_init, __on_left const& /*StorageDir*/) const williamr@2: { return _lhs._M_get_storage(__ref, __do_init); } williamr@2: williamr@2: template williamr@2: _BString const& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir> const& __ref, williamr@2: bool __do_init, __on_right const& /*StorageDir*/) const williamr@2: { return _rhs._M_get_storage(__ref, __do_init); } williamr@2: williamr@2: template williamr@2: _BString const& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Lhs, _Rhs, _StorageDir> const& __ref, williamr@2: bool __do_init) const williamr@2: { return _M_get_storage(__ref, __do_init, _StorageDirection()); } williamr@2: williamr@2: private: williamr@2: _Left _lhs; williamr@2: _Right _rhs; williamr@2: }; williamr@2: williamr@2: /* williamr@2: * For this operator we choose to use the right part as the storage part williamr@2: */ williamr@2: template williamr@2: inline __bstr_sum<_CharT, _Traits, _Alloc, williamr@2: __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1>, williamr@2: __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2>, williamr@2: __on_right> _STLP_CALL williamr@2: operator + (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs, williamr@2: const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs) { williamr@2: return __bstr_sum<_CharT, _Traits, _Alloc, williamr@2: __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1>, williamr@2: __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2>, williamr@2: __on_right>(__lhs, __rhs); williamr@2: } williamr@2: williamr@2: template williamr@2: inline bool _STLP_CALL williamr@2: operator == (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs, williamr@2: const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs) williamr@2: { return (__lhs.size() == __rhs.size()) && (__lhs._M_get_storage() == __rhs._M_get_storage()); } williamr@2: williamr@2: template williamr@2: inline bool _STLP_CALL williamr@2: operator < (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs, williamr@2: const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs) williamr@2: { return __lhs._M_get_storage() < __rhs._M_get_storage(); } williamr@2: williamr@2: #ifdef _STLP_USE_SEPARATE_RELOPS_NAMESPACE williamr@2: williamr@2: template williamr@2: inline bool _STLP_CALL williamr@2: operator != (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs, williamr@2: const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs) williamr@2: { return !(__lhs == __rhs); } williamr@2: williamr@2: template williamr@2: inline bool _STLP_CALL williamr@2: operator > (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs, williamr@2: const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs) williamr@2: { return __rhs < __lhs; } williamr@2: williamr@2: template williamr@2: inline bool _STLP_CALL williamr@2: operator <= (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs, williamr@2: const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs) williamr@2: { return !(__rhs < __lhs); } williamr@2: williamr@2: template williamr@2: inline bool _STLP_CALL williamr@2: operator >= (const __bstr_sum<_CharT, _Traits, _Alloc, _Lh1, _Rh1, _StoreDir1> &__lhs, williamr@2: const __bstr_sum<_CharT, _Traits, _Alloc, _Lh2, _Rh2, _StoreDir2> &__rhs) williamr@2: { return !(__lhs < __rhs); } williamr@2: williamr@2: #endif /* _STLP_USE_SEPARATE_RELOPS_NAMESPACE */ williamr@2: williamr@2: williamr@2: /* williamr@2: * This class will be used to simulate a temporary string that is required for williamr@2: * a call to the c_str method on the __bstr_sum class. williamr@2: */ williamr@2: williamr@2: template williamr@2: struct __sum_storage_elem { williamr@2: typedef basic_string<_CharT, _Traits, _Alloc> _BString; williamr@2: williamr@2: __sum_storage_elem(_Alloc __alloc) : _M_init(false), _M_storage(__alloc) williamr@2: {} williamr@2: williamr@2: template williamr@2: void _M_Init(__bstr_sum<_CharT, _Traits, _Alloc, _Left, _Right, _StorageDir> const& __ref) const { williamr@2: if (!_M_init) { williamr@2: _M_storage = __ref; williamr@2: _M_init = true; williamr@2: } williamr@2: } williamr@2: williamr@2: template williamr@2: _BString const& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Left, _Right, _StorageDir> const& __ref, williamr@2: bool __do_init) const { williamr@2: if (__do_init) { williamr@2: _M_Init(__ref); williamr@2: } williamr@2: return _M_storage; williamr@2: } williamr@2: template williamr@2: _BString& _M_get_storage(__bstr_sum<_CharT, _Traits, _Alloc, _Left, _Right, _StorageDir> const& __ref) { williamr@2: _M_Init(__ref); williamr@2: return _M_storage; williamr@2: } williamr@2: williamr@2: size_t size() const { return 0; } williamr@2: _CharT const& operator[](size_t __n) const williamr@2: { return __STATIC_CAST(_CharT*, 0)[__n]; } williamr@2: williamr@2: private: williamr@2: mutable bool _M_init; williamr@2: mutable basic_string<_CharT, _Traits, _Alloc> _M_storage; williamr@2: }; williamr@2: williamr@2: _STLP_MOVE_TO_STD_NAMESPACE williamr@2: williamr@2: _STLP_END_NAMESPACE williamr@2: williamr@2: #endif /*_STLP_STRING_SUM_H*/