You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1008 lines
32 KiB
1008 lines
32 KiB
/* /////////////////////////////////////////////////////////////////////////
|
|
* File: stlsoft/string/special_string_instance.hpp
|
|
*
|
|
* Purpose: Special string instance class template.
|
|
*
|
|
* Created: 3rd June 2006
|
|
* Updated: 19th May 2012
|
|
*
|
|
* Thanks to: Pablo Aguilar for spotting my omission of string access shims
|
|
* for special_string_instance_1.
|
|
*
|
|
* Home: http://stlsoft.org/
|
|
*
|
|
* Copyright (c) 2006-2012, Matthew Wilson and Synesis Software
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* - Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* - Neither the name(s) of Matthew Wilson and Synesis Software nor the
|
|
* names of any contributors may be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
|
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
|
|
/** \file stlsoft/string/special_string_instance.hpp
|
|
*
|
|
* \brief [C++ only] Definition of the stlsoft::special_string_instance
|
|
* class template
|
|
* (\ref group__library__string "String" Library).
|
|
*/
|
|
|
|
#ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE
|
|
#define STLSOFT_INCL_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE
|
|
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
# define STLSOFT_VER_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE_MAJOR 1
|
|
# define STLSOFT_VER_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE_MINOR 3
|
|
# define STLSOFT_VER_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE_REVISION 2
|
|
# define STLSOFT_VER_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE_EDIT 23
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Compatibility
|
|
*/
|
|
|
|
/*
|
|
[Incompatibilies-start]
|
|
STLSOFT_COMPILER_IS_MSVC: _MSC_VER<1200
|
|
[Incompatibilies-end]
|
|
*/
|
|
|
|
/* Compatibility
|
|
[<[STLSOFT-AUTO:NO-DOCFILELABEL]>]
|
|
[<[STLSOFT-AUTO:NO-UNITTEST]>]
|
|
*/
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Includes
|
|
*/
|
|
|
|
#ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
|
|
# include <stlsoft/stlsoft.h>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
|
|
#ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
|
|
# include <stlsoft/memory/auto_buffer.hpp>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
|
|
#ifndef STLSOFT_INCL_STLSOFT_META_HPP_IS_SAME_TYPE
|
|
# include <stlsoft/meta/is_same_type.hpp>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_META_HPP_IS_SAME_TYPE */
|
|
#ifndef STLSOFT_INCL_STLSOFT_META_HPP_SELECT_FIRST_TYPE_IF
|
|
# include <stlsoft/meta/select_first_type_if.hpp>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_META_HPP_SELECT_FIRST_TYPE_IF */
|
|
#ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_LOCK_SCOPE
|
|
# include <stlsoft/synch/lock_scope.hpp>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_SYNCH_HPP_LOCK_SCOPE */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Namespace
|
|
*/
|
|
|
|
#ifndef _STLSOFT_NO_NAMESPACE
|
|
namespace stlsoft
|
|
{
|
|
#endif /* _STLSOFT_NO_NAMESPACE */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Classes
|
|
*/
|
|
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
|
|
template< ss_typename_param_k C
|
|
, ss_size_t N
|
|
, ss_typename_param_k A
|
|
, ss_typename_param_k A0
|
|
>
|
|
struct ssi_buffer
|
|
{
|
|
/// \name Member Types
|
|
/// @{
|
|
public:
|
|
/// The character type
|
|
typedef C char_type;
|
|
/// The allocator type
|
|
typedef A allocator_type;
|
|
/// The size type
|
|
typedef ss_size_t size_type;
|
|
/// The argument type
|
|
typedef A0 argument_0_type;
|
|
/// The class type
|
|
typedef ssi_buffer<C, N, A, A0> class_type;
|
|
private:
|
|
/// The buffer type
|
|
typedef stlsoft::auto_buffer<
|
|
char_type
|
|
#if defined(STLSOFT_COMPILER_IS_BORLAND)
|
|
, 128
|
|
#else /* ? compiler */
|
|
, N
|
|
#endif /* compiler */
|
|
, allocator_type
|
|
> buffer_type_;
|
|
/// @}
|
|
|
|
/// \name Construction
|
|
/// @{
|
|
public:
|
|
ssi_buffer()
|
|
: m_len(0)
|
|
, m_buffer(0)
|
|
{}
|
|
#ifdef STLSOFT_COMPILER_IS_GCC
|
|
ssi_buffer(class_type const& rhs)
|
|
: m_len(rhs.m_len)
|
|
, m_buffer(rhs.m_len + 1)
|
|
{
|
|
::memcpy(&m_buffer[0], &rhs.m_buffer[0], sizeof(char_type) * (1u + m_len));
|
|
}
|
|
#endif /* compiler */
|
|
|
|
void init(size_type (*pfn)(char_type*, size_type))
|
|
{
|
|
// We don't pass NULL here, just in case
|
|
char_type empty = '\0';
|
|
size_type cch = pfn(&empty, 0);
|
|
|
|
if(m_buffer.resize(1 + cch))
|
|
{
|
|
for(;;)
|
|
{
|
|
cch = pfn(&m_buffer[0], m_buffer.size());
|
|
|
|
if(cch < m_buffer.size())
|
|
{
|
|
m_len = cch;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if(!m_buffer.resize(2 * m_buffer.size()))
|
|
{
|
|
m_buffer.resize(0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_buffer[m_len] = '\0';
|
|
}
|
|
|
|
void init(argument_0_type arg0, size_type (*pfn)(argument_0_type, char_type*, size_type))
|
|
{
|
|
size_type cch = pfn(arg0, NULL, 0); // We don't pass NULL here, just in case
|
|
|
|
if(m_buffer.resize(1 + cch))
|
|
{
|
|
for(;;)
|
|
{
|
|
cch = pfn(arg0, &m_buffer[0], m_buffer.size());
|
|
|
|
if(cch < m_buffer.size())
|
|
{
|
|
m_len = cch;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if(!m_buffer.resize(2 * m_buffer.size()))
|
|
{
|
|
m_buffer.resize(0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_buffer[m_len] = '\0';
|
|
}
|
|
/// @}
|
|
|
|
/// \name Accessors
|
|
/// @{
|
|
public:
|
|
char_type const* data() const
|
|
{
|
|
return m_buffer.data();
|
|
}
|
|
size_type length() const
|
|
{
|
|
return m_len;
|
|
}
|
|
/// @}
|
|
|
|
/// \name Members
|
|
/// @{
|
|
private:
|
|
size_type m_len;
|
|
buffer_type_ m_buffer;
|
|
/// @}
|
|
};
|
|
|
|
template< ss_typename_param_k C
|
|
, ss_size_t N
|
|
, ss_typename_param_k A
|
|
, ss_typename_param_k A0
|
|
>
|
|
struct ssi_buffer_non_static
|
|
: public ssi_buffer<C, N, A, A0>
|
|
{
|
|
/// \name Member Types
|
|
/// @{
|
|
public:
|
|
typedef ssi_buffer<C, N, A, A0> ssi_buffer_type;
|
|
typedef ssi_buffer<C, N, A, A0> parent_class_type;
|
|
typedef ssi_buffer_non_static<C, N, A, A0> class_type;
|
|
|
|
typedef ss_typename_type_k ssi_buffer_type::char_type char_type;
|
|
typedef ss_typename_type_k ssi_buffer_type::size_type size_type;
|
|
/// @}
|
|
|
|
/// \name Construction
|
|
/// @{
|
|
public:
|
|
ssi_buffer_non_static(size_type (*pfn)(char_type*, size_type))
|
|
{
|
|
parent_class_type::init(pfn);
|
|
}
|
|
ssi_buffer_non_static(A0 a0, size_type (*pfn)(A0, char_type*, size_type))
|
|
{
|
|
parent_class_type::init(a0, pfn);
|
|
}
|
|
#ifdef STLSOFT_COMPILER_IS_GCC
|
|
ssi_buffer_non_static(class_type const& rhs)
|
|
: parent_class_type(rhs)
|
|
{}
|
|
#endif /* compiler */
|
|
/// @}
|
|
|
|
/// \name Accessors
|
|
/// @{
|
|
public:
|
|
char_type const* data() const
|
|
{
|
|
return parent_class_type::data();
|
|
}
|
|
size_type length() const
|
|
{
|
|
return parent_class_type::length();
|
|
}
|
|
/// @}
|
|
|
|
/// \name Not to be implemented
|
|
/// @{
|
|
private:
|
|
#ifndef STLSOFT_COMPILER_IS_GCC
|
|
ssi_buffer_non_static(class_type const&);
|
|
#endif /* compiler */
|
|
class_type& operator =(class_type const&);
|
|
/// @}
|
|
};
|
|
|
|
template< ss_typename_param_k C
|
|
, ss_size_t N
|
|
, ss_typename_param_k A
|
|
, ss_typename_param_k A0
|
|
, ss_typename_param_k P // Passes policy type, from which spin_mutex_type is elicited, so non-statics do not need to specify it
|
|
>
|
|
struct ssi_buffer_static
|
|
{
|
|
/// \name Member Types
|
|
/// @{
|
|
public:
|
|
typedef ssi_buffer<C, N, A, A0> ssi_buffer_type;
|
|
typedef ssi_buffer_static<C, N, A, A0, P> class_type;
|
|
|
|
typedef ss_typename_type_k ssi_buffer_type::char_type char_type;
|
|
typedef ss_typename_type_k ssi_buffer_type::size_type size_type;
|
|
private:
|
|
typedef P policy_type;
|
|
typedef ss_typename_type_k policy_type::spin_mutex_type spin_mutex_type;
|
|
typedef ss_typename_type_k policy_type::atomic_int_type atomic_int_type;
|
|
/// @}
|
|
|
|
/// \name Construction
|
|
/// @{
|
|
public:
|
|
ssi_buffer_static(size_type (*pfn)(char_type*, size_type))
|
|
: m_buffer(get_buffer(pfn))
|
|
{}
|
|
ssi_buffer_static(A0 a0, size_type (*pfn)(A0, char_type*, size_type))
|
|
: m_buffer(a0, get_buffer(a0, pfn))
|
|
{}
|
|
#ifdef STLSOFT_COMPILER_IS_GCC
|
|
ssi_buffer_static(class_type const& rhs)
|
|
: m_buffer(rhs.m_buffer)
|
|
{}
|
|
#endif /* compiler */
|
|
/// @}
|
|
|
|
/// \name Accessors
|
|
/// @{
|
|
public:
|
|
char_type const* data() const
|
|
{
|
|
return m_buffer.data();
|
|
}
|
|
size_type length() const
|
|
{
|
|
return m_buffer.length();
|
|
}
|
|
/// @}
|
|
|
|
/// \name Implementation
|
|
/// @{
|
|
private:
|
|
static ssi_buffer_type& get_buffer(size_type (*pfn)(char_type*, size_type))
|
|
{
|
|
static atomic_int_type s_count = 0;
|
|
static bool s_bInit = false;
|
|
spin_mutex_type mx(&s_count);
|
|
stlsoft::lock_scope<spin_mutex_type> lock(mx);
|
|
|
|
static ssi_buffer_type s_buffer;
|
|
|
|
if(!s_bInit)
|
|
{
|
|
s_buffer.init(pfn);
|
|
|
|
s_bInit = true;
|
|
}
|
|
|
|
return s_buffer;
|
|
}
|
|
static ssi_buffer_type& get_buffer(A0 a0, size_type (*pfn)(A0, char_type*, size_type))
|
|
{
|
|
static atomic_int_type s_count = 0;
|
|
static bool s_bInit = false;
|
|
spin_mutex_type mx(&s_count);
|
|
stlsoft::lock_scope<spin_mutex_type> lock(mx);
|
|
|
|
static ssi_buffer_type s_buffer;
|
|
|
|
if(!s_bInit)
|
|
{
|
|
s_buffer.init(a0, pfn);
|
|
|
|
s_bInit = true;
|
|
}
|
|
|
|
return s_buffer;
|
|
}
|
|
/// @}
|
|
|
|
/// \name Members
|
|
/// @{
|
|
private:
|
|
ssi_buffer_type& m_buffer;
|
|
/// @}
|
|
|
|
/// \name Not to be implemented
|
|
/// @{
|
|
private:
|
|
#ifndef STLSOFT_COMPILER_IS_GCC
|
|
ssi_buffer_static(class_type const&);
|
|
#endif /* compiler */
|
|
class_type& operator =(class_type const&);
|
|
/// @}
|
|
};
|
|
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
|
|
/** \brief Special string instance class template.
|
|
*
|
|
* \ingroup group__library__string
|
|
*
|
|
* \param P The SSI policy type.
|
|
*
|
|
* The policy type provides the following:
|
|
*
|
|
* - A member constant <code>internalBufferSize</code> that determines the
|
|
* size of the SSI's internal
|
|
* \link stlsoft::auto_buffer auto_buffer\endlink's internal buffer size.
|
|
* - A static method <code>get_value(char_type* buffer, size_type cchBuffer)</code>
|
|
* that has the
|
|
* - A member constant <code>allowImplicitConversion</code> that determines
|
|
* whether an implicit conversion operator (to
|
|
* <code>char_type const*</code>) is to be provided.
|
|
*/
|
|
template <ss_typename_param_k P>
|
|
class special_string_instance_0
|
|
{
|
|
/// \name Member Types
|
|
/// @{
|
|
public:
|
|
/// \brief The policy type
|
|
typedef P policy_type;
|
|
/// \brief The current instantiation of the template.
|
|
typedef special_string_instance_0<P> class_type;
|
|
/// \brief The character type
|
|
typedef ss_typename_type_k policy_type::char_type char_type;
|
|
/// \brief The size type
|
|
typedef ss_typename_type_k policy_type::size_type size_type;
|
|
|
|
/// \brief The character type for ANSI specialisations
|
|
///
|
|
/// \note This is used in the specification of the string access shim
|
|
/// functions.
|
|
private:
|
|
enum { charTypeIsAnsi = is_same_type<ss_char_a_t, char_type>::value };
|
|
public:
|
|
typedef ss_typename_type_k select_first_type_if<
|
|
ss_char_a_t const*
|
|
, void
|
|
, charTypeIsAnsi
|
|
>::type cstring_a_type;
|
|
/// \brief The character type for Unicode specialisations
|
|
///
|
|
/// \note This is used in the specification of the string access shim
|
|
/// functions.
|
|
private:
|
|
enum { charTypeIsWide = is_same_type<ss_char_w_t, char_type>::value };
|
|
public:
|
|
typedef ss_typename_type_k select_first_type_if<
|
|
ss_char_w_t const*
|
|
, void
|
|
, charTypeIsWide
|
|
>::type cstring_w_type;
|
|
private:
|
|
typedef ss_typename_type_k policy_type::pfn_type pfn_type;
|
|
private:
|
|
// This section allows for the case where the policy does not define an
|
|
// allocator, which it indicates by defining its member type
|
|
// allocator_type to be void.
|
|
typedef ss_typename_type_k policy_type::allocator_type putative_allocator_type;
|
|
enum
|
|
{
|
|
policy_has_allocator_type = (0 != size_of<putative_allocator_type>::value)
|
|
};
|
|
typedef ss_typename_type_k allocator_selector<char_type>::allocator_type backup_allocator_type;
|
|
public:
|
|
/// \brief The allocator type
|
|
typedef ss_typename_type_k select_first_type_if<
|
|
putative_allocator_type
|
|
, backup_allocator_type
|
|
, policy_has_allocator_type
|
|
>::type allocator_type;
|
|
private:
|
|
enum { allowImplicitConversion = policy_type::allowImplicitConversion };
|
|
public:
|
|
/// \brief The implicit conversion operator type
|
|
typedef ss_typename_type_k select_first_type_if<
|
|
char_type const*
|
|
, void
|
|
, allowImplicitConversion
|
|
>::type implicit_conversion_type;
|
|
private:
|
|
// This section accounts for whether the policy indicates shared state.
|
|
// If so, then the buffer type resolves to the appropriate
|
|
// specialisation of ssi_buffer_static, which stores a threadsafe buffer
|
|
// shared by all instances. If not, then the buffer type resolves to
|
|
// ssi_buffer_non_static, which stores a buffer per instance.
|
|
enum
|
|
{
|
|
policy_indicates_shared_state = (0 != policy_type::sharedState)
|
|
};
|
|
|
|
struct null_argument
|
|
{};
|
|
|
|
enum { internalBufferSize = policy_type::internalBufferSize };
|
|
typedef ssi_buffer_static<
|
|
char_type
|
|
, internalBufferSize
|
|
, allocator_type
|
|
, null_argument
|
|
, policy_type // Passes policy type, from which spin_mutex_type is elicited, so non-statics do not need to specify it
|
|
> ssi_buffer_static_type;
|
|
typedef ssi_buffer_non_static<
|
|
char_type
|
|
, internalBufferSize
|
|
, allocator_type
|
|
, null_argument
|
|
> ssi_buffer_non_static_type;
|
|
|
|
typedef ss_typename_type_k select_first_type_if<
|
|
ssi_buffer_static_type
|
|
, ssi_buffer_non_static_type
|
|
, policy_indicates_shared_state
|
|
>::type buffer_type_;
|
|
/// @}
|
|
|
|
/// \name Construction
|
|
/// @{
|
|
public:
|
|
special_string_instance_0()
|
|
: m_buffer(policy_type::get_fn())
|
|
{}
|
|
/// @}
|
|
|
|
/// \name Accessors
|
|
/// @{
|
|
public:
|
|
size_type length() const
|
|
{
|
|
return m_buffer.length();
|
|
}
|
|
size_type size() const
|
|
{
|
|
return length();
|
|
}
|
|
|
|
char_type const* data() const
|
|
{
|
|
return m_buffer.data();
|
|
}
|
|
char_type const* c_str() const
|
|
{
|
|
return data();
|
|
}
|
|
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
cstring_a_type c_str_a() const
|
|
{
|
|
return c_str();
|
|
}
|
|
cstring_w_type c_str_w() const
|
|
{
|
|
return c_str();
|
|
}
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
/// @}
|
|
|
|
/// \name Operators
|
|
/// @{
|
|
public:
|
|
#if !defined(STLSOFT_COMPILER_IS_BORLAND)
|
|
operator implicit_conversion_type () const
|
|
{
|
|
return this->c_str();
|
|
}
|
|
#endif /* compiler */
|
|
/// @}
|
|
|
|
/// \name Operations
|
|
/// @{
|
|
public:
|
|
static size_type get(char_type* buffer, size_type cchBuffer)
|
|
{
|
|
return (policy_type::get_fn())(buffer, cchBuffer);
|
|
}
|
|
/// @}
|
|
|
|
/// \name Members
|
|
/// @{
|
|
private:
|
|
buffer_type_ m_buffer;
|
|
/// @}
|
|
};
|
|
|
|
/** \brief Special string instance class template.
|
|
*
|
|
* \ingroup group__library__string
|
|
*
|
|
* \param P The SSI policy type.
|
|
*
|
|
* The policy type provides the following:
|
|
*
|
|
* - A member constant <code>internalBufferSize</code> that determines the
|
|
* size of the SSI's internal
|
|
* \link stlsoft::auto_buffer auto_buffer\endlink's internal buffer size.
|
|
* - A static method <code>get_value(char_type* buffer, size_type cchBuffer)</code>
|
|
* that has the
|
|
* - A member constant <code>allowImplicitConversion</code> that determines
|
|
* whether an implicit conversion operator (to
|
|
* <code>char_type const*</code>) is to be provided.
|
|
*/
|
|
template <ss_typename_param_k P>
|
|
class special_string_instance_1
|
|
{
|
|
/// \name Member Types
|
|
/// @{
|
|
public:
|
|
/// \brief The policy type.
|
|
typedef P policy_type;
|
|
/// \brief The current instantiation of the template.
|
|
typedef special_string_instance_1<P> class_type;
|
|
/// \brief The character type
|
|
typedef ss_typename_type_k policy_type::char_type char_type;
|
|
/// \brief The size type
|
|
typedef ss_typename_type_k policy_type::size_type size_type;
|
|
/// \brief The argument type
|
|
typedef ss_typename_type_k policy_type::argument_0_type argument_0_type;
|
|
|
|
/// \brief The character type for ANSI specialisations
|
|
///
|
|
/// \note This is used in the specification of the string access shim
|
|
/// functions.
|
|
private:
|
|
enum { charTypeIsAnsi = is_same_type<ss_char_a_t, char_type>::value };
|
|
public:
|
|
typedef ss_typename_type_k select_first_type_if<
|
|
ss_char_a_t const*
|
|
, void
|
|
, charTypeIsAnsi
|
|
>::type cstring_a_type;
|
|
/// \brief The character type for Unicode specialisations
|
|
///
|
|
/// \note This is used in the specification of the string access shim
|
|
/// functions.
|
|
private:
|
|
enum { charTypeIsWide = is_same_type<ss_char_w_t, char_type>::value };
|
|
public:
|
|
typedef ss_typename_type_k select_first_type_if<
|
|
ss_char_w_t const*
|
|
, void
|
|
, charTypeIsWide
|
|
>::type cstring_w_type;
|
|
private:
|
|
typedef ss_typename_type_k policy_type::pfn_type pfn_type;
|
|
private:
|
|
// This section allows for the case where the policy does not define an
|
|
// allocator, which it indicates by defining its member type
|
|
// allocator_type to be void.
|
|
typedef ss_typename_type_k policy_type::allocator_type putative_allocator_type;
|
|
enum
|
|
{
|
|
policy_has_allocator_type = (0 != size_of<putative_allocator_type>::value)
|
|
};
|
|
typedef ss_typename_type_k allocator_selector<char_type>::allocator_type backup_allocator_type;
|
|
public:
|
|
/// \brief The allocator type
|
|
typedef ss_typename_type_k select_first_type_if<
|
|
putative_allocator_type
|
|
, backup_allocator_type
|
|
, policy_has_allocator_type
|
|
>::type allocator_type;
|
|
|
|
/// \brief The implicit conversion operator type
|
|
private:
|
|
enum { allowImplicitConversion = policy_type::allowImplicitConversion };
|
|
public:
|
|
typedef ss_typename_type_k select_first_type_if<
|
|
char_type const*
|
|
, void
|
|
, allowImplicitConversion
|
|
>::type implicit_conversion_type;
|
|
private:
|
|
// This section accounts for whether the policy indicates shared state.
|
|
// If so, then the buffer type resolves to the appropriate
|
|
// specialisation of ssi_buffer_static, which stores a threadsafe buffer
|
|
// shared by all instances. If not, then the buffer type resolves to
|
|
// ssi_buffer_non_static, which stores a buffer per instance.
|
|
enum
|
|
{
|
|
policy_indicates_shared_state = (0 != policy_type::sharedState)
|
|
};
|
|
|
|
enum { internalBufferSize = policy_type::internalBufferSize };
|
|
typedef ssi_buffer_static<
|
|
char_type
|
|
, internalBufferSize
|
|
, allocator_type
|
|
, argument_0_type
|
|
, policy_type // Passes policy type, from which spin_mutex_type is elicited, so non-statics do not need to specify it
|
|
> ssi_buffer_static_type;
|
|
typedef ssi_buffer_non_static<
|
|
char_type
|
|
, internalBufferSize
|
|
, allocator_type
|
|
, argument_0_type
|
|
> ssi_buffer_non_static_type;
|
|
|
|
typedef ss_typename_type_k select_first_type_if<
|
|
ssi_buffer_static_type
|
|
, ssi_buffer_non_static_type
|
|
, policy_indicates_shared_state
|
|
>::type buffer_type_;
|
|
|
|
/// @}
|
|
|
|
/// \name Construction
|
|
/// @{
|
|
public:
|
|
special_string_instance_1(argument_0_type argument)
|
|
: m_buffer(argument, policy_type::get_fn())
|
|
{}
|
|
/// @}
|
|
|
|
/// \name Operations
|
|
/// @{
|
|
public:
|
|
static size_type get(argument_0_type argument, char_type* buffer, size_type cchBuffer)
|
|
{
|
|
return (policy_type::get_fn())(argument, buffer, cchBuffer);
|
|
}
|
|
/// @}
|
|
|
|
/// \name Attributes
|
|
/// @{
|
|
public:
|
|
char_type const* c_str() const
|
|
{
|
|
return m_buffer.data();
|
|
}
|
|
char_type const* data() const
|
|
{
|
|
return m_buffer.data();
|
|
}
|
|
size_type length() const
|
|
{
|
|
return m_buffer.length();
|
|
}
|
|
size_type size() const
|
|
{
|
|
return length();
|
|
}
|
|
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
cstring_a_type c_str_a() const
|
|
{
|
|
return c_str();
|
|
}
|
|
cstring_w_type c_str_w() const
|
|
{
|
|
return c_str();
|
|
}
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
/// @}
|
|
|
|
/// \name Operators
|
|
/// @{
|
|
public:
|
|
#if !defined(STLSOFT_COMPILER_IS_BORLAND)
|
|
operator implicit_conversion_type () const
|
|
{
|
|
return this->c_str();
|
|
}
|
|
#endif /* compiler */
|
|
/// @}
|
|
|
|
/// \name Member Types
|
|
/// @{
|
|
private:
|
|
buffer_type_ m_buffer;
|
|
/// @}
|
|
};
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Shims
|
|
*/
|
|
|
|
/** \brief \ref group__concept__shim__string_access__c_str_ptr_null for stlsoft::special_string_instance_0
|
|
*
|
|
* \ingroup group__concept__shim__string_access
|
|
*/
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_0<P>::char_type const* c_str_ptr_null(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
return (0 != ssi.length()) ? ssi.c_str() : NULL;
|
|
}
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_a_type c_str_ptr_null_a(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
return (0 != ssi.length()) ? ssi.c_str_a() : NULL;
|
|
}
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_w_type c_str_ptr_null_w(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
return (0 != ssi.length()) ? ssi.c_str_w() : NULL;
|
|
}
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/** \brief \ref group__concept__shim__string_access__c_str_ptr for stlsoft::special_string_instance_0
|
|
*
|
|
* \ingroup group__concept__shim__string_access
|
|
*/
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_0<P>::char_type const* c_str_ptr(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
return ssi.c_str();
|
|
}
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_a_type c_str_ptr_a(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
return ssi.c_str_a();
|
|
}
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_w_type c_str_ptr_w(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
return ssi.c_str_w();
|
|
}
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/** \brief \ref group__concept__shim__string_access__c_str_data for stlsoft::special_string_instance_0
|
|
*
|
|
* \ingroup group__concept__shim__string_access
|
|
*/
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_0<P>::char_type const* c_str_data(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
return ssi.c_str();
|
|
}
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_a_type c_str_data_a(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
return ssi.c_str_a();
|
|
}
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_w_type c_str_data_w(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
return ssi.c_str_w();
|
|
}
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/** \brief \ref group__concept__shim__string_access__c_str_len for stlsoft::special_string_instance_0
|
|
*
|
|
* \ingroup group__concept__shim__string_access
|
|
*/
|
|
template <ss_typename_param_k P>
|
|
inline ss_size_t c_str_len(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
return ssi.length();
|
|
}
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
template <ss_typename_param_k P>
|
|
inline ss_size_t c_str_len_a(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
// If this fires, you're trying to invoke c_str_len_w() on an SSI
|
|
// whose policy defines the character type to be something other
|
|
// than char.
|
|
ss_char_a_t const* const special_string_instance_must_use_narrow_character = ssi.c_str_a();
|
|
|
|
STLSOFT_SUPPRESS_UNUSED(special_string_instance_must_use_narrow_character);
|
|
|
|
return ssi.length();
|
|
}
|
|
template <ss_typename_param_k P>
|
|
inline ss_size_t c_str_len_w(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
|
|
{
|
|
// If this fires, you're trying to invoke c_str_len_w() on an SSI
|
|
// whose policy defines the character type to be something other
|
|
// than wchar_t.
|
|
ss_char_w_t const* const special_string_instance_must_use_wide_character = ssi.c_str_w();
|
|
|
|
STLSOFT_SUPPRESS_UNUSED(special_string_instance_must_use_wide_character);
|
|
|
|
return ssi.length();
|
|
}
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/** \brief \ref group__concept__shim__string_access__c_str_ptr_null for stlsoft::special_string_instance_1
|
|
*
|
|
* \ingroup group__concept__shim__string_access
|
|
*/
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_1<P>::char_type const* c_str_ptr_null(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
return (0 != ssi.length()) ? ssi.c_str() : NULL;
|
|
}
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_a_type c_str_ptr_null_a(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
return (0 != ssi.length()) ? ssi.c_str_a() : NULL;
|
|
}
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_w_type c_str_ptr_null_w(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
return (0 != ssi.length()) ? ssi.c_str_w() : NULL;
|
|
}
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/** \brief \ref group__concept__shim__string_access__c_str_ptr for stlsoft::special_string_instance_1
|
|
*
|
|
* \ingroup group__concept__shim__string_access
|
|
*/
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_1<P>::char_type const* c_str_ptr(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
return ssi.c_str();
|
|
}
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_a_type c_str_ptr_a(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
return ssi.c_str_a();
|
|
}
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_w_type c_str_ptr_w(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
return ssi.c_str_w();
|
|
}
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/** \brief \ref group__concept__shim__string_access__c_str_data for stlsoft::special_string_instance_1
|
|
*
|
|
* \ingroup group__concept__shim__string_access
|
|
*/
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_1<P>::char_type const* c_str_data(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
return ssi.c_str();
|
|
}
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_a_type c_str_data_a(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
return ssi.c_str_a();
|
|
}
|
|
template <ss_typename_param_k P>
|
|
inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_w_type c_str_data_w(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
return ssi.c_str_w();
|
|
}
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/** \brief \ref group__concept__shim__string_access__c_str_len for stlsoft::special_string_instance_1
|
|
*
|
|
* \ingroup group__concept__shim__string_access
|
|
*/
|
|
template <ss_typename_param_k P>
|
|
inline ss_size_t c_str_len(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
return ssi.length();
|
|
}
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
template <ss_typename_param_k P>
|
|
inline ss_size_t c_str_len_a(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
// If this fires, you're trying to invoke c_str_len_w() on an SSI
|
|
// whose policy defines the character type to be something other
|
|
// than char.
|
|
ss_char_a_t const* const special_string_instance_must_use_narrow_character = ssi.c_str_a();
|
|
|
|
STLSOFT_SUPPRESS_UNUSED(special_string_instance_must_use_narrow_character);
|
|
|
|
return ssi.length();
|
|
}
|
|
template <ss_typename_param_k P>
|
|
inline ss_size_t c_str_len_w(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
|
|
{
|
|
// If this fires, you're trying to invoke c_str_len_w() on an SSI
|
|
// whose policy defines the character type to be something other
|
|
// than wchar_t.
|
|
ss_char_w_t const* const special_string_instance_must_use_wide_character = ssi.c_str_w();
|
|
|
|
STLSOFT_SUPPRESS_UNUSED(special_string_instance_must_use_wide_character);
|
|
|
|
return ssi.length();
|
|
}
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
#ifndef _STLSOFT_NO_NAMESPACE
|
|
} // namespace stlsoft
|
|
#endif /* _STLSOFT_NO_NAMESPACE */
|
|
|
|
/* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
#endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE */
|
|
|
|
/* ///////////////////////////// end of file //////////////////////////// */
|