#ifndef __STRING_R_H #define __STRING_R_H #pragma option push -b -a8 -pc -Vx- -Ve- -w-inl -w-aus -w-sig // -*- C++ -*- /*************************************************************************** * * string_ref - Declarations for the Standard Library string_ref classes * *************************************************************************** * * Copyright (c) 1994-1999 Rogue Wave Software, Inc. All Rights Reserved. * * This computer software is owned by Rogue Wave Software, Inc. and is * protected by U.S. copyright laws and other laws and by international * treaties. This computer software is furnished by Rogue Wave Software, * Inc. pursuant to a written license agreement and may be used, copied, * transmitted, and stored only in accordance with the terms of such * license and with the inclusion of the above copyright notice. This * computer software or any other copies thereof may not be provided or * otherwise made available to any other person. * * U.S. Government Restricted Rights. This computer software is provided * with Restricted Rights. Use, duplication, or disclosure by the * Government is subject to restrictions as set forth in subparagraph (c) * (1) (ii) of The Rights in Technical Data and Computer Software clause * at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the * Commercial Computer Software – Restricted Rights at 48 CFR 52.227-19, * as applicable. Manufacturer is Rogue Wave Software, Inc., 5500 * Flatiron Parkway, Boulder, Colorado 80301 USA. * **************************************************************************/ #ifndef __STD_STRING_REF #define __STD_STRING_REF #include #include #include // For allocator. #include #ifndef _RWSTD_NO_NAMESPACE namespace std { #endif // // Class & Structure Declarations // template< class charT, class traits _RWSTD_COMPLEX_DEFAULT(char_traits), class Allocator _RWSTD_COMPLEX_DEFAULT(allocator) > class basic_string; #ifndef _RWSTD_NO_NAMESPACE } namespace __rwstd { #endif // // __string_noref_rep and __string_noref are used to implement a // non-reference counted string. Use this implementation when the // overhead from the reference counting (including mutex locking) // overwhelms the advantages. One example of such a situation would // be in an application that infrequently copies short strings and // only very rarely copies long ones. Another example would be an // application that makes heavy use of iterators from basic_string, // since any outstanding refernece into the string data nullifies // the advantages of reference counting. // template class _RWSTDExportTemplate __string_noref_rep { public: _EXPLICIT __string_noref_rep(long refs = 0) : __refs_((bool)refs), __capacity_(0), __nchars_(0) {;} __string_noref_rep(const __string_noref_rep& r) : __refs_((bool)r.__refs_), __capacity_(0), __nchars_(0) {;} typedef Allocator allocator_type; typedef _TYPENAME _RWSTD_ALLOC_SIZE_TYPE size_type; protected: bool __refs_; // true if null ref, else false size_type __capacity_; // Size of allocated memory size_type __nchars_; // Number of actual data values stored }; template class _RWSTDExportTemplate __string_noref : public __string_noref_rep { public: typedef __string_noref_rep __string_ref_rep_type; typedef _TYPENAME __string_noref_rep::size_type size_type; _EXPLICIT __string_noref (long=0) { ; } private: long __references () const { return (long)__string_noref_rep::__refs_; } void __setRefCount (long r) { ; } void __addReference () { ; } long __removeReference () { return (long)__string_noref_rep::__refs_; } size_type length () const { return __string_noref_rep::__nchars_; } size_type __getCapac () const { return __string_noref_rep::__capacity_; } charT* data () const { return (charT*)(this+1); } charT& operator[] (size_type i) { return (_RWSTD_REINTERPRET_CAST(charT*,(this+1)))[i]; } const charT& operator[] (size_type i) const { return ((charT*)(this+1))[i]; } #ifndef _RWSTD_NO_NAMESPACE friend class std::basic_string; #else friend class basic_string; #endif }; // // __string_ref_rep and __string_ref are used to implement a // reference counted string. Using this class basic_string // optimizes copying by sharing data whenever possible. Copies // are only made when absolutely necessary. // #if defined (_RWSTD_MULTI_THREAD) && defined(_RWSTD_ONE_STRING_MUTEX) && defined(_RWSTD_NO_TEST_AND_SET) extern _RWSTDMutex _RWSTDExport __rw_string_mutex; #endif /* _RWSTD_MULTI_THREAD */ template class _RWSTDExportTemplate __string_ref_rep { public: // the __refs_ are initialized to 1 because of a problem // where the destructor was being called when it // should not be. __string_ref_rep() : __refs_(0), __capacity_(0), __nchars_(0) {;} __string_ref_rep(long x) : __refs_(x), __capacity_(0), __nchars_(0) {;} __string_ref_rep(const __string_ref_rep& r) : __refs_(r.__refs_), __capacity_(0), __nchars_(0) {;} typedef Allocator allocator_type; typedef _TYPENAME _RWSTD_ALLOC_SIZE_TYPE size_type; protected: #if defined (_RWSTD_MULTI_THREAD) && !defined(_RWSTD_ONE_STRING_MUTEX) && defined(_RWSTD_NO_TEST_AND_SET) _RWSTDMutex __mutex_; #endif /* _RWSTD_MULTI_THREAD */ long __refs_; // (1 less than) number of references // (-2 if reference counting disabled) size_type __capacity_; // Size of allocated memory size_type __nchars_; // Number of actual data values stored }; template class _RWSTDExportTemplate __string_ref : public __string_ref_rep { public: typedef __string_ref_rep __string_ref_rep_type; typedef _TYPENAME __string_ref_rep::size_type size_type; _EXPLICIT __string_ref (long initRef = 0) : __string_ref_rep(initRef - 1) { ; } __string_ref (const __string_ref& ref) : __string_ref_rep(ref.__refs_) { ; } private: long __references () const { return __string_ref_rep::__refs_+1; } void __setRefCount (long r) { if (this != _RW_STD::basic_string::__getNullRep()) { #ifdef _RWSTD_NO_TEST_AND_SET #ifdef _RWSTD_MULTI_THREAD #ifdef _RWSTD_ONE_STRING_MUTEX _RWSTDGuard guard(__rw_string_mutex); #else _RWSTDGuard guard(this->__mutex_); #endif #endif /* _RWSTD_MULTI_THREAD */ #endif /* _RWSTD_NO_TEST_AND_SET */ _RWSTD_MT_SET(this->__refs_,r-1); } } void __addReference () { if (this != _RW_STD::basic_string::__getNullRep()) { #ifdef _RWSTD_NO_TEST_AND_SET #ifdef _RWSTD_MULTI_THREAD #ifdef _RWSTD_ONE_STRING_MUTEX _RWSTDGuard guard(__rw_string_mutex); #else _RWSTDGuard guard(this->__mutex_); #endif #endif /* _RWSTD_MULTI_THREAD */ #endif /* _RWSTD_NO_TEST_AND_SET */ _RWSTD_MT_INCREMENT(this->__refs_); } } long __removeReference () { if (this != _RW_STD::basic_string::__getNullRep()) { #ifdef _RWSTD_NO_TEST_AND_SET #ifdef _RWSTD_MULTI_THREAD #ifdef _RWSTD_ONE_STRING_MUTEX _RWSTDGuard guard(__rw_string_mutex); #else _RWSTDGuard guard(this->__mutex_); #endif #endif /* _RWSTD_MULTI_THREAD */ #endif /* _RWSTD_NO_TEST_AND_SET */ return __unSafeRemoveReference(); } else return 1; } long __unSafeRemoveReference () { if (this != _RW_STD::basic_string::__getNullRep()) { _RWSTD_MT_DECREMENT(this->__refs_); return this->__refs_+1; } else return 1; } size_type length () const { return __string_ref_rep::__nchars_; } size_type __getCapac () const { return __string_ref_rep::__capacity_;} charT* data () const { return (charT*)(this+1); } charT& operator[] (size_type i) { return (_RWSTD_REINTERPRET_CAST(charT*,(this+1)))[i]; } const charT& operator[] (size_type i) const { return ((charT*)(this+1))[i]; } #ifndef _RWSTD_NO_NAMESPACE friend class std::basic_string; #else friend class basic_string; #endif }; // // __null_string_ref_rep is used to provide a single empty // string reference for all instances of empty strings. // This makes empty strings much smaller and avoids unecessary // allocations of reference objects. // template ) > struct _RWSTDExportTemplate __null_string_ref_rep { // // __ref_hdr_ has to be immediately followed by __eos_char_ ! // stringRef __ref_hdr_; charT __eos_char_; __null_string_ref_rep () : __ref_hdr_(1), __eos_char_(charT(0)) {;} __null_string_ref_rep (const __null_string_ref_rep& r) : __ref_hdr_(r.__ref_hdr_), __eos_char_(charT(0)) {;} }; #ifndef _RWSTD_NO_NAMESPACE } // End of __rwstd #endif #endif // __STD_STRING_REF #pragma option pop #endif /* __STRING_R_H */