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