Coverage Report

Created: 2025-09-05 06:51

/src/boost/boost/json/detail/impl/format.ipp
Line
Count
Source
1
//
2
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3
// Copyright (c) 2020 Peter Dimov (pdimov at gmail dot com),
4
//
5
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
//
8
// Official repository: https://github.com/boostorg/json
9
//
10
11
#ifndef BOOST_JSON_DETAIL_IMPL_FORMAT_IPP
12
#define BOOST_JSON_DETAIL_IMPL_FORMAT_IPP
13
14
#include <boost/json/detail/ryu/ryu.hpp>
15
#include <cstring>
16
17
namespace boost {
18
namespace json {
19
namespace detail {
20
21
/*  Reference work:
22
23
    https://www.ampl.com/netlib/fp/dtoa.c
24
    https://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
25
    https://kkimdev.github.io/posts/2018/06/15/IEEE-754-Floating-Point-Type-in-C++.html
26
*/
27
28
inline char const* digits_lut() noexcept
29
810k
{
30
810k
    return
31
810k
        "00010203040506070809"
32
810k
        "10111213141516171819"
33
810k
        "20212223242526272829"
34
810k
        "30313233343536373839"
35
810k
        "40414243444546474849"
36
810k
        "50515253545556575859"
37
810k
        "60616263646566676869"
38
810k
        "70717273747576777879"
39
810k
        "80818283848586878889"
40
810k
        "90919293949596979899";
41
810k
}
42
43
inline void format_four_digits( char * dest, unsigned v )
44
332k
{
45
332k
    std::memcpy( dest + 2, digits_lut() + (v % 100) * 2, 2 );
46
332k
    std::memcpy( dest    , digits_lut() + (v / 100) * 2, 2 );
47
332k
}
48
49
inline void format_two_digits( char * dest, unsigned v )
50
145k
{
51
145k
    std::memcpy( dest, digits_lut() + v * 2, 2 );
52
145k
}
53
54
inline void format_digit( char * dest, unsigned v )
55
91.6k
{
56
91.6k
    *dest = static_cast<char>( v + '0' );
57
91.6k
}
58
59
unsigned
60
format_uint64(
61
    char* dest,
62
    std::uint64_t v) noexcept
63
2.91M
{
64
2.91M
    if(v < 10)
65
2.70M
    {
66
2.70M
        *dest = static_cast<char>( '0' + v );
67
2.70M
        return 1;
68
2.70M
    }
69
70
210k
    char buffer[ 24 ];
71
72
210k
    char * p = buffer + 24;
73
74
543k
    while( v >= 1000 )
75
332k
    {
76
332k
        p -= 4;
77
332k
        format_four_digits( p, v % 10000 );
78
332k
        v /= 10000;
79
332k
    }
80
81
210k
    if( v >= 10 )
82
145k
    {
83
145k
        p -= 2;
84
145k
        format_two_digits( p, v % 100 );
85
145k
        v /= 100;
86
145k
    }
87
88
210k
    if( v )
89
91.6k
    {
90
91.6k
        p -= 1;
91
91.6k
        format_digit( p, static_cast<unsigned>(v) );
92
91.6k
    }
93
94
210k
    unsigned const n = static_cast<unsigned>( buffer + 24 - p );
95
210k
    std::memcpy( dest, p, n );
96
97
210k
    return n;
98
2.91M
}
99
100
unsigned
101
format_int64(
102
    char* dest, int64_t i) noexcept
103
2.87M
{
104
2.87M
    std::uint64_t ui = static_cast<
105
2.87M
        std::uint64_t>(i);
106
2.87M
    if(i >= 0)
107
2.86M
        return format_uint64(dest, ui);
108
7.07k
    *dest++ = '-';
109
7.07k
    ui = ~ui + 1;
110
7.07k
    return 1 + format_uint64(dest, ui);
111
2.87M
}
112
113
unsigned
114
format_double(
115
    char* dest, double d, bool allow_infinity_and_nan) noexcept
116
5.83M
{
117
5.83M
    return static_cast<int>(
118
5.83M
        ryu::d2s_buffered_n(d, dest, allow_infinity_and_nan));
119
5.83M
}
120
121
} // detail
122
} // namespace json
123
} // namespace boost
124
125
#endif