Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:58

0001 //
0002 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
0003 // Copyright (c) 2020 Peter Dimov (pdimov at gmail dot com),
0004 //
0005 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0006 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 // Official repository: https://github.com/boostorg/json
0009 //
0010 
0011 #ifndef BOOST_JSON_DETAIL_IMPL_FORMAT_IPP
0012 #define BOOST_JSON_DETAIL_IMPL_FORMAT_IPP
0013 
0014 #include <boost/json/detail/ryu/ryu.hpp>
0015 #include <cstring>
0016 
0017 namespace boost {
0018 namespace json {
0019 namespace detail {
0020 
0021 /*  Reference work:
0022 
0023     https://www.ampl.com/netlib/fp/dtoa.c
0024     https://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
0025     https://kkimdev.github.io/posts/2018/06/15/IEEE-754-Floating-Point-Type-in-C++.html
0026 */
0027 
0028 inline char const* digits_lut() noexcept
0029 {
0030     return
0031         "00010203040506070809"
0032         "10111213141516171819"
0033         "20212223242526272829"
0034         "30313233343536373839"
0035         "40414243444546474849"
0036         "50515253545556575859"
0037         "60616263646566676869"
0038         "70717273747576777879"
0039         "80818283848586878889"
0040         "90919293949596979899";
0041 }
0042 
0043 inline void format_four_digits( char * dest, unsigned v )
0044 {
0045     std::memcpy( dest + 2, digits_lut() + (v % 100) * 2, 2 );
0046     std::memcpy( dest    , digits_lut() + (v / 100) * 2, 2 );
0047 }
0048 
0049 inline void format_two_digits( char * dest, unsigned v )
0050 {
0051     std::memcpy( dest, digits_lut() + v * 2, 2 );
0052 }
0053 
0054 inline void format_digit( char * dest, unsigned v )
0055 {
0056     *dest = static_cast<char>( v + '0' );
0057 }
0058 
0059 unsigned
0060 format_uint64(
0061     char* dest,
0062     std::uint64_t v) noexcept
0063 {
0064     if(v < 10)
0065     {
0066         *dest = static_cast<char>( '0' + v );
0067         return 1;
0068     }
0069 
0070     char buffer[ 24 ];
0071 
0072     char * p = buffer + 24;
0073 
0074     while( v >= 1000 )
0075     {
0076         p -= 4;
0077         format_four_digits( p, v % 10000 );
0078         v /= 10000;
0079     }
0080 
0081     if( v >= 10 )
0082     {
0083         p -= 2;
0084         format_two_digits( p, v % 100 );
0085         v /= 100;
0086     }
0087 
0088     if( v )
0089     {
0090         p -= 1;
0091         format_digit( p, static_cast<unsigned>(v) );
0092     }
0093 
0094     unsigned const n = static_cast<unsigned>( buffer + 24 - p );
0095     std::memcpy( dest, p, n );
0096 
0097     return n;
0098 }
0099 
0100 unsigned
0101 format_int64(
0102     char* dest, int64_t i) noexcept
0103 {
0104     std::uint64_t ui = static_cast<
0105         std::uint64_t>(i);
0106     if(i >= 0)
0107         return format_uint64(dest, ui);
0108     *dest++ = '-';
0109     ui = ~ui + 1;
0110     return 1 + format_uint64(dest, ui);
0111 }
0112 
0113 unsigned
0114 format_double(
0115     char* dest, double d, bool allow_infinity_and_nan) noexcept
0116 {
0117     return static_cast<int>(
0118         ryu::d2s_buffered_n(d, dest, allow_infinity_and_nan));
0119 }
0120 
0121 } // detail
0122 } // namespace json
0123 } // namespace boost
0124 
0125 #endif