SQLRETURN number_to_string()

in source/shared/core_results.cpp [161:232]


SQLRETURN number_to_string( _In_ Number* number_data, _Out_writes_bytes_to_opt_(buffer_length, *out_buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length, _Inout_ sqlsrv_error_auto_ptr& last_error )
{
    size_t precision = 0;

#ifdef _WIN32
    std::basic_ostringstream<Char> os;
    precision = get_float_precision( buffer_length, sizeof( Char ));
    os.precision( precision );
    std::locale loc;
    os.imbue(loc);
    std::use_facet< std::num_put< Char > >( loc ).put( std::basic_ostream<Char>::_Iter( os.rdbuf()), os, ' ', *number_data );
    std::basic_string<Char>& str_num = os.str();

    if ( os.fail() ) {
        last_error = new ( sqlsrv_malloc(sizeof( sqlsrv_error ))) sqlsrv_error(( SQLCHAR* ) "IMSSP", (SQLCHAR*) "Failed to convert number to string", -1 );
        return SQL_ERROR;
    }

    if ( str_num.size() * sizeof( Char ) > ( size_t )buffer_length ) {
        last_error = new ( sqlsrv_malloc(sizeof( sqlsrv_error ))) sqlsrv_error(( SQLCHAR* ) "HY090", ( SQLCHAR* ) "Buffer length too small to hold number as string", -1 );
        return SQL_ERROR;
    }

   *out_buffer_length = str_num.size() * sizeof( Char ); // str_num.size() already include the NULL terminator
    memcpy_s( buffer, buffer_length, str_num.c_str(), *out_buffer_length );

    return SQL_SUCCESS;
#else
    std::basic_string<char> str_num;
    SQLRETURN r;

    if ( std::is_integral<Number>::value )
    {
        long num_data = *number_data;
        r = get_string_from_stream<long>( num_data, str_num, precision, last_error );
    }
    else
    {
        precision = get_float_precision( buffer_length, sizeof( Char ));
        r = get_string_from_stream<double>( *number_data, str_num, precision, last_error );
    }

    if ( r == SQL_ERROR ) return SQL_ERROR;

    if ( std::is_same<Char, char16_t>::value )
    {

        std::basic_string<char16_t> str;
                
        for (const auto &mb : str_num )
        {
            size_t cch = SystemLocale::NextChar( CP_ACP, &mb ) - &mb;
            if ( cch > 0 )
            {
                WCHAR ch16;
                DWORD rc;                
                size_t cchActual = SystemLocale::ToUtf16( CP_ACP, &mb, cch, &ch16, 1, &rc);
                if (cchActual > 0)
                {
                    str.push_back ( ch16 );
                }
            }
        }

        return copy_buffer<char16_t>( buffer, buffer_length, out_buffer_length, str, last_error );
    }

    return copy_buffer<char>( buffer, buffer_length, out_buffer_length, str_num, last_error );

#endif // _WIN32

}