Skip to content

Commit a9a8d55

Browse files
authored
Merge pull request #272 from boostorg/develop
Initial Merge for Boost 1.89
2 parents 22a7e22 + 42892ec commit a9a8d55

File tree

8 files changed

+135
-43
lines changed

8 files changed

+135
-43
lines changed

.drone.jsonnet

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ local linux_pipeline(name, image, environment, packages = "", sources = [], arch
2323
os: "linux",
2424
arch: arch
2525
},
26+
"clone": {
27+
"retries": 5
28+
},
2629
steps:
2730
[
2831
{

.github/workflows/ci.yml

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -92,27 +92,31 @@ jobs:
9292
- toolset: gcc-11
9393
cxxstd: "03,11,14,17,20,23"
9494
address_model: 32,64
95-
os: ubuntu-22.04
95+
os: ubuntu-latest
96+
container: ubuntu:22.04
9697
install:
9798
- g++-11-multilib
9899
- toolset: gcc-12
99100
cxxstd: "03,11,14,17,20,23"
100101
address_model: 32,64
101-
os: ubuntu-22.04
102+
os: ubuntu-latest
103+
container: ubuntu:22.04
102104
install:
103105
- g++-12-multilib
104106
- toolset: gcc-12
105107
cxxstd: "03-gnu,11-gnu,14-gnu,17-gnu,20-gnu,23-gnu"
106108
address_model: 32,64
107-
os: ubuntu-22.04
109+
os: ubuntu-latest
110+
container: ubuntu:22.04
108111
install:
109112
- g++-12-multilib
110113
- name: UBSAN
111114
toolset: gcc-12
112115
cxxstd: "03,11,14,17,20,23"
113116
address_model: 32,64
114117
ubsan: 1
115-
os: ubuntu-22.04
118+
os: ubuntu-latest
119+
container: ubuntu:22.04
116120
install:
117121
- g++-12-multilib
118122
- toolset: gcc-13
@@ -193,37 +197,43 @@ jobs:
193197
- toolset: clang
194198
compiler: clang++-11
195199
cxxstd: "03,11,14,17,20"
196-
os: ubuntu-22.04
200+
os: ubuntu-latest
201+
container: ubuntu:22.04
197202
install:
198203
- clang-11
199204
- toolset: clang
200205
compiler: clang++-12
201206
cxxstd: "03,11,14,17,20"
202-
os: ubuntu-22.04
207+
os: ubuntu-latest
208+
container: ubuntu:22.04
203209
install:
204210
- clang-12
205211
- toolset: clang
206212
compiler: clang++-13
207213
cxxstd: "03,11,14,17,20"
208-
os: ubuntu-22.04
214+
os: ubuntu-latest
215+
container: ubuntu:22.04
209216
install:
210217
- clang-13
211218
- toolset: clang
212219
compiler: clang++-14
213220
cxxstd: "03,11,14,17,20"
214-
os: ubuntu-22.04
221+
os: ubuntu-latest
222+
container: ubuntu:22.04
215223
install:
216224
- clang-14
217225
- toolset: clang
218226
compiler: clang++-14
219227
cxxstd: "03-gnu,11-gnu,14-gnu,17-gnu,20-gnu"
220-
os: ubuntu-22.04
228+
os: ubuntu-latest
229+
container: ubuntu:22.04
221230
install:
222231
- clang-14
223232
- toolset: clang
224233
compiler: clang++-15
225234
cxxstd: "03,11,14,17,20"
226-
os: ubuntu-22.04
235+
os: ubuntu-latest
236+
container: ubuntu:22.04
227237
install:
228238
- clang-15
229239
sources:
@@ -233,7 +243,8 @@ jobs:
233243
- toolset: clang
234244
compiler: clang++-15
235245
cxxstd: "03,11,14,17,20,2b"
236-
os: ubuntu-22.04
246+
os: ubuntu-latest
247+
container: ubuntu:22.04
237248
install:
238249
- clang-15
239250
- libc++-15-dev
@@ -247,7 +258,8 @@ jobs:
247258
- toolset: clang
248259
compiler: clang++-16
249260
cxxstd: "03,11,14,17,20,2b"
250-
os: ubuntu-22.04
261+
os: ubuntu-latest
262+
container: ubuntu:22.04
251263
install:
252264
- clang-16
253265
sources:
@@ -257,7 +269,8 @@ jobs:
257269
- toolset: clang
258270
compiler: clang++-17
259271
cxxstd: "03,11,14,17,20,2b"
260-
os: ubuntu-22.04
272+
os: ubuntu-latest
273+
container: ubuntu:22.04
261274
install:
262275
- clang-17
263276
sources:
@@ -271,7 +284,8 @@ jobs:
271284
cxxflags: -stdlib=libc++
272285
linkflags: -stdlib=libc++
273286
ubsan: 1
274-
os: ubuntu-22.04
287+
os: ubuntu-latest
288+
container: ubuntu:22.04
275289
install:
276290
- clang-14
277291
- libc++-14-dev
@@ -502,26 +516,18 @@ jobs:
502516
fail-fast: false
503517
matrix:
504518
include:
505-
- toolset: msvc-14.0
506-
cxxstd: "14,latest"
507-
addrmd: 32,64
508-
os: windows-2019
509-
- toolset: msvc-14.2
510-
cxxstd: "14,17,20,latest"
511-
addrmd: 32,64
512-
os: windows-2019
513519
- toolset: msvc-14.3
514520
cxxstd: "14,17,20,latest"
515521
addrmd: 32,64
516522
os: windows-2022
517523
- toolset: clang-win
518524
cxxstd: "14,17,latest"
519525
addrmd: 32,64
520-
os: windows-2022
526+
os: windows-latest
521527
- toolset: gcc
522528
cxxstd: "03,11,14,17,2a"
523529
addrmd: 64
524-
os: windows-2019
530+
os: windows-latest
525531

526532
runs-on: ${{matrix.os}}
527533

@@ -561,7 +567,6 @@ jobs:
561567
fail-fast: false
562568
matrix:
563569
include:
564-
- os: ubuntu-22.04
565570
- os: ubuntu-24.04
566571
- os: macos-13
567572
- os: macos-14
@@ -610,7 +615,6 @@ jobs:
610615
fail-fast: false
611616
matrix:
612617
include:
613-
- os: ubuntu-22.04
614618
- os: ubuntu-24.04
615619
- os: macos-13
616620
- os: macos-14
@@ -669,7 +673,6 @@ jobs:
669673
fail-fast: false
670674
matrix:
671675
include:
672-
- os: ubuntu-22.04
673676
- os: ubuntu-24.04
674677
- os: macos-13
675678
- os: macos-14

include/boost/charconv/detail/dragonbox/floff.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,7 @@ BOOST_CHARCONV_SAFEBUFFERS to_chars_result floff(const double x, int precision,
13331333

13341334
auto buffer_size = static_cast<std::size_t>(last - first);
13351335
auto buffer = first;
1336+
bool trailing_zeros_removed = false;
13361337

13371338
BOOST_CHARCONV_ASSERT(precision >= 0);
13381339
using namespace detail;
@@ -3849,6 +3850,7 @@ BOOST_CHARCONV_SAFEBUFFERS to_chars_result floff(const double x, int precision,
38493850
}
38503851

38513852
// Remove trailing zeros.
3853+
trailing_zeros_removed = true;
38523854
while (true)
38533855
{
38543856
auto prev = buffer - 1;
@@ -3903,7 +3905,16 @@ BOOST_CHARCONV_SAFEBUFFERS to_chars_result floff(const double x, int precision,
39033905
print_2_digits(static_cast<std::uint32_t>(decimal_exponent_normalized), buffer);
39043906
buffer += 2;
39053907
}
3906-
}
3908+
}
3909+
else if (!trailing_zeros_removed && buffer - (decimal_dot_pos + 1) < precision)
3910+
{
3911+
// If we have fixed precision, and we don't have enough digits after the decimal yet
3912+
// insert a sufficient amount of zeros
3913+
const auto remaining_zeros = precision - (buffer - (decimal_dot_pos + 1));
3914+
BOOST_CHARCONV_ASSERT(remaining_zeros > 0);
3915+
std::memset(buffer, '0', static_cast<std::size_t>(remaining_zeros));
3916+
buffer += remaining_zeros;
3917+
}
39073918

39083919
return {buffer, std::errc()};
39093920

@@ -4018,9 +4029,10 @@ BOOST_CHARCONV_SAFEBUFFERS to_chars_result floff(const double x, int precision,
40184029
++decimal_dot_pos;
40194030
}
40204031
}
4021-
else if (decimal_exponent_normalized == 0)
4032+
else if (decimal_exponent_normalized == 0 || remaining_digits == 1)
40224033
{
40234034
// For the case 0.99...9 -> 1.00...0, the rounded digit is one before the first digit written.
4035+
// This same case applies for 0.099 -> 0.10 in the precision = 2 instance
40244036
// Note: decimal_exponent_normalized was negative before the increment (++decimal_exponent_normalized),
40254037
// so we already have printed "00" onto the buffer.
40264038
// Hence, --digit_starting_pos doesn't go more than the starting position of the buffer.

include/boost/charconv/detail/from_chars_integer_impl.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ constexpr unsigned char digit_from_char(char val) noexcept
9393
# pragma warning(push)
9494
# pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned
9595
# pragma warning(disable: 4189) // 'is_negative': local variable is initialized but not referenced
96-
96+
# pragma warning(disable: 4127) // Conditional expression is constant (if constexpr pre-c++17)
9797
#elif defined(__clang__)
9898
# pragma clang diagnostic push
9999
# pragma clang diagnostic ignored "-Wconstant-conversion"
@@ -186,8 +186,11 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs
186186
}
187187
}
188188

189-
#ifdef BOOST_CHARCONV_HAS_INT128
190-
BOOST_IF_CONSTEXPR (std::is_same<Integer, boost::int128_type>::value)
189+
BOOST_IF_CONSTEXPR ((std::numeric_limits<Integer>::is_signed && sizeof(Integer) == 16)
190+
#ifdef BOOST_CHARCONV_HAS_INT128
191+
|| std::is_same<boost::int128_type, Integer>::value
192+
#endif
193+
)
191194
{
192195
overflow_value /= unsigned_base;
193196
max_digit %= unsigned_base;
@@ -200,7 +203,6 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs
200203
#endif
201204
}
202205
else
203-
#endif
204206
{
205207
overflow_value /= unsigned_base;
206208
max_digit %= unsigned_base;

include/boost/charconv/detail/to_chars_integer_impl.hpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -214,15 +214,13 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char
214214
// to extract the digits
215215
//
216216
// See: https://quuxplusone.github.io/blog/2019/02/28/is-int128-integral/
217-
template <typename Integer>
217+
#ifdef BOOST_CHARCONV_HAS_INT128
218+
template <typename Integer, typename Unsigned_Integer = boost::uint128_type>
219+
#else
220+
template <typename Integer, typename Unsigned_Integer = uint128>
221+
#endif
218222
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, char* last, Integer value) noexcept
219223
{
220-
#ifdef BOOST_CHARCONV_HAS_INT128
221-
using Unsigned_Integer = boost::uint128_type;
222-
#else
223-
using Unsigned_Integer = uint128;
224-
#endif
225-
226224
Unsigned_Integer unsigned_value {};
227225

228226
const std::ptrdiff_t user_buffer_size = last - first;
@@ -234,8 +232,11 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c
234232
}
235233

236234
// Strip the sign from the value and apply at the end after parsing if the type is signed
237-
#ifdef BOOST_CHARCONV_HAS_INT128
238-
BOOST_IF_CONSTEXPR (std::is_same<boost::int128_type, Integer>::value)
235+
BOOST_IF_CONSTEXPR (std::numeric_limits<Integer>::is_signed
236+
#ifdef BOOST_CHARCONV_HAS_INT128
237+
|| std::is_same<boost::int128_type, Integer>::value
238+
#endif
239+
)
239240
{
240241
if (value < 0)
241242
{
@@ -248,7 +249,6 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c
248249
}
249250
}
250251
else
251-
#endif
252252
{
253253
unsigned_value = static_cast<Unsigned_Integer>(value);
254254
}

test/Jamfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,5 @@ run github_issue_166.cpp ;
7070
run github_issue_166_float128.cpp ;
7171
run github_issue_186.cpp ;
7272
run github_issue_212.cpp ;
73+
run github_issue_266.cpp ;
74+
run github_issue_267.cpp ;

test/github_issue_266.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
// See: https://github.com/boostorg/charconv/issues/266
6+
7+
#include <boost/charconv.hpp>
8+
#include <boost/core/lightweight_test.hpp>
9+
10+
template <typename T>
11+
void test(T value, int precision, const char* correct_result)
12+
{
13+
char buffer[64] {};
14+
const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), value, boost::charconv::chars_format::fixed, precision);
15+
BOOST_TEST_CSTR_EQ(buffer, correct_result);
16+
BOOST_TEST(r);
17+
}
18+
19+
int main()
20+
{
21+
test(123456789012345.6789012345678901, 5, "123456789012345.67188");
22+
test(1234567890123456.789012345678901, 5, "1234567890123456.75000");
23+
test(12345678901234567.89012345678901, 5, "12345678901234568.00000");
24+
test(123456789012345678.9012345678901, 5, "123456789012345680.00000");
25+
test(1234567890123456789.012345678901, 5, "1234567890123456768.00000");
26+
27+
test(123456789012345678901234567.8901, 5, "123456789012345678152597504.00000");
28+
test(12345678901234567890123456.78901, 5, "12345678901234568244756480.00000");
29+
test(1234567890123456789012345.678901, 5, "1234567890123456824475648.00000");
30+
test(123456789012345678901234.5678901, 5, "123456789012345685803008.00000");
31+
test(12345678901234567890123.45678901, 5, "12345678901234567741440.00000");
32+
test(123456789012345678901.2345678901, 5, "123456789012345683968.00000");
33+
34+
return boost::report_errors();
35+
}

test/github_issue_267.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
// See: https://github.com/boostorg/charconv/issues/267
6+
7+
#include <boost/charconv.hpp>
8+
#include <boost/core/lightweight_test.hpp>
9+
10+
template <typename T>
11+
void test(T value, int precision, const char* correct_result)
12+
{
13+
char buffer[64] {};
14+
const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), value, boost::charconv::chars_format::fixed, precision);
15+
BOOST_TEST_CSTR_EQ(buffer, correct_result);
16+
BOOST_TEST(r);
17+
}
18+
19+
int main()
20+
{
21+
test(0.09, 2, "0.09");
22+
test(0.099, 2, "0.10");
23+
test(0.0999, 2, "0.10");
24+
test(0.09999, 2, "0.10");
25+
test(0.099999, 2, "0.10");
26+
test(0.0999999, 2, "0.10");
27+
test(0.09999999, 2, "0.10");
28+
test(0.099999999, 2, "0.10");
29+
test(0.0999999999, 2, "0.10");
30+
test(0.09999999999, 2, "0.10");
31+
test(0.099999999999, 2, "0.10");
32+
test(0.0999999999999, 2, "0.10");
33+
34+
return boost::report_errors();
35+
}

0 commit comments

Comments
 (0)