Skip to content

Commit 4ee8e34

Browse files
Merge pull request #688 from BartelNieuwenhuyse/bugfix/jmespath_floor-and-ceil-return-integer
JMESPath functions floor and ceil return integer
2 parents 56374a5 + c122300 commit 4ee8e34

2 files changed

Lines changed: 79 additions & 4 deletions

File tree

include/jsoncons_ext/jmespath/jmespath.hpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,9 @@ namespace detail {
12401240
template <typename Json>
12411241
class jmespath_evaluator
12421242
{
1243+
static constexpr double max_double_to_int64 = 9223372036854775807.0;
1244+
static constexpr double min_double_to_int64 = -9223372036854775808.0;
1245+
12431246
public:
12441247
typedef typename Json::char_type char_type;
12451248
typedef typename Json::char_traits_type char_traits_type;
@@ -1387,11 +1390,22 @@ namespace detail {
13871390
case json_type::uint64:
13881391
case json_type::int64:
13891392
{
1390-
return *context.create_json(arg0.template as<double>());
1393+
return arg0;
13911394
}
13921395
case json_type::float64:
13931396
{
1394-
return *context.create_json(std::ceil(arg0.template as<double>()));
1397+
auto dbl0 = arg0.template as<double>();
1398+
if (!std::isfinite(dbl0)) {
1399+
ec = jmespath_errc::invalid_type;
1400+
return context.null_value();
1401+
}
1402+
dbl0 = std::ceil(dbl0);
1403+
if (dbl0 >= min_double_to_int64 && dbl0 <= max_double_to_int64) {
1404+
return *context.create_json(static_cast<int64_t>(dbl0));
1405+
}
1406+
else {
1407+
return *context.create_json(dbl0);
1408+
}
13951409
}
13961410
default:
13971411
ec = jmespath_errc::invalid_type;
@@ -1523,11 +1537,22 @@ namespace detail {
15231537
case json_type::uint64:
15241538
case json_type::int64:
15251539
{
1526-
return *context.create_json(arg0.template as<double>());
1540+
return *context.create_json(arg0);
15271541
}
15281542
case json_type::float64:
15291543
{
1530-
return *context.create_json(std::floor(arg0.template as<double>()));
1544+
auto dbl0 = arg0.template as<double>();
1545+
if (!std::isfinite(dbl0)) {
1546+
ec = jmespath_errc::invalid_type;
1547+
return context.null_value();
1548+
}
1549+
dbl0 = std::floor(dbl0);
1550+
if (dbl0 >= min_double_to_int64 && dbl0 <= max_double_to_int64) {
1551+
return *context.create_json(static_cast<int64_t>(dbl0));
1552+
}
1553+
else {
1554+
return *context.create_json(dbl0);
1555+
}
15311556
}
15321557
default:
15331558
ec = jmespath_errc::invalid_type;

test/jmespath/input/test.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,56 @@
3737
"result": { "value": false }
3838
}
3939
]
40+
},
41+
{
42+
"given": {},
43+
"cases": [
44+
{
45+
"comment": "Floor function applied to a float should return integer",
46+
"expression": "to_string(floor(`3.7`))",
47+
"result": "3"
48+
},
49+
{
50+
"comment": "Floor function applied to a negative float should return integer",
51+
"expression": "to_string(floor(`-3.7`))",
52+
"result": "-4"
53+
},
54+
{
55+
"comment": "Floor function applied to an integer should return the same integer",
56+
"expression": "to_string(floor(`3`))",
57+
"result": "3"
58+
},
59+
{
60+
"comment": "Floor function applied to a negative integer should return the same integer",
61+
"expression": "to_string(floor(`-3`))",
62+
"result": "-3"
63+
},
64+
{
65+
"comment": "Ceil function applied to a float should return integer",
66+
"expression": "to_string(ceil(`3.7`))",
67+
"result": "4"
68+
},
69+
{
70+
"comment": "Ceil function applied to a negative float should return integer",
71+
"expression": "to_string(ceil(`-3.7`))",
72+
"result": "-3"
73+
},
74+
{
75+
"comment": "Ceil function applied to an integer should return the same integer",
76+
"expression": "to_string(ceil(`3`))",
77+
"result": "3"
78+
},
79+
{
80+
"comment": "Ceil function applied to a negative integer should return the same integer",
81+
"expression": "to_string(ceil(`-3`))",
82+
"result": "-3"
83+
},
84+
{
85+
"comment": "Ceil function applied to a large double not in int64_t range should return as double",
86+
"expression": "ceil(`1e20`)",
87+
"result": 1e20
88+
}
89+
]
4090
}
4191
]
4292

0 commit comments

Comments
 (0)