Skip to content

Commit d6c9c3e

Browse files
authored
Merge pull request #1227 from cppalliance/charconv_limits
2 parents 84ee07e + 67ce073 commit d6c9c3e

File tree

8 files changed

+115
-23
lines changed

8 files changed

+115
-23
lines changed

doc/modules/ROOT/pages/charconv.adoc

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,25 +159,41 @@ IMPORTANT: Same as `from_chars`, `boost::decimal::to_chars` will return a `std::
159159
The library offers an additional feature for sizing buffers without specified precision and in general format
160160

161161
[#charconv_limits]
162-
== limits
162+
== Formatting Limits
163163
[source, c++]
164164
----
165165
#include <boost/decimal/charconv.hpp>
166166
167167
namespace boost {
168168
namespace decimal {
169169
170-
template <typename T>
171-
struct limits
170+
template <typename DecimalType, int Precision = std::numeric_limits<DecimalType>::max_digits10>
171+
class formatting_limits
172172
{
173-
static constexpr int max_chars;
174-
}
173+
public:
174+
175+
static constexpr std::size_t scientific_format_max_chars;
176+
177+
static constexpr std::size_t fixed_format_max_chars;
178+
179+
static constexpr std::size_t hex_format_max_chars;
180+
181+
static constexpr std::size_t cohort_preserving_scientific_max_chars;
182+
183+
static constexpr std::size_t general_format_max_chars;
184+
185+
static constexpr std::size_t max_chars;
186+
};
175187
176188
} //namespace decimal
177189
} //namespace boost
178190
----
179191

180-
The member can then be used to size buffers such as:
192+
This class allows you to size buffers for `to_chars` without have to arbitrarily guess what size you need it to be.
193+
The `Precision` is defaulted to the maximum precision of the type, which is the same assumption that is made when you use `to_chars` with an unspecified precision.
194+
The `max_chars` variable is the largest of the 5 specified `chars_format` options.
195+
196+
The members can then be used to size buffers such as:
181197

182198
[source, c++]
183199
----
@@ -190,7 +206,7 @@ int main()
190206
191207
decimal32_t val {5, -1};
192208
193-
char buffer[limits<decimal32_t>::max_chars];
209+
char buffer[formatting_limits<decimal32_t>::max_chars];
194210
195211
auto r_to = to_chars(buffer, buffer + sizeof(buffer), val);
196212
*r_to.ptr = '\0';

include/boost/decimal/charconv.hpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <boost/decimal/detail/remove_trailing_zeros.hpp>
2828
#include <boost/decimal/detail/promotion.hpp>
2929
#include <boost/decimal/detail/write_payload.hpp>
30+
#include <boost/decimal/detail/formatting_limits.hpp>
3031

3132
#ifndef BOOST_DECIMAL_BUILD_MODULE
3233
#include <cstdint>
@@ -1393,18 +1394,6 @@ constexpr auto to_chars(char* first, char* last, DecimalType value, std::chars_f
13931394

13941395
#endif // BOOST_DECIMAL_HAS_STD_CHARCONV
13951396

1396-
BOOST_DECIMAL_EXPORT template <typename T>
1397-
struct limits
1398-
{
1399-
static constexpr int max_chars = boost::decimal::detail::max_string_length_v<T>;
1400-
};
1401-
1402-
#if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900)
1403-
1404-
template <typename T> constexpr int limits<T>::max_chars;
1405-
1406-
#endif
1407-
14081397
} //namespace decimal
14091398
} //namespace boost
14101399

include/boost/decimal/detail/buffer_sizing.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ constexpr int get_real_precision(const int my_precision = -1) noexcept
3030
return my_precision == -1 ? std::numeric_limits<Dec>::max_digits10 : my_precision;
3131
}
3232

33-
// We don't need to use the full digit counting since the range of the exponents is well defined
33+
// We don't need to use the full digit counting since the range of the exponents is well-defined
3434
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType, BOOST_DECIMAL_INTEGRAL Int>
3535
constexpr auto buffer_length_exp(Int x) noexcept -> std::enable_if_t<std::numeric_limits<DecimalType>::max_exponent >= 1000, int>
3636
{
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2025 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#ifndef BOOST_DECIMAL_DETAIL_FORMATTING_LIMITS_HPP
6+
#define BOOST_DECIMAL_DETAIL_FORMATTING_LIMITS_HPP
7+
8+
#include <boost/decimal/detail/config.hpp>
9+
#include <boost/decimal/detail/concepts.hpp>
10+
#include <boost/decimal/detail/buffer_sizing.hpp>
11+
#include <boost/decimal/detail/chars_format.hpp>
12+
#include <boost/decimal/detail/attributes.hpp>
13+
14+
namespace boost {
15+
namespace decimal {
16+
17+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType, int Precision = -1>
18+
class formatting_limits
19+
{
20+
private:
21+
22+
// Fix format removes the e+/e-
23+
static constexpr std::size_t fixed_format_offset {2U};
24+
25+
static constexpr std::size_t required_characters() noexcept
26+
{
27+
static_assert(Precision > 0 || Precision == -1, "A specified precision must be greater than zero");
28+
29+
const auto local_precision {detail::get_real_precision<DecimalType>(Precision)};
30+
return detail::total_buffer_length<DecimalType>(local_precision, detail::max_biased_exp_v<DecimalType>, true);
31+
}
32+
33+
public:
34+
35+
static constexpr std::size_t scientific_format_max_chars {required_characters()};
36+
37+
static constexpr std::size_t fixed_format_max_chars { scientific_format_max_chars - fixed_format_offset };
38+
39+
static constexpr std::size_t hex_format_max_chars { scientific_format_max_chars };
40+
41+
static constexpr std::size_t cohort_preserving_scientific_max_chars { scientific_format_max_chars };
42+
43+
static constexpr std::size_t general_format_max_chars { scientific_format_max_chars };
44+
45+
static constexpr std::size_t max_chars { scientific_format_max_chars };
46+
};
47+
48+
#if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900)
49+
50+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType, int Precision>
51+
constexpr std::size_t formatting_limits<DecimalType, Precision>::scientific_format_max_chars;
52+
53+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType, int Precision>
54+
constexpr std::size_t formatting_limits<DecimalType, Precision>::fixed_format_max_chars;
55+
56+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType, int Precision>
57+
constexpr std::size_t formatting_limits<DecimalType, Precision>::hex_format_max_chars;
58+
59+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType, int Precision>
60+
constexpr std::size_t formatting_limits<DecimalType, Precision>::cohort_preserving_scientific_max_chars;
61+
62+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType, int Precision>
63+
constexpr std::size_t formatting_limits<DecimalType, Precision>::general_format_max_chars;
64+
65+
#endif
66+
67+
} // namespace decimal
68+
} // namespace boost
69+
70+
#endif // BOOST_DECIMAL_DETAIL_FORMATTING_LIMITS_HPP

test/limits_link_1.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@
77
#include <limits>
88

99
void test_odr_use( int const* );
10+
void test_odr_use( std::size_t const* );
1011

1112
template<typename T> void test()
1213
{
13-
test_odr_use( &boost::decimal::limits<T>::max_chars );
14+
test_odr_use( &boost::decimal::formatting_limits<T>::scientific_format_max_chars );
15+
test_odr_use( &boost::decimal::formatting_limits<T>::fixed_format_max_chars );
16+
test_odr_use( &boost::decimal::formatting_limits<T>::hex_format_max_chars );
17+
test_odr_use( &boost::decimal::formatting_limits<T>::cohort_preserving_scientific_max_chars );
18+
test_odr_use( &boost::decimal::formatting_limits<T>::general_format_max_chars );
1419
test_odr_use( &std::numeric_limits<T>::digits10 );
1520
}
1621

test/limits_link_2.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@
77
#include <limits>
88

99
void test_odr_use( int const* );
10+
void test_odr_use( std::size_t const* );
1011

1112
template<typename T> void test()
1213
{
13-
test_odr_use( &boost::decimal::limits<T>::max_chars );
14+
test_odr_use( &boost::decimal::formatting_limits<T>::scientific_format_max_chars );
15+
test_odr_use( &boost::decimal::formatting_limits<T>::fixed_format_max_chars );
16+
test_odr_use( &boost::decimal::formatting_limits<T>::hex_format_max_chars );
17+
test_odr_use( &boost::decimal::formatting_limits<T>::cohort_preserving_scientific_max_chars );
18+
test_odr_use( &boost::decimal::formatting_limits<T>::general_format_max_chars );
1419
test_odr_use( &std::numeric_limits<T>::digits10 );
1520
}
1621

test/limits_link_3.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// Copyright 2023 Peter Dimov
2+
// Copyright 2025 Matt Borland
23
// Distributed under the Boost Software License, Version 1.0.
34
// https://www.boost.org/LICENSE_1_0.txt
45

6+
#include <cstddef>
7+
58
void f1();
69
void f2();
710

@@ -14,3 +17,7 @@ int main()
1417
void test_odr_use( int const* )
1518
{
1619
}
20+
21+
void test_odr_use ( std::size_t const* )
22+
{
23+
}

test/test_to_chars.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void test_value(T val, const char* result, chars_format fmt)
5959
template <typename T>
6060
void test_value(T val, const char* result)
6161
{
62-
char buffer[boost::decimal::limits<T>::max_chars] {};
62+
char buffer[formatting_limits<T>::max_chars] {};
6363
auto r = to_chars(buffer, buffer + sizeof(buffer), val, chars_format::general);
6464
*r.ptr = '\0';
6565
BOOST_TEST(r);

0 commit comments

Comments
 (0)