Function append_sprintf_va_list

Synopsis

#include <include/EASTL/string.h>

this_type & append_sprintf_va_list(const value_type *pFormat, va_list arguments)

Description

No description yet.

Source

Lines 1744-1862 in include/EASTL/string.h. Line 631 in include/EASTL/string.h.

template <typename T, typename Allocator>
basic_string<T, Allocator>& basic_string<T, Allocator>::append_sprintf_va_list(const value_type* pFormat, va_list arguments)
{
    // From unofficial C89 extension documentation:
    // The vsnprintf returns the number of characters written into the array,
    // not counting the terminating null character, or a negative value
    // if count or more characters are requested to be generated.
    // An error can occur while converting a value for output.
    // From the C99 standard:
    // The vsnprintf function returns the number of characters that would have
    // been written had n been sufficiently large, not counting the terminating
    // null character, or a negative value if an encoding error occurred.
    // Thus, the null-terminated output has been completely written if and only
    // if the returned value is nonnegative and less than n.
    // https://www.freebsd.org/cgi/man.cgi?query=vswprintf&sektion=3&manpath=freebsd-release-ports
    // https://www.freebsd.org/cgi/man.cgi?query=snprintf&manpath=SuSE+Linux/i386+11.3
    // Well its time to go on an adventure...
    // C99 vsnprintf states that a buffer size of zero returns the number of characters that would
    // be written to the buffer irrelevant of whether the buffer is a nullptr
    // But C99 vswprintf for wchar_t changes the behaviour of the return to instead say that it
    // "will fail if n or more wide characters were requested to be written", so
    // calling vswprintf with a buffer size of zero always returns -1
    // unless... you are MSVC where they deviate from the std and say if the buffer is NULL
    // and the size is zero it will return the number of characters written or if we are using
    // EAStdC which also does the sane behaviour.
if !EASTL_OPENSOURCE || defined(EA_PLATFORM_MICROSOFT)
    size_type nInitialSize = internalLayout().GetSize();
    int nReturnValue;
    #if EASTL_VA_COPY_ENABLED
        va_list argumentsSaved;
        va_copy(argumentsSaved, arguments);
    #endif
    nReturnValue = eastl::Vsnprintf(nullptr, 0, pFormat, arguments);
    if (nReturnValue > 0)
    {
        resize(nReturnValue + nInitialSize);
    #if EASTL_VA_COPY_ENABLED
        va_end(arguments);
        va_copy(arguments, argumentsSaved);
    #endif
        nReturnValue = eastl::Vsnprintf(internalLayout().BeginPtr() + nInitialSize, static_cast<size_t>(nReturnValue) + 1, pFormat, arguments);
    }
    if (nReturnValue >= 0)
        internalLayout().SetSize(nInitialSize + nReturnValue);
    #if EASTL_VA_COPY_ENABLED
        // va_end for arguments will be called by the caller.
        va_end(argumentsSaved);
    #endif
else
    size_type nInitialSize = internalLayout().GetSize();
    size_type nInitialRemainingCapacity = internalLayout().GetRemainingCapacity();
    int       nReturnValue;
    #if EASTL_VA_COPY_ENABLED
        va_list argumentsSaved;
        va_copy(argumentsSaved, arguments);
    #endif
    nReturnValue = eastl::Vsnprintf(internalLayout().EndPtr(), (size_t)nInitialRemainingCapacity + 1,
                                    pFormat, arguments);
    if(nReturnValue >= (int)(nInitialRemainingCapacity + 1))  // If there wasn't enough capacity...
    {
        // In this case we definitely have C99 Vsnprintf behaviour.
    #if EASTL_VA_COPY_ENABLED
        va_end(arguments);
        va_copy(arguments, argumentsSaved);
    #endif
        resize(nInitialSize + nReturnValue);
        nReturnValue = eastl::Vsnprintf(internalLayout().BeginPtr() + nInitialSize, (size_t)(nReturnValue + 1),
                                        pFormat, arguments);
    }
    else if(nReturnValue < 0) // If vsnprintf is non-C99-standard
    {
        // In this case we either have C89 extension behaviour or C99 behaviour.
        size_type n = eastl::max_alt((size_type)(SSOLayout::SSO_CAPACITY - 1), (size_type)(nInitialSize * 2));
        for(; (nReturnValue < 0) && (n < 1000000); n *= 2)
        {
        #if EASTL_VA_COPY_ENABLED
            va_end(arguments);
            va_copy(arguments, argumentsSaved);
        #endif
            resize(n);
            const size_t nCapacity = (size_t)(n - nInitialSize);
            nReturnValue = eastl::Vsnprintf(internalLayout().BeginPtr() + nInitialSize, nCapacity + 1, pFormat, arguments);
            if(nReturnValue == (int)(unsigned)nCapacity)
            {
                resize(++n);
                nReturnValue = eastl::Vsnprintf(internalLayout().BeginPtr() + nInitialSize, nCapacity + 2, pFormat, arguments);
            }
        }
    }
    if(nReturnValue >= 0)
        internalLayout().SetSize(nInitialSize + nReturnValue);
    #if EASTL_VA_COPY_ENABLED
        // va_end for arguments will be called by the caller.
        va_end(argumentsSaved);
    #endif
endif // EASTL_OPENSOURCE
    return *this;
}





Add Discussion as Guest

Log in