Skip to content

Commit 317e04f

Browse files
authored
Merge pull request #168 from boostorg/166.2
Fix for issue #166 negative precision
2 parents 1e8e3a7 + 340a72e commit 317e04f

File tree

5 files changed

+326
-129
lines changed

5 files changed

+326
-129
lines changed

include/boost/charconv/to_chars.hpp

+34-9
Original file line numberDiff line numberDiff line change
@@ -78,36 +78,61 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, boost
7878
//----------------------------------------------------------------------------------------------------------------------
7979

8080
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, float value,
81-
chars_format fmt = chars_format::general, int precision = -1 ) noexcept;
81+
chars_format fmt = chars_format::general) noexcept;
82+
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, double value,
83+
chars_format fmt = chars_format::general) noexcept;
84+
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, long double value,
85+
chars_format fmt = chars_format::general) noexcept;
86+
87+
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, float value,
88+
chars_format fmt, int precision) noexcept;
8289
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, double value,
83-
chars_format fmt = chars_format::general, int precision = -1 ) noexcept;
90+
chars_format fmt, int precision) noexcept;
8491
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, long double value,
85-
chars_format fmt = chars_format::general, int precision = -1 ) noexcept;
92+
chars_format fmt, int precision) noexcept;
8693

8794
#ifdef BOOST_CHARCONV_HAS_FLOAT128
8895
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, __float128 value,
89-
chars_format fmt = chars_format::general, int precision = -1 ) noexcept;
96+
chars_format fmt = chars_format::general) noexcept;
97+
98+
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, __float128 value,
99+
chars_format fmt, int precision) noexcept;
90100
#endif
91101

92102
#ifdef BOOST_CHARCONV_HAS_FLOAT16
103+
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float16_t value,
104+
chars_format fmt = chars_format::general) noexcept;
105+
93106
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float16_t value,
94-
chars_format fmt = chars_format::general, int precision = -1 ) noexcept;
107+
chars_format fmt, int precision) noexcept;
95108
#endif
96109
#ifdef BOOST_CHARCONV_HAS_FLOAT32
110+
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float32_t value,
111+
chars_format fmt = chars_format::general) noexcept;
112+
97113
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float32_t value,
98-
chars_format fmt = chars_format::general, int precision = -1 ) noexcept;
114+
chars_format fmt, int precision) noexcept;
99115
#endif
100116
#ifdef BOOST_CHARCONV_HAS_FLOAT64
117+
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float64_t value,
118+
chars_format fmt = chars_format::general) noexcept;
119+
101120
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float64_t value,
102-
chars_format fmt = chars_format::general, int precision = -1 ) noexcept;
121+
chars_format fmt, int precision) noexcept;
103122
#endif
104123
#if defined(BOOST_CHARCONV_HAS_STDFLOAT128) && defined(BOOST_CHARCONV_HAS_FLOAT128)
105124
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float128_t value,
106-
chars_format fmt = chars_format::general, int precision = -1 ) noexcept;
125+
chars_format fmt = chars_format::general) noexcept;
126+
127+
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float128_t value,
128+
chars_format fmt, int precision) noexcept;
107129
#endif
108130
#ifdef BOOST_CHARCONV_HAS_BRAINFLOAT16
131+
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::bfloat16_t value,
132+
chars_format fmt = chars_format::general) noexcept;
133+
109134
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::bfloat16_t value,
110-
chars_format fmt = chars_format::general, int precision = -1 ) noexcept;
135+
chars_format fmt, int precision) noexcept;
111136
#endif
112137

113138
} // namespace charconv

src/to_chars.cpp

+110-119
Original file line numberDiff line numberDiff line change
@@ -548,95 +548,76 @@ namespace boost { namespace charconv { namespace detail { namespace to_chars_det
548548

549549
}}}} // Namespaces
550550

551+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, float value,
552+
boost::charconv::chars_format fmt) noexcept
553+
{
554+
return boost::charconv::detail::to_chars_float_impl(first, last, value, fmt, -1);
555+
}
556+
551557
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, float value,
552558
boost::charconv::chars_format fmt, int precision) noexcept
553559
{
560+
if (precision < 0)
561+
{
562+
precision = 6;
563+
}
564+
554565
return boost::charconv::detail::to_chars_float_impl(first, last, value, fmt, precision);
555566
}
556567

568+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, double value,
569+
boost::charconv::chars_format fmt) noexcept
570+
{
571+
return boost::charconv::detail::to_chars_float_impl(first, last, value, fmt, -1);
572+
}
573+
557574
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, double value,
558575
boost::charconv::chars_format fmt, int precision) noexcept
559576
{
577+
if (precision < 0)
578+
{
579+
precision = 6;
580+
}
581+
560582
return boost::charconv::detail::to_chars_float_impl(first, last, value, fmt, precision);
561583
}
562584

563585
#if BOOST_CHARCONV_LDBL_BITS == 64 || defined(BOOST_MSVC)
564586

565587
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, long double value,
566-
boost::charconv::chars_format fmt, int precision) noexcept
588+
boost::charconv::chars_format fmt) noexcept
567589
{
568-
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<double>(value), fmt, precision);
590+
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<double>(value), fmt, -1);
569591
}
570592

571-
#elif (BOOST_CHARCONV_LDBL_BITS == 80 || BOOST_CHARCONV_LDBL_BITS == 128)
572-
573593
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, long double value,
574594
boost::charconv::chars_format fmt, int precision) noexcept
575595
{
576-
static_assert(std::numeric_limits<long double>::is_iec559, "Long double must be IEEE 754 compliant");
577-
578-
const auto classification = std::fpclassify(value);
579-
#if BOOST_CHARCONV_LDBL_BITS == 128
580-
if (classification == FP_NAN || classification == FP_INFINITE)
596+
if (precision < 0)
581597
{
582-
return boost::charconv::detail::to_chars_nonfinite(first, last, value, classification);
598+
precision = 6;
583599
}
584-
#else
585-
if (classification == FP_NAN || classification == FP_INFINITE)
586-
{
587-
const auto fd128 = boost::charconv::detail::ryu::long_double_to_fd128(value);
588-
const auto num_chars = boost::charconv::detail::ryu::generic_to_chars(fd128, first, last - first, fmt, precision);
589600

590-
if (num_chars > 0)
591-
{
592-
return { first + num_chars, std::errc() };
593-
}
594-
else
595-
{
596-
return {last, std::errc::value_too_large};
597-
}
598-
}
599-
#endif
601+
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<double>(value), fmt, precision);
602+
}
600603

601-
// Sanity check our bounds
602-
const std::ptrdiff_t buffer_size = last - first;
603-
auto real_precision = boost::charconv::detail::get_real_precision<long double>(precision);
604-
if (buffer_size < real_precision || first > last)
605-
{
606-
return {last, std::errc::value_too_large};
607-
}
604+
#elif (BOOST_CHARCONV_LDBL_BITS == 80 || BOOST_CHARCONV_LDBL_BITS == 128)
608605

609-
if (fmt == boost::charconv::chars_format::general || fmt == boost::charconv::chars_format::scientific)
610-
{
611-
const auto fd128 = boost::charconv::detail::ryu::long_double_to_fd128(value);
612-
const auto num_chars = boost::charconv::detail::ryu::generic_to_chars(fd128, first, last - first, fmt, precision);
606+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, long double value,
607+
boost::charconv::chars_format fmt) noexcept
608+
{
609+
return boost::charconv::detail::to_chars_float_impl(first, last, value, fmt, -1);
610+
}
613611

614-
if (num_chars > 0)
615-
{
616-
return { first + num_chars, std::errc() };
617-
}
618-
}
619-
else if (fmt == boost::charconv::chars_format::hex)
612+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, long double value,
613+
boost::charconv::chars_format fmt, int precision) noexcept
614+
{
615+
if (precision < 0)
620616
{
621-
return boost::charconv::detail::to_chars_hex(first, last, value, precision);
617+
precision = 6;
622618
}
623-
else if (fmt == boost::charconv::chars_format::fixed)
624-
{
625-
const auto fd128 = boost::charconv::detail::ryu::long_double_to_fd128(value);
626-
const auto num_chars = boost::charconv::detail::ryu::generic_to_chars_fixed(fd128, first, last - first, precision);
627619

628-
if (num_chars > 0)
629-
{
630-
return { first + num_chars, std::errc() };
631-
}
632-
else if (num_chars == -static_cast<int>(std::errc::value_too_large))
633-
{
634-
return { last, std::errc::value_too_large };
635-
}
636-
}
637-
638-
// Fallback to printf methods
639-
return boost::charconv::detail::to_chars_printf_impl(first, last, value, fmt, precision);
620+
return boost::charconv::detail::to_chars_float_impl(first, last, value, fmt, precision);
640621
}
641622

642623
#else
@@ -681,117 +662,127 @@ boost::charconv::to_chars_result boost::charconv::to_chars( char* first, char* l
681662

682663
#ifdef BOOST_CHARCONV_HAS_FLOAT128
683664

684-
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, __float128 value, boost::charconv::chars_format fmt, int precision) noexcept
665+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, __float128 value, boost::charconv::chars_format fmt) noexcept
685666
{
686-
// Sanity check our bounds
687-
if (first >= last)
688-
{
689-
return {last, std::errc::value_too_large};
690-
}
691-
692-
char* const original_first = first;
693-
694-
if (isnanq(value))
695-
{
696-
return boost::charconv::detail::to_chars_nonfinite(first, last, value, FP_NAN);
697-
}
698-
else if (isinfq(value))
699-
{
700-
return boost::charconv::detail::to_chars_nonfinite(first, last, value, FP_INFINITE);
701-
}
702-
703-
// Sanity check our bounds
704-
const std::ptrdiff_t buffer_size = last - first;
705-
auto real_precision = boost::charconv::detail::get_real_precision<__float128>(precision);
706-
if (buffer_size < real_precision || first > last)
707-
{
708-
return {last, std::errc::value_too_large};
709-
}
710-
711-
if ((fmt == boost::charconv::chars_format::general || fmt == boost::charconv::chars_format::scientific))
712-
{
713-
const auto fd128 = boost::charconv::detail::ryu::float128_to_fd128(value);
714-
const auto num_chars = boost::charconv::detail::ryu::generic_to_chars(fd128, first, last - first, fmt, precision);
667+
return boost::charconv::detail::to_chars_float_impl(first, last, value, fmt, -1);
668+
}
715669

716-
if (num_chars > 0)
717-
{
718-
return { first + num_chars, std::errc() };
719-
}
720-
else if (num_chars == -1)
721-
{
722-
return {last, std::errc::value_too_large};
723-
}
724-
}
725-
else if (fmt == boost::charconv::chars_format::hex)
670+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, __float128 value, boost::charconv::chars_format fmt, int precision) noexcept
671+
{
672+
if (precision < 0)
726673
{
727-
return boost::charconv::detail::to_chars_hex(first, last, value, precision);
674+
precision = 6;
728675
}
729-
else if (fmt == boost::charconv::chars_format::fixed)
730-
{
731-
const auto fd128 = boost::charconv::detail::ryu::float128_to_fd128(value);
732-
const auto num_chars = boost::charconv::detail::ryu::generic_to_chars_fixed(fd128, first, last - first, precision);
733676

734-
if (num_chars > 0)
735-
{
736-
return { first + num_chars, std::errc() };
737-
}
738-
else if (num_chars == -static_cast<int>(std::errc::value_too_large))
739-
{
740-
return { last, std::errc::value_too_large };
741-
}
742-
}
743-
744-
first = original_first;
745-
// Fallback to printf
746-
return boost::charconv::detail::to_chars_printf_impl(first, last, value, fmt, precision);
677+
return boost::charconv::detail::to_chars_float_impl(first, last, value, fmt, precision);
747678
}
748679

749680
#endif
750681

751682
#ifdef BOOST_CHARCONV_HAS_FLOAT16
683+
684+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, std::float16_t value,
685+
boost::charconv::chars_format fmt) noexcept
686+
{
687+
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<float>(value), fmt, -1);
688+
}
689+
752690
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, std::float16_t value,
753691
boost::charconv::chars_format fmt, int precision) noexcept
754692
{
693+
if (precision < 0)
694+
{
695+
precision = 6;
696+
}
697+
755698
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<float>(value), fmt, precision);
756699
}
757700
#endif
758701

759702
#ifdef BOOST_CHARCONV_HAS_FLOAT32
703+
704+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, std::float32_t value,
705+
boost::charconv::chars_format fmt) noexcept
706+
{
707+
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<float>(value), fmt, -1);
708+
}
709+
760710
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, std::float32_t value,
761711
boost::charconv::chars_format fmt, int precision) noexcept
762712
{
763713
static_assert(std::numeric_limits<std::float32_t>::digits == FLT_MANT_DIG &&
764714
std::numeric_limits<std::float32_t>::min_exponent == FLT_MIN_EXP,
765715
"float and std::float32_t are not the same layout like they should be");
766716

717+
if (precision < 0)
718+
{
719+
precision = 6;
720+
}
721+
767722
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<float>(value), fmt, precision);
768723
}
769724
#endif
770725

771726
#ifdef BOOST_CHARCONV_HAS_FLOAT64
727+
728+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, std::float64_t value,
729+
boost::charconv::chars_format fmt) noexcept
730+
{
731+
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<double>(value), fmt, -1);
732+
}
733+
772734
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, std::float64_t value,
773735
boost::charconv::chars_format fmt, int precision) noexcept
774736
{
775737
static_assert(std::numeric_limits<std::float64_t>::digits == DBL_MANT_DIG &&
776738
std::numeric_limits<std::float64_t>::min_exponent == DBL_MIN_EXP,
777739
"double and std::float64_t are not the same layout like they should be");
778-
740+
741+
if (precision < 0)
742+
{
743+
precision = 6;
744+
}
745+
779746
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<double>(value), fmt, precision);
780747
}
781748
#endif
782749

783750
#if defined(BOOST_CHARCONV_HAS_STDFLOAT128) && defined(BOOST_CHARCONV_HAS_FLOAT128)
751+
752+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, std::float128_t value,
753+
boost::charconv::chars_format fmt) noexcept
754+
{
755+
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<__float128>(value), fmt, -1);
756+
}
757+
784758
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, std::float128_t value,
785759
boost::charconv::chars_format fmt, int precision) noexcept
786760
{
787-
return boost::charconv::to_chars(first, last, static_cast<__float128>(value), fmt, precision);
761+
if (precision < 0)
762+
{
763+
precision = 6;
764+
}
765+
766+
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<__float128>(value), fmt, precision);
788767
}
789768
#endif
790769

791770
#ifdef BOOST_CHARCONV_HAS_BRAINFLOAT16
771+
772+
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, std::bfloat16_t value,
773+
boost::charconv::chars_format fmt) noexcept
774+
{
775+
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<float>(value), fmt, -1);
776+
}
777+
792778
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, std::bfloat16_t value,
793779
boost::charconv::chars_format fmt, int precision) noexcept
794780
{
781+
if (precision < 0)
782+
{
783+
precision = 6;
784+
}
785+
795786
return boost::charconv::detail::to_chars_float_impl(first, last, static_cast<float>(value), fmt, precision);
796787
}
797788
#endif

0 commit comments

Comments
 (0)