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

/* /////////////////////////////////////////////////////////////////////////
* 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 //////////////////////////// */