// // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) // Copyright (c) 2020 Peter Dimov (pdimov at gmail dot com), // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/json // #ifndef BOOST_JSON_DETAIL_IMPL_FORMAT_IPP #define BOOST_JSON_DETAIL_IMPL_FORMAT_IPP #include #include BOOST_JSON_NS_BEGIN namespace detail { /* Reference work: https://www.ampl.com/netlib/fp/dtoa.c https://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ https://kkimdev.github.io/posts/2018/06/15/IEEE-754-Floating-Point-Type-in-C++.html */ inline char const* digits_lut() noexcept { return "00010203040506070809" "10111213141516171819" "20212223242526272829" "30313233343536373839" "40414243444546474849" "50515253545556575859" "60616263646566676869" "70717273747576777879" "80818283848586878889" "90919293949596979899"; } inline void format_four_digits( char * dest, unsigned v ) { std::memcpy( dest + 2, digits_lut() + (v % 100) * 2, 2 ); std::memcpy( dest , digits_lut() + (v / 100) * 2, 2 ); } inline void format_two_digits( char * dest, unsigned v ) { std::memcpy( dest, digits_lut() + v * 2, 2 ); } inline void format_digit( char * dest, unsigned v ) { *dest = static_cast( v + '0' ); } unsigned format_uint64( char* dest, std::uint64_t v) noexcept { if(v < 10) { *dest = static_cast( '0' + v ); return 1; } char buffer[ 24 ]; char * p = buffer + 24; while( v >= 1000 ) { p -= 4; format_four_digits( p, v % 10000 ); v /= 10000; } if( v >= 10 ) { p -= 2; format_two_digits( p, v % 100 ); v /= 100; } if( v ) { p -= 1; format_digit( p, static_cast(v) ); } unsigned const n = static_cast( buffer + 24 - p ); std::memcpy( dest, p, n ); return n; } unsigned format_int64( char* dest, int64_t i) noexcept { std::uint64_t ui = static_cast< std::uint64_t>(i); if(i >= 0) return format_uint64(dest, ui); *dest++ = '-'; ui = ~ui + 1; return 1 + format_uint64(dest, ui); } unsigned format_double( char* dest, double d) noexcept { return static_cast( ryu::d2s_buffered_n(d, dest)); } } // detail BOOST_JSON_NS_END #endif