274 lines
7.7 KiB
C++
274 lines
7.7 KiB
C++
/***************************************************************************
|
|
*
|
|
* _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: _strref.h 585996 2007-10-18 14:59:39Z sebor $
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you 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.
|
|
*
|
|
* Copyright 1994-2007 Rogue Wave Software, Inc.
|
|
*
|
|
**************************************************************************/
|
|
|
|
#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
|
|
|
|
#if !defined (_RWSTD_NO_ATOMIC_OPS) && !defined (_RWSTD_NO_STRING_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_NO_STRING_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
|