예제 #1
0
 typename std::enable_if<std::is_same<CharT,wchar_t>::value,double>::type
 operator()(const CharT* s, size_t /*length*/) const
 {
     CharT *end = nullptr;
     double val = wcstod(s, &end);
     if (s == end)
     {
         JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert string to double failed"));
     }
     return val;
 }
예제 #2
0
 typename std::enable_if<std::is_same<CharT,char>::value,double>::type
 operator()(const CharT* s, size_t length) const
 {
     char *end = nullptr;
     double val = strtold_l(s, &end, locale_);
     if (s == end)
     {
         JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert string to double failed"));
     }
     return val;
 }
예제 #3
0
    size_t operator()(double val, Result& result)
    {
        size_t count = 0;

        chars_format format = override_.format() != chars_format() ? override_.format() : chars_format::general;

        int decimal_places;
        if (override_.decimal_places() != 0)
        {
            decimal_places = override_.decimal_places();
        }
        else
        {
            format = chars_format::general;
            decimal_places = 0;
        }             

        char number_buffer[200]; 
        int length = 0;

        switch (format)
        {
        case chars_format::fixed:
            {
                length = snprintf(number_buffer, sizeof(number_buffer), "%1.*f", decimal_places, val);
                if (length < 0)
                {
                    JSONCONS_THROW(json_runtime_error<std::invalid_argument>("print_double failed."));
                }
                dump_buffer(number_buffer, length, decimal_point_, result);
            }
            break;
        case chars_format::scientific:
            {
                length = snprintf(number_buffer, sizeof(number_buffer), "%1.*e", decimal_places, val);
                if (length < 0)
                {
                    JSONCONS_THROW(json_runtime_error<std::invalid_argument>("print_double failed."));
                }
                dump_buffer(number_buffer, length, decimal_point_, result);
            }
            break;
        case chars_format::general:
            {
                if (override_.precision() != 0)
                {
                    int precision = override_.precision();
                    length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision, val);
                    if (length < 0)
                    {
                        JSONCONS_THROW(json_runtime_error<std::invalid_argument>("print_double failed."));
                    }
                    dump_buffer(number_buffer, length, decimal_point_, result);
                }
                else
                {
                    if (!dtoa(val, decimal_point_, result))
                    {
                        JSONCONS_THROW(json_runtime_error<std::invalid_argument>("print_double failed."));
                    }
                }             
                break;
            }
            default:
                JSONCONS_THROW(json_runtime_error<std::invalid_argument>("print_double failed."));
                break;
        }
        return count;
    }
예제 #4
0
    void operator()(double val, const floating_point_options& fmt, Writer& writer)
    {
        typedef typename Writer::char_type char_type;

        chars_format format;
        if (override_.format() != chars_format::hex)
        {
            format = override_.format();
        }
        else 
        {
            format = fmt.format();
        }

        int precision;
        int precision2 = 0;
        if (override_.precision() != 0)
        {
            precision = override_.precision();
        }
        else if (fmt.precision() != 0)
        {
            precision = fmt.precision();
        }
        else
        {
            precision = std::numeric_limits<double>::digits10;
            precision2 = std::numeric_limits<double>::max_digits10;
        }             

        int decimal_places;
        if (override_.decimal_places() != 0)
        {
            decimal_places = override_.decimal_places();
        }
        else if (fmt.decimal_places() != 0)
        {
            decimal_places = fmt.decimal_places();
        }
        else
        {
            format = chars_format::general;
        }             

        char number_buffer[200]; 

        int length = 0;
        switch (format)
        {
        case chars_format::fixed:
            {
                length = snprintf(number_buffer, sizeof(number_buffer), "%1.*f", decimal_places, val);
                if (length < 0)
                {
                    JSONCONS_THROW(json_exception_impl<std::invalid_argument>("print_double failed."));
                }
            }
            break;
        case chars_format::scientific:
            {
                length = snprintf(number_buffer, sizeof(number_buffer), "%1.*e", decimal_places, val);
                if (length < 0)
                {
                    JSONCONS_THROW(json_exception_impl<std::invalid_argument>("print_double failed."));
                }
            }
            break;
        default:
            {
                length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision, val);
                if (length < 0)
                {
                    JSONCONS_THROW(json_exception_impl<std::invalid_argument>("print_double failed."));
                }
                if (precision2 > 0)
                {
                    if (to_double_(number_buffer,sizeof(number_buffer)) != val)
                    {
                        length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision2, val);
                        if (length < 0)
                        {
                            JSONCONS_THROW(json_exception_impl<std::invalid_argument>("print_double failed."));
                        }
                    }
                }
            }
            break;
        }

        const char* sbeg = number_buffer;
        const char* send = sbeg + length;
        const char* pexp = send;

        if (sbeg != send)
        {
            bool dot = false;
            for (pexp = sbeg; *pexp != 'e' && *pexp != 'E' && pexp < send; ++pexp)
            {
            }

            for (const char* q = sbeg; q < pexp; ++q)
            {
                switch (*q)
                {
                case '-':case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
                    writer.put(*q);
                    break;
                default:
                    if (*q == decimal_point_)
                    {
                        dot = true;
                        writer.put('.');
                    }
                    break;
                }
            }
            if (!dot)
            {
                writer.put('.');
                writer.put('0');
                dot = true;
            }
            for (const char* q = pexp; q < send; ++q)
            {
                writer.put(*q);
            }
        }
    }