Skip to content

Commit ee8d72d

Browse files
committed
Fix value to_number warning for lossy conversion
1 parent 4e3dd6f commit ee8d72d

File tree

2 files changed

+170
-48
lines changed

2 files changed

+170
-48
lines changed

include/boost/json/detail/value.hpp

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <boost/json/kind.hpp>
1414
#include <boost/json/storage_ptr.hpp>
1515
#include <cstdint>
16+
#include <limits>
1617
#include <new>
1718
#include <utility>
1819

@@ -23,6 +24,142 @@ struct key_t
2324
{
2425
};
2526

27+
#if 0
28+
template<class T>
29+
struct to_number_limit
30+
: std::numeric_limits<T>
31+
{
32+
};
33+
34+
template<class T>
35+
struct to_number_limit<T const>
36+
: to_number_limit<T>
37+
{
38+
};
39+
40+
template<>
41+
struct to_number_limit<long long>
42+
{
43+
static constexpr long long (min)() noexcept
44+
{
45+
return -9223372036854774784;
46+
}
47+
48+
static constexpr long long (max)() noexcept
49+
{
50+
return 9223372036854774784;
51+
}
52+
};
53+
54+
template<>
55+
struct to_number_limit<unsigned long long>
56+
{
57+
static constexpr
58+
unsigned long long (min)() noexcept
59+
{
60+
return 0;
61+
}
62+
63+
static constexpr
64+
unsigned long long (max)() noexcept
65+
{
66+
return 18446744073709549568ULL;
67+
}
68+
};
69+
#else
70+
71+
template<class T>
72+
class to_number_limit
73+
{
74+
// unsigned
75+
76+
static constexpr
77+
double min1(std::false_type)
78+
{
79+
return 0.0;
80+
}
81+
82+
static constexpr
83+
double max1(std::false_type)
84+
{
85+
return max2u(std::integral_constant<
86+
bool, (std::numeric_limits<T>::max)() ==
87+
UINT64_MAX>{});
88+
}
89+
90+
static constexpr
91+
double max2u(std::false_type)
92+
{
93+
return static_cast<double>(
94+
(std::numeric_limits<T>::max)());
95+
}
96+
97+
static constexpr
98+
double max2u(std::true_type)
99+
{
100+
return 18446744073709549568.0;
101+
}
102+
103+
// signed
104+
105+
static constexpr
106+
double min1(std::true_type)
107+
{
108+
return min2s(std::integral_constant<
109+
bool, (std::numeric_limits<T>::max)() ==
110+
INT64_MAX>{});
111+
}
112+
113+
static constexpr
114+
double min2s(std::false_type)
115+
{
116+
return static_cast<double>(
117+
(std::numeric_limits<T>::min)());
118+
}
119+
120+
static constexpr
121+
double min2s(std::true_type)
122+
{
123+
return -9223372036854774784.0;
124+
}
125+
126+
static constexpr
127+
double max1(std::true_type)
128+
{
129+
return max2s(std::integral_constant<
130+
bool, (std::numeric_limits<T>::max)() ==
131+
INT64_MAX>{});
132+
}
133+
134+
static constexpr
135+
double max2s(std::false_type)
136+
{
137+
return static_cast<double>(
138+
(std::numeric_limits<T>::max)());
139+
}
140+
141+
static constexpr
142+
double max2s(std::true_type)
143+
{
144+
return 9223372036854774784.0;
145+
}
146+
147+
public:
148+
static constexpr
149+
double (min)() noexcept
150+
{
151+
return min1(std::is_signed<T>{});
152+
}
153+
154+
static constexpr
155+
double (max)() noexcept
156+
{
157+
return max1(std::is_signed<T>{});
158+
}
159+
};
160+
161+
#endif
162+
26163
struct scalar
27164
{
28165
storage_ptr sp; // must come first

include/boost/json/value.hpp

Lines changed: 33 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2423,54 +2423,47 @@ class value
24232423
! std::is_floating_point<T>::value,
24242424
T>::type
24252425
{
2426-
T result{};
24272426
if(sca_.k == json::kind::int64)
24282427
{
24292428
auto const i = sca_.i;
2430-
if( i > (std::numeric_limits<T>::max)() ||
2431-
i < (std::numeric_limits<T>::min)())
2429+
if( i >= (std::numeric_limits<T>::min)() &&
2430+
i <= (std::numeric_limits<T>::max)())
24322431
{
2433-
ec = error::not_exact;
2434-
}
2435-
else
2436-
{
2437-
result = static_cast<T>(i);
2432+
ec = {};
2433+
return static_cast<T>(i);
24382434
}
2435+
ec = error::not_exact;
24392436
}
24402437
else if(sca_.k == json::kind::uint64)
24412438
{
24422439
auto const u = sca_.u;
2443-
if(u > static_cast<std::uint64_t>((
2440+
if(u <= static_cast<std::uint64_t>((
24442441
std::numeric_limits<T>::max)()))
24452442
{
2446-
ec = error::not_exact;
2447-
}
2448-
else
2449-
{
2450-
result = static_cast<T>(u);
2443+
ec = {};
2444+
return static_cast<T>(u);
24512445
}
2446+
ec = error::not_exact;
24522447
}
24532448
else if(sca_.k == json::kind::double_)
24542449
{
24552450
auto const d = sca_.d;
2456-
if( d > static_cast<double>(
2457-
(std::numeric_limits<T>::max)()) ||
2458-
d < static_cast<double>(
2459-
(std::numeric_limits<T>::min)()) ||
2460-
static_cast<T>(d) != d)
2451+
if( d >= static_cast<double>(
2452+
(detail::to_number_limit<T>::min)()) &&
2453+
d <= static_cast<double>(
2454+
(detail::to_number_limit<T>::max)()) &&
2455+
static_cast<T>(d) == d)
24612456
{
2462-
ec = error::not_exact;
2463-
}
2464-
else
2465-
{
2466-
result = static_cast<T>(d);
2457+
ec = {};
2458+
return static_cast<T>(d);
24672459
}
2460+
ec = error::not_exact;
24682461
}
24692462
else
24702463
{
24712464
ec = error::not_number;
24722465
}
2473-
return result;
2466+
return T{};
24742467
}
24752468

24762469
template<class T>
@@ -2481,52 +2474,44 @@ class value
24812474
! std::is_same<T, bool>::value,
24822475
T>::type
24832476
{
2484-
T result{};
24852477
if(sca_.k == json::kind::int64)
24862478
{
24872479
auto const i = sca_.i;
2488-
if( i < 0 || static_cast<std::uint64_t>(i) >
2480+
if( i >= 0 && static_cast<std::uint64_t>(i) <=
24892481
(std::numeric_limits<T>::max)())
24902482
{
2491-
ec = error::not_exact;
2492-
}
2493-
else
2494-
{
2495-
result = static_cast<T>(i);
2483+
ec = {};
2484+
return static_cast<T>(i);
24962485
}
2486+
ec = error::not_exact;
24972487
}
24982488
else if(sca_.k == json::kind::uint64)
24992489
{
25002490
auto const u = sca_.u;
2501-
if(u > (std::numeric_limits<T>::max)())
2502-
{
2503-
ec = error::not_exact;
2504-
}
2505-
else
2491+
if(u <= (std::numeric_limits<T>::max)())
25062492
{
2507-
result = static_cast<T>(u);
2493+
ec = {};
2494+
return static_cast<T>(u);
25082495
}
2496+
ec = error::not_exact;
25092497
}
25102498
else if(sca_.k == json::kind::double_)
25112499
{
25122500
auto const d = sca_.d;
2513-
if( d < 0 ||
2514-
d > static_cast<double>(
2515-
(std::numeric_limits<T>::max)()) ||
2516-
static_cast<T>(d) != d)
2501+
if( d >= 0 &&
2502+
d <= (detail::to_number_limit<T>::max)() &&
2503+
static_cast<T>(d) == d)
25172504
{
2518-
ec = error::not_exact;
2519-
}
2520-
else
2521-
{
2522-
result = static_cast<T>(d);
2505+
ec = {};
2506+
return static_cast<T>(d);
25232507
}
2508+
ec = error::not_exact;
25242509
}
25252510
else
25262511
{
25272512
ec = error::not_number;
25282513
}
2529-
return result;
2514+
return T{};
25302515
}
25312516

25322517
template<class T>

0 commit comments

Comments
 (0)