// Copyright 2020-2022 Junekey Jeon // // The contents of this file may be used under the terms of // the Apache License v2.0 with LLVM Exceptions. // // (See accompanying file LICENSE-Apache or copy at // https://llvm.org/foundation/relicensing/LICENSE.txt) // // Alternatively, the contents of this file may be used under the terms of // the Boost Software License, Version 1.0. // (See accompanying file LICENSE-Boost or copy at // https://www.boost.org/LICENSE_1_0.txt) // // Unless required by applicable law or agreed to in writing, this software // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. #ifndef JKJ_HEADER_DRAGONBOX_TO_CHARS #define JKJ_HEADER_DRAGONBOX_TO_CHARS #include "dragonbox.h" namespace jkj::dragonbox { namespace to_chars_detail { template extern char* to_chars(typename FloatTraits::carrier_uint significand, int exponent, char* buffer) noexcept; // Avoid needless ABI overhead incurred by tag dispatch. template char* to_chars_n_impl(float_bits br, char* buffer) noexcept { auto const exponent_bits = br.extract_exponent_bits(); auto const s = br.remove_exponent_bits(exponent_bits); if (br.is_finite(exponent_bits)) { if (s.is_negative()) { *buffer = '-'; ++buffer; } if (br.is_nonzero()) { auto result = to_decimal( s, exponent_bits, policy::sign::ignore, policy::trailing_zero::ignore, typename PolicyHolder::decimal_to_binary_rounding_policy{}, typename PolicyHolder::binary_to_decimal_rounding_policy{}, typename PolicyHolder::cache_policy{}); return to_chars_detail::to_chars(result.significand, result.exponent, buffer); } else { *buffer = '0'; return buffer + 1; } } else { if (s.has_all_zero_significand_bits()) { if (s.is_negative()) { *buffer = '-'; ++buffer; } std::memcpy(buffer, "Infinity", 8); return buffer + 8; } else { std::memcpy(buffer, "NaN", 3); return buffer + 3; } } } } // Returns the next-to-end position template , class... Policies> char* to_chars_n(Float x, char* buffer, Policies... policies) noexcept { using namespace jkj::dragonbox::detail::policy_impl; using policy_holder = decltype(make_policy_holder( base_default_pair_list, base_default_pair, base_default_pair>{}, policies...)); return to_chars_detail::to_chars_n_impl(float_bits(x), buffer); } // Null-terminate and bypass the return value of fp_to_chars_n template , class... Policies> char* to_chars(Float x, char* buffer, Policies... policies) noexcept { auto ptr = to_chars_n(x, buffer, policies...); *ptr = '\0'; return ptr; } // Maximum required buffer size (excluding null-terminator) template inline constexpr std::size_t max_output_string_length = std::is_same_v ? // sign(1) + significand(9) + decimal_point(1) + exp_marker(1) + exp_sign(1) + exp(2) (1 + 9 + 1 + 1 + 1 + 2) : // format == ieee754_format::binary64 // sign(1) + significand(17) + decimal_point(1) + exp_marker(1) + exp_sign(1) + exp(3) (1 + 17 + 1 + 1 + 1 + 3); } #endif