| /*************************************************************************** |
| * |
| * _strref.h - Declarations for the Standard Library string_ref classes |
| * |
| * This is an internal header file used to implement the C++ Standard |
| * Library. It should never be #included directly by a program. |
| * |
| * $Id$ |
| * |
| *************************************************************************** |
| * |
| * Copyright 2005-2006 The Apache Software Foundation or its licensors, |
| * as applicable. |
| * |
| * Copyright 1994-2006 Rogue Wave Software. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| **************************************************************************/ |
| |
| #ifndef _RWSTD_RW_STRREF_H_INCLUDED |
| #define _RWSTD_RW_STRREF_H_INCLUDED |
| |
| #ifndef _RWSTD_RW_ALLOCATOR_H_INCLUDED |
| # include <rw/_allocator.h> |
| #endif // _RWSTD_RW_ALLOCATOR_H_INCLUDED |
| |
| #ifndef _RWSTD_RW_MUTEX_H_INCLUDED |
| # include <rw/_mutex.h> |
| #endif // _RWSTD_RW_MUTEX_H_INCLUDED |
| |
| #ifndef _RWSTD_RW_SPECIALIZED_H_INCLUDED |
| # include <rw/_specialized.h> |
| #endif // _RWSTD_RW_SPECIALIZED_H_INCLUDED |
| |
| #ifndef _RWSTD_RW_TRAITS_H_INCLUDED |
| # include <rw/_traits.h> |
| #endif // _RWSTD_RW_TRAITS_H_INCLUDED |
| |
| |
| #if !defined(_RWSTD_STRING_REF_OFFSET) |
| # define _RWSTD_STRING_REF_OFFSET 1 |
| #endif |
| |
| #if !defined(_RWSTD_STRING_REF_INT) |
| # define _RWSTD_STRING_REF_INT long |
| #endif |
| |
| #ifndef _RWSTD_NO_ATOMIC_OPS |
| // disable string mutex when atomic operations are available |
| # ifndef _RWSTD_NO_STRING_MUTEX |
| # define _RWSTD_NO_STRING_MUTEX |
| # endif // _RWSTD_NO_STRING_MUTEX |
| #endif // _RWSTD_NO_ATOMIC_OPS |
| |
| _RWSTD_NAMESPACE (std) { |
| |
| |
| // chooses either a single global mutex or a mutex per string object |
| // or no mutex at all when atomic test-and-set instruction is available |
| #if !defined (_RWSTD_REENTRANT) || defined (_RWSTD_NO_STRING_MUTEX) |
| # define _RWSTD_STRING_MUTEX(ignore) false |
| #elif defined (_RWSTD_ONE_STRING_MUTEX) |
| # define _RWSTD_STRING_MUTEX(ignore) __rw_string_mutex |
| #else |
| # define _RWSTD_STRING_MUTEX(pstr) pstr->_C_mutex |
| #endif |
| |
| |
| template <class _CharT, |
| class _Traits = char_traits<_CharT>, |
| class _Allocator = allocator<_CharT> > |
| class basic_string; |
| |
| |
| } // namespace std |
| |
| |
| _RWSTD_NAMESPACE (__rw) { |
| |
| |
| #if defined (_RWSTD_REENTRANT) \ |
| && defined (_RWSTD_ONE_STRING_MUTEX) \ |
| && !defined (_RWSTD_NO_STRING_MUTEX) |
| |
| extern __rw_mutex _RWSTD_EXPORT __rw_string_mutex; |
| |
| #endif // _REENTRANT && _ONE_STRING_MUTEX && !NO_STRING_MUTEX |
| |
| |
| template <class _CharT, class _Traits , class _Allocator> |
| struct __string_ref |
| { |
| typedef _CharT char_type; |
| typedef _Allocator allocator_type; |
| typedef _TYPENAME allocator_type::size_type size_type; |
| typedef _STD::basic_string<_CharT, _Traits, _Allocator> string_type; |
| |
| #if defined (_RWSTD_REENTRANT) \ |
| && !defined (_RWSTD_ONE_STRING_MUTEX) \ |
| && !defined (_RWSTD_NO_STRING_MUTEX) \ |
| && !defined (_RWSTD_NO_STATIC_MUTEX_INIT) |
| |
| void _C_init (size_type __cap, size_type __size) { |
| |
| _C_cap = __cap; |
| _C_size._C_size = __size; |
| |
| # ifndef _RWSTD_NO_STRING_REF_COUNT |
| |
| _C_refs = 1 - _RWSTD_STRING_REF_OFFSET; |
| |
| if (0 != _RWSTD_MUTEX_INIT (this->_C_mutex._C_mutex)) |
| _RW::__rw_throw (_RWSTD_ERROR_RUNTIME_ERROR, |
| "synchronization error"); |
| |
| # endif // _RWSTD_NO_STRING_REF_COUNT |
| |
| } |
| |
| void _C_destroy () { |
| # ifndef _RWSTD_NO_STRING_REF_COUNT |
| _RWSTD_MUTEX_DESTROY (this->_C_mutex._C_mutex); |
| # endif |
| } |
| |
| #else |
| |
| void _C_init (size_type __cap, size_type __size) { |
| |
| # ifndef _RWSTD_NO_STRING_REF_COUNT |
| _C_refs = 1 - _RWSTD_STRING_REF_OFFSET; |
| # endif // _RWSTD_NO_STRING_REF_COUNT |
| |
| _C_cap = __cap; |
| _C_size._C_size = __size; |
| } |
| |
| void _C_destroy () { } |
| |
| #endif // _RWSTD_REENTRANT && !_RWSTD_ONE_STRING_MUTEX && |
| // !_RWSTD_NO_STRING_MUTEX && !_RWSTD_NO_STATIC_MUTEX_INIT |
| |
| |
| int _C_get_ref () const { |
| |
| # ifndef _RWSTD_NO_STRING_REF_COUNT |
| |
| return _C_refs + _RWSTD_STRING_REF_OFFSET; |
| |
| #else // if defined (_RWSTD_NO_STRING_REF_COUNT) |
| |
| return 0; |
| |
| #endif // _RWSTD_NO_STRING_REF_COUNT |
| |
| } |
| |
| void _C_unref () { |
| |
| #ifndef _RWSTD_NO_STRING_REF_COUNT |
| |
| // not thread-safe (see caller) |
| if (this != string_type::_C_nullref ()) |
| _C_refs = -_RWSTD_STRING_REF_OFFSET; |
| |
| #endif // _RWSTD_NO_STRING_REF_COUNT |
| } |
| |
| int _C_inc_ref () { |
| |
| #ifndef _RWSTD_NO_STRING_REF_COUNT |
| |
| return this == string_type::_C_nullref () ? 1 : |
| _RWSTD_STRING_ATOMIC_PREINCREMENT (_C_refs, |
| _RWSTD_STRING_MUTEX (this)); |
| #else // if defined (_RWSTD_NO_STRING_REF_COUNT) |
| return 0 + (this != string_type::_C_nullref ()); |
| #endif // _RWSTD_NO_STRING_REF_COUNT |
| |
| } |
| |
| int _C_dec_ref () { |
| |
| #ifndef _RWSTD_NO_STRING_REF_COUNT |
| |
| return this == string_type::_C_nullref () ? 1 : |
| _RWSTD_STRING_REF_OFFSET |
| + _RWSTD_STRING_ATOMIC_PREDECREMENT (_C_refs, |
| _RWSTD_STRING_MUTEX (this)); |
| |
| #else // if defined (_RWSTD_NO_STRING_REF_COUNT) |
| return 0 + (this == string_type::_C_nullref ()); |
| #endif // _RWSTD_NO_STRING_REF_COUNT |
| |
| } |
| |
| size_type size () const { |
| return _C_size._C_size; |
| } |
| |
| size_type capacity () const { |
| return _C_cap; |
| } |
| |
| char_type* data () { |
| return _RWSTD_REINTERPRET_CAST (char_type*, this + 1); |
| } |
| |
| const char_type* data () const { |
| return _RWSTD_REINTERPRET_CAST (const char_type*, this + 1); |
| } |
| |
| #ifndef _RWSTD_NO_STRING_REF_COUNT |
| |
| # if defined (_RWSTD_REENTRANT) \ |
| && !defined (_RWSTD_ONE_STRING_MUTEX) \ |
| && !defined (_RWSTD_NO_STRING_MUTEX) |
| |
| __rw_mutex_base _C_mutex; |
| |
| # endif // _REENTRANT && !_ONE_STRING_MUTEX && !_NO_STRING_MUTEX |
| |
| // reference count: |
| // 1 less than the number of references to the string body |
| // _RWSTD_STRING_REF_OFFSET less if _RWSTD_NO_STRING_MUTEX is defined |
| // -1 if reference counting is disabled |
| int _C_refs; |
| |
| #endif // _RWSTD_NO_STRING_REF_COUNT |
| |
| size_type _C_cap; // Size of allocated memory |
| |
| union { |
| size_type _C_size; // Number of actual data values stored |
| _CharT _C_dummy; // force the alignment of the first char |
| } _C_size; // named to work around an HP aCC 3.30 bug |
| }; |
| |
| |
| // representation of the null string; will be a POD wherever possible |
| // (will not be POD if the reference contains a mutex with a UD-ctor) |
| template <class _CharT, class _Traits , class _Allocator> |
| struct __null_ref |
| : __string_ref<_CharT, _Traits , _Allocator> |
| { |
| // string reference immediately followed by a single terminating null |
| _CharT _C_eos; |
| }; |
| |
| |
| #ifdef _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS |
| |
| extern _RWSTD_EXPORT unsigned long __nullref []; |
| |
| #endif // _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS |
| |
| } // namespace __rw |
| |
| |
| #endif // _RWSTD_RW_STRREF_H_INCLUDED |