Line data Source code
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 4839 : inline char const* digits_lut() noexcept
29 : {
30 : return
31 : "00010203040506070809"
32 : "10111213141516171819"
33 : "20212223242526272829"
34 : "30313233343536373839"
35 : "40414243444546474849"
36 : "50515253545556575859"
37 : "60616263646566676869"
38 : "70717273747576777879"
39 : "80818283848586878889"
40 4839 : "90919293949596979899";
41 : }
42 :
43 1988 : inline void format_four_digits( char * dest, unsigned v )
44 : {
45 1988 : std::memcpy( dest + 2, digits_lut() + (v % 100) * 2, 2 );
46 1988 : std::memcpy( dest , digits_lut() + (v / 100) * 2, 2 );
47 1988 : }
48 :
49 863 : inline void format_two_digits( char * dest, unsigned v )
50 : {
51 863 : std::memcpy( dest, digits_lut() + v * 2, 2 );
52 863 : }
53 :
54 405 : inline void format_digit( char * dest, unsigned v )
55 : {
56 405 : *dest = static_cast<char>( v + '0' );
57 405 : }
58 :
59 : unsigned
60 3614 : format_uint64(
61 : char* dest,
62 : std::uint64_t v) noexcept
63 : {
64 3614 : if(v < 10)
65 : {
66 2475 : *dest = static_cast<char>( '0' + v );
67 2475 : return 1;
68 : }
69 :
70 : char buffer[ 24 ];
71 :
72 1139 : char * p = buffer + 24;
73 :
74 3127 : while( v >= 1000 )
75 : {
76 1988 : p -= 4;
77 1988 : format_four_digits( p, v % 10000 );
78 1988 : v /= 10000;
79 : }
80 :
81 1139 : if( v >= 10 )
82 : {
83 863 : p -= 2;
84 863 : format_two_digits( p, v % 100 );
85 863 : v /= 100;
86 : }
87 :
88 1139 : if( v )
89 : {
90 405 : p -= 1;
91 405 : format_digit( p, static_cast<unsigned>(v) );
92 : }
93 :
94 1139 : unsigned const n = static_cast<unsigned>( buffer + 24 - p );
95 1139 : std::memcpy( dest, p, n );
96 :
97 1139 : return n;
98 : }
99 :
100 : unsigned
101 3189 : format_int64(
102 : char* dest, int64_t i) noexcept
103 : {
104 3189 : std::uint64_t ui = static_cast<
105 : std::uint64_t>(i);
106 3189 : if(i >= 0)
107 2747 : return format_uint64(dest, ui);
108 442 : *dest++ = '-';
109 442 : ui = ~ui + 1;
110 442 : return 1 + format_uint64(dest, ui);
111 : }
112 :
113 : unsigned
114 477 : format_double(
115 : char* dest, double d, bool allow_infinity_and_nan) noexcept
116 : {
117 : return static_cast<int>(
118 477 : ryu::d2s_buffered_n(d, dest, allow_infinity_and_nan));
119 : }
120 :
121 : } // detail
122 : } // namespace json
123 : } // namespace boost
124 :
125 : #endif
|