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.
640 lines
19 KiB
640 lines
19 KiB
/* /////////////////////////////////////////////////////////////////////////
|
|
* File: winstl/conversion/int_to_string.hpp
|
|
*
|
|
* Purpose: WinSTL integer to string conversions.
|
|
*
|
|
* Created: 31st July 2002
|
|
* Updated: 10th August 2009
|
|
*
|
|
* Home: http://stlsoft.org/
|
|
*
|
|
* Copyright (c) 2002-2009, 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 winstl/conversion/int_to_string.hpp
|
|
*
|
|
* \brief [C++ only] Very efficient integer to string conversion functions
|
|
* for the Windows platform
|
|
* (\ref group__library__conversion "Conversion" Library).
|
|
*/
|
|
|
|
#ifndef WINSTL_INCL_WINSTL_CONVERSION_HPP_INT_TO_STRING
|
|
#define WINSTL_INCL_WINSTL_CONVERSION_HPP_INT_TO_STRING
|
|
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
# define _WINSTL_VER_WINSTL_CONVERSION_HPP_INT_TO_STRING_MAJOR 2
|
|
# define _WINSTL_VER_WINSTL_CONVERSION_HPP_INT_TO_STRING_MINOR 1
|
|
# define _WINSTL_VER_WINSTL_CONVERSION_HPP_INT_TO_STRING_REVISION 4
|
|
# define _WINSTL_VER_WINSTL_CONVERSION_HPP_INT_TO_STRING_EDIT 41
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Compatibility
|
|
*/
|
|
|
|
/*
|
|
[Incompatibilies-start]
|
|
STLSOFT_COMPILER_IS_BORLAND: __BORLANDC__<0x0560
|
|
[Incompatibilies-end]
|
|
*/
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Includes
|
|
*/
|
|
|
|
#ifndef WINSTL_INCL_WINSTL_H_WINSTL
|
|
# include <winstl/winstl.h>
|
|
#endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
|
|
#ifndef STLSOFT_INCL_STLSOFT_CONVERSION_HPP_INT_TO_STRING
|
|
# include <stlsoft/conversion/integer_to_string.hpp>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_CONVERSION_HPP_INT_TO_STRING */
|
|
#ifndef WINSTL_INCL_WINSTL_SYNCH_HPP_THREAD_MUTEX
|
|
# include <winstl/synch/thread_mutex.hpp>
|
|
#endif /* !WINSTL_INCL_WINSTL_SYNCH_HPP_THREAD_MUTEX */
|
|
#ifndef WINSTL_INCL_WINSTL_SYNCH_HPP_SPIN_MUTEX
|
|
# include <winstl/synch/spin_mutex.hpp>
|
|
#endif /* !WINSTL_INCL_WINSTL_SYNCH_HPP_SPIN_MUTEX */
|
|
#ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_LOCK_SCOPE
|
|
# include <stlsoft/synch/lock_scope.hpp>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_SYNCH_HPP_LOCK_SCOPE */
|
|
#ifndef STLSOFT_INCL_STLSOFT_CONVERSION_HPP_SAP_CAST
|
|
# include <stlsoft/conversion/sap_cast.hpp>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_CONVERSION_HPP_SAP_CAST */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Namespace
|
|
*/
|
|
|
|
#ifndef _WINSTL_NO_NAMESPACE
|
|
# if defined(_STLSOFT_NO_NAMESPACE) || \
|
|
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
|
|
/* There is no stlsoft namespace, so must define ::winstl */
|
|
namespace winstl
|
|
{
|
|
# else
|
|
/* Define stlsoft::winstl_project */
|
|
|
|
namespace stlsoft
|
|
{
|
|
|
|
namespace winstl_project
|
|
{
|
|
|
|
# endif /* _STLSOFT_NO_NAMESPACE */
|
|
#endif /* !_WINSTL_NO_NAMESPACE */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Pre-processor options
|
|
*/
|
|
|
|
#if defined(_WINSTL_INT_TO_STRING_USE_DECLSPECTHREAD_FOR_EXES)
|
|
# if defined(_DLL) || \
|
|
defined(__DLL__) || \
|
|
defined(_WINDLL) || \
|
|
defined(_USRDLL) || \
|
|
defined(_AFXDLL)
|
|
# pragma message("Using _WINSTL_INT_TO_STRING_USE_DECLSPECTHREAD_FOR_EXES when building DLLs will result in their not being loadable dynamically (via LoadLibrary())")
|
|
# endif /* dll */
|
|
#endif /* _WINSTL_INT_TO_STRING_USE_DECLSPECTHREAD_FOR_EXES */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Functions
|
|
*/
|
|
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
|
|
#ifdef STLSOFT_CF_NAMESPACE_SUPPORT
|
|
namespace int_to_string_tls
|
|
{
|
|
#endif /* STLSOFT_CF_NAMESPACE_SUPPORT */
|
|
|
|
// NOTE: This class had to be moved out of line to prevent VC++
|
|
// from emitting multiple definitions. Silly billy!
|
|
|
|
struct thread_mx_
|
|
: public thread_mutex
|
|
{
|
|
public:
|
|
thread_mx_()
|
|
{}
|
|
|
|
void* operator new(ws_size_t , void* p)
|
|
{
|
|
return p;
|
|
}
|
|
|
|
#if !defined(STLSOFT_COMPILER_IS_BORLAND) && \
|
|
( !defined(STLSOFT_COMPILER_IS_MSVC) || \
|
|
_MSC_VER >= 1200)
|
|
void operator delete(void* , void* )
|
|
{}
|
|
#endif /* compiler */
|
|
void operator delete(void*)
|
|
{}
|
|
};
|
|
|
|
|
|
template< ss_typename_param_k C
|
|
, ws_size_t CCH
|
|
>
|
|
struct Slot
|
|
{
|
|
Slot(Slot* next)
|
|
: next(next)
|
|
{}
|
|
~Slot() stlsoft_throw_0()
|
|
{
|
|
delete next;
|
|
}
|
|
|
|
// Use the process heap because:
|
|
//
|
|
// 1. Don't want to worry about thread-specificity, since
|
|
// deallocation will occur in a different thread to allocation
|
|
// 2. Don't want to worry about linkage to any specific CRT or
|
|
// other library
|
|
// 3. Doesn't matter how fast it is
|
|
// 4. Want it to be *highly* unlikely that allocation will fail,
|
|
// which is indeed pretty unheard of when using the Win32
|
|
// process heap.
|
|
// 5. Want a C++-exception free solution, so use the Win32-system
|
|
// out-of-memory exception, and not have to worry about any
|
|
// linkage pains.
|
|
void* operator new(ws_size_t cb)
|
|
{
|
|
return ::HeapAlloc(::GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, cb);
|
|
}
|
|
void operator delete(void* pv)
|
|
{
|
|
::HeapFree(::GetProcessHeap(), 0, pv);
|
|
}
|
|
|
|
C buff[CCH];
|
|
Slot* next;
|
|
};
|
|
|
|
template< ss_typename_param_k C
|
|
, ws_size_t CCH
|
|
>
|
|
struct Key
|
|
{
|
|
typedef Slot<C, CCH> Slot;
|
|
|
|
// This is admittedly totally gross, but it works and will be portable
|
|
// across different compilers. The reason it works is that s_index is
|
|
// static, and therefore all its members will be 0. This facilitates
|
|
// using interlocking and spin-locks in order to manage the lifetime
|
|
// correctly, and control access to the instance's constructor.
|
|
//
|
|
// Note that no members are initialised in a constructor member
|
|
// initialisation list (MIL). They are initialised within the
|
|
// constructor body
|
|
|
|
Key()
|
|
{
|
|
// Since multiple threads could get into here before they
|
|
// are all eventually blocked out by the static controller
|
|
// variable, we must guard against such multiple
|
|
// construction. Hence, if this is the only thread currently
|
|
// engaged in construction, we can proceed to initialisation.
|
|
// otherwise we must spin.
|
|
//
|
|
// We can start off by incrementing m_ctor, since it will have
|
|
// been initialised to 0 by the load-time initialisation of
|
|
// all static memory
|
|
|
|
// Wrap the constructor count in a spin-mutex, and then lock it
|
|
spin_mutex smx(&m_ctor);
|
|
stlsoft_ns_qual(lock_scope)<spin_mutex, spin_mutex_lock_traits> lock(smx);
|
|
|
|
if(0 == m_init++) // The test on this variable is always guarded by m_ctor
|
|
{
|
|
// Initialisation.
|
|
|
|
// The construction thread could be suspended after a
|
|
// successful completion of the constructor, but before
|
|
// the hidden boolean managing static creation was
|
|
// updated. Therefore, we need to reference-count the
|
|
// construction, which is done via another interlocked
|
|
// count, this time on m_init.
|
|
|
|
// The constructor has not yet been called through
|
|
// to this point
|
|
|
|
new (&mx()) thread_mx_();
|
|
|
|
m_index = ::TlsAlloc();
|
|
|
|
// Use Win32 exception because:
|
|
//
|
|
// 1. Process cannot recover from this error in any
|
|
// meaningful way
|
|
// 2. Do not want to couple to C++ exception-handling
|
|
// and there is no graceful way to allow this to be
|
|
// parameterisable. (May allow a pp-discriminated
|
|
// mechanism in next version.)
|
|
if(TLS_OUT_OF_INDEXES == m_index)
|
|
{
|
|
::RaiseException(STATUS_NO_MEMORY, EXCEPTION_NONCONTINUABLE, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
~Key() stlsoft_throw_0()
|
|
{
|
|
if(0 == ::InterlockedDecrement((LPLONG)&m_init))
|
|
{
|
|
// Walk the slot list and free. This can be as slow as
|
|
// you like, since performance is not important here
|
|
delete m_top;
|
|
|
|
// Now release the index
|
|
::TlsFree(m_index);
|
|
|
|
// Need to explicitly destroy the mutex.
|
|
mx().~thread_mutex();
|
|
}
|
|
}
|
|
|
|
Slot* GetSlot()
|
|
{
|
|
// NOTE: This does not need to be thread-safe
|
|
return sap_cast<Slot*>(::TlsGetValue(m_index));
|
|
}
|
|
|
|
Slot* AllocSlot()
|
|
{
|
|
Slot* next;
|
|
|
|
{ // Protect linked-list manipulation
|
|
stlsoft_ns_qual(lock_scope)<thread_mutex, thread_mutex_lock_traits> lock(mx());
|
|
|
|
m_top = next = new Slot(m_top);
|
|
}
|
|
|
|
::TlsSetValue(m_index, next);
|
|
|
|
return next;
|
|
}
|
|
|
|
// Implementation
|
|
private:
|
|
thread_mutex &mx()
|
|
{
|
|
return *static_cast<thread_mutex*>(static_cast<void*>(&m__mx.bytes[0]));
|
|
}
|
|
|
|
private:
|
|
#if 0
|
|
// In an ideal world the member layout would be as follows:
|
|
ws_dword_t m_index;
|
|
Slot* m_top;
|
|
thread_mutex m_mx;
|
|
#else /* ? 0 */
|
|
// But we're not in an ideal world, so it is like this
|
|
ws_dword_t m_index;
|
|
Slot* m_top;
|
|
union
|
|
{
|
|
ws_byte_t bytes[sizeof(thread_mutex)];
|
|
long double ld;
|
|
} m__mx;
|
|
ws_sint32_t m_init; // Construction count
|
|
ws_sint32_t m_ctor; // Ctor entry count
|
|
#endif /* 0 */
|
|
};
|
|
|
|
#ifdef STLSOFT_CF_NAMESPACE_SUPPORT
|
|
} /* namespace int_to_string_tls */
|
|
#endif /* STLSOFT_CF_NAMESPACE_SUPPORT */
|
|
|
|
|
|
template< ss_typename_param_k C
|
|
, ws_size_t CCH
|
|
>
|
|
inline C* i2str_get_tss_buffer()
|
|
{
|
|
#if defined(_WINSTL_INT_TO_STRING_USE_DECLSPECTHREAD_FOR_EXES)
|
|
__declspec(thread) static C s_buffer[CCH];
|
|
|
|
return s_buffer;
|
|
#else
|
|
|
|
#ifdef STLSOFT_CF_NAMESPACE_SUPPORT
|
|
typedef int_to_string_tls::Key<C, CCH> Key;
|
|
typedef int_to_string_tls::Slot<C, CCH> Slot;
|
|
#else
|
|
typedef Key<C, CCH> Key;
|
|
typedef Slot<C, CCH> Slot;
|
|
#endif /* STLSOFT_CF_NAMESPACE_SUPPORT */
|
|
|
|
static Key s_index;
|
|
Slot* slot = s_index.GetSlot();
|
|
|
|
if(NULL == slot)
|
|
{
|
|
slot = s_index.AllocSlot();
|
|
}
|
|
|
|
return slot->buff;
|
|
#endif /* dll */
|
|
}
|
|
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/** Converts a signed 8-bit integer to a character string
|
|
*
|
|
* For example:
|
|
\code
|
|
signed char v = 13;
|
|
|
|
assert(0 == ::strcmp(winstl::int_to_string<char>(v), "13"));
|
|
assert(0 == ::wcscmp(winstl::int_to_string<wchar_t>(v), L"13"));
|
|
\endcode
|
|
*
|
|
* \ingroup group__library__conversion
|
|
*
|
|
* \warning This function is *not* re-entrant. You must ensure that
|
|
* it is only invoked once in a statement. This includes possible
|
|
* invocations by other functions in the same statement.
|
|
*/
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(ws_sint8_t value)
|
|
{
|
|
const ws_size_t CCH = 21; // 5 fits 8-bit + sign
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
/** Converts a unsigned 8-bit integer to a character string
|
|
*
|
|
* For example:
|
|
\code
|
|
unsigned char v = 14;
|
|
|
|
assert(0 == ::strcmp(winstl::int_to_string<char>(v), "14"));
|
|
assert(0 == ::wcscmp(winstl::int_to_string<wchar_t>(v), L"14"));
|
|
\endcode
|
|
*
|
|
* \ingroup group__library__conversion
|
|
*
|
|
* \warning This function is *not* re-entrant. You must ensure that
|
|
* it is only invoked once in a statement. This includes possible
|
|
* invocations by other functions in the same statement.
|
|
*/
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(ws_uint8_t value)
|
|
{
|
|
const ws_size_t CCH = 21; // 4 fits 8-bit
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
/** Converts a signed 16-bit integer to a character string
|
|
*
|
|
* For example:
|
|
\code
|
|
signed char v = 15;
|
|
|
|
assert(0 == ::strcmp(winstl::int_to_string<char>(v), "15"));
|
|
assert(0 == ::wcscmp(winstl::int_to_string<wchar_t>(v), L"15"));
|
|
\endcode
|
|
*
|
|
* \ingroup group__library__conversion
|
|
*
|
|
* \warning This function is *not* re-entrant. You must ensure that
|
|
* it is only invoked once in a statement. This includes possible
|
|
* invocations by other functions in the same statement.
|
|
*/
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(ws_sint16_t value)
|
|
{
|
|
const ws_size_t CCH = 21; // 7 fits 16-bit + sign
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
/** Converts a unsigned 16-bit integer to a character string
|
|
*
|
|
* For example:
|
|
\code
|
|
unsigned char v = 16;
|
|
|
|
assert(0 == ::strcmp(winstl::int_to_string<char>(v), "16"));
|
|
assert(0 == ::wcscmp(winstl::int_to_string<wchar_t>(v), L"16"));
|
|
\endcode
|
|
*
|
|
* \ingroup group__library__conversion
|
|
*
|
|
* \warning This function is *not* re-entrant. You must ensure that
|
|
* it is only invoked once in a statement. This includes possible
|
|
* invocations by other functions in the same statement.
|
|
*/
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(ws_uint16_t value)
|
|
{
|
|
const ws_size_t CCH = 21; // 6 fits 16-bit
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
/** Converts a signed 32-bit integer to a character string
|
|
*
|
|
* For example:
|
|
\code
|
|
signed char v = 17;
|
|
|
|
assert(0 == ::strcmp(winstl::int_to_string<char>(v), "17"));
|
|
assert(0 == ::wcscmp(winstl::int_to_string<wchar_t>(v), L"17"));
|
|
\endcode
|
|
*
|
|
* \ingroup group__library__conversion
|
|
*
|
|
* \warning This function is *not* re-entrant. You must ensure that
|
|
* it is only invoked once in a statement. This includes possible
|
|
* invocations by other functions in the same statement.
|
|
*/
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(ws_sint32_t value)
|
|
{
|
|
const ws_size_t CCH = 21; // 12 fits 32-bit + sign
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
/** Converts a unsigned 32-bit integer to a character string
|
|
*
|
|
* For example:
|
|
\code
|
|
unsigned char v = 18;
|
|
|
|
assert(0 == ::strcmp(winstl::int_to_string<char>(v), "18"));
|
|
assert(0 == ::wcscmp(winstl::int_to_string<wchar_t>(v), L"18"));
|
|
\endcode
|
|
*
|
|
* \ingroup group__library__conversion
|
|
*
|
|
* \warning This function is *not* re-entrant. You must ensure that
|
|
* it is only invoked once in a statement. This includes possible
|
|
* invocations by other functions in the same statement.
|
|
*/
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(ws_uint32_t value)
|
|
{
|
|
const ws_size_t CCH = 21; // 11 fits 32-bit
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
/** Converts a signed 64-bit integer to a character string
|
|
*
|
|
* For example:
|
|
\code
|
|
signed char v = 19;
|
|
|
|
assert(0 == ::strcmp(winstl::int_to_string<char>(v), "19"));
|
|
assert(0 == ::wcscmp(winstl::int_to_string<wchar_t>(v), L"19"));
|
|
\endcode
|
|
*
|
|
* \ingroup group__library__conversion
|
|
*
|
|
* \warning This function is *not* re-entrant. You must ensure that
|
|
* it is only invoked once in a statement. This includes possible
|
|
* invocations by other functions in the same statement.
|
|
*/
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(ws_sint64_t const& value)
|
|
{
|
|
const ws_size_t CCH = 21; // fits 64-bit + sign
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
/** Converts a unsigned 64-bit integer to a character string
|
|
*
|
|
* For example:
|
|
\code
|
|
unsigned char v = 20;
|
|
|
|
assert(0 == ::strcmp(winstl::int_to_string<char>(v), "20"));
|
|
assert(0 == ::wcscmp(winstl::int_to_string<wchar_t>(v), L"20"));
|
|
\endcode
|
|
*
|
|
* \ingroup group__library__conversion
|
|
*
|
|
* \warning This function is *not* re-entrant. You must ensure that
|
|
* it is only invoked once in a statement. This includes possible
|
|
* invocations by other functions in the same statement.
|
|
*/
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(ws_uint64_t const& value)
|
|
{
|
|
const ws_size_t CCH = 21; // fits 64-bit
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
|
|
#ifdef STLSOFT_CF_INT_DISTINCT_INT_TYPE
|
|
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(int const& value)
|
|
{
|
|
const ws_size_t CCH = 21; // fits 64-bit
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(unsigned int const& value)
|
|
{
|
|
const ws_size_t CCH = 21; // fits 64-bit
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
#endif /* !STLSOFT_CF_INT_DISTINCT_INT_TYPE */
|
|
|
|
#ifdef STLSOFT_CF_LONG_DISTINCT_INT_TYPE
|
|
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(long const& value)
|
|
{
|
|
const ws_size_t CCH = 21; // fits 64-bit
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
template<ss_typename_param_k C>
|
|
inline C const* int_to_string(unsigned long const& value)
|
|
{
|
|
const ws_size_t CCH = 21; // fits 64-bit
|
|
C* buffer = i2str_get_tss_buffer<C, CCH>();
|
|
|
|
return stlsoft::integer_to_string(buffer, CCH, value);
|
|
}
|
|
|
|
#endif /* !STLSOFT_CF_LONG_DISTINCT_INT_TYPE */
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// Unit-testing
|
|
|
|
#ifdef STLSOFT_UNITTEST
|
|
# include "./unittest/int_to_string_unittest_.h"
|
|
#endif /* STLSOFT_UNITTEST */
|
|
|
|
/* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
#ifndef _WINSTL_NO_NAMESPACE
|
|
# if defined(_STLSOFT_NO_NAMESPACE) || \
|
|
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
|
|
} /* namespace winstl */
|
|
# else
|
|
} /* namespace winstl_project */
|
|
} /* namespace stlsoft */
|
|
# endif /* _STLSOFT_NO_NAMESPACE */
|
|
#endif /* !_WINSTL_NO_NAMESPACE */
|
|
|
|
/* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
#endif /* !WINSTL_INCL_WINSTL_CONVERSION_HPP_INT_TO_STRING */
|
|
|
|
/* ///////////////////////////// end of file //////////////////////////// */
|