| 1 | // |
| 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) |
| 3 | // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com) |
| 4 | // |
| 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 7 | // |
| 8 | // Official repository: https://github.com/boostorg/json |
| 9 | // |
| 10 | |
| 11 | #include <boost/json/stream_parser.hpp> |
| 12 | #include <boost/json/parse.hpp> |
| 13 | #include <boost/json/serialize.hpp> |
| 14 | |
| 15 | #include <iostream> |
| 16 | #include <random> |
| 17 | #include <cinttypes> |
| 18 | |
| 19 | #include "parse-vectors.hpp" |
| 20 | #include "test.hpp" |
| 21 | #include "test_suite.hpp" |
| 22 | |
| 23 | namespace boost { |
| 24 | namespace json { |
| 25 | |
| 26 | template<std::size_t N, class... Args> |
| 27 | void |
| 28 | sprintf(char (&buf)[N], |
| 29 | char const* format, Args&&... args) |
| 30 | { |
| 31 | #ifdef _MSC_VER |
| 32 | sprintf_s(buf, format, |
| 33 | std::forward<Args>(args)...); |
| 34 | #else |
| 35 | std::snprintf(s: buf, maxlen: N, format: format, |
| 36 | std::forward<Args>(args)...); |
| 37 | #endif |
| 38 | } |
| 39 | |
| 40 | class double_test |
| 41 | { |
| 42 | public: |
| 43 | struct f_boost |
| 44 | { |
| 45 | static |
| 46 | string_view |
| 47 | name() noexcept |
| 48 | { |
| 49 | return "boost" ; |
| 50 | } |
| 51 | |
| 52 | double |
| 53 | operator()(string_view s, parse_options const& po = {}) const |
| 54 | { |
| 55 | BOOST_TEST_CHECKPOINT(); |
| 56 | system::error_code ec; |
| 57 | stream_parser p({}, po); |
| 58 | p.write(data: s.data(), size: s.size(), ec); |
| 59 | if(BOOST_TEST(! ec)) |
| 60 | p.finish(ec); |
| 61 | if(! BOOST_TEST(! ec)) |
| 62 | return 0; |
| 63 | auto const jv = p.release(); |
| 64 | double const d = jv.as_double(); |
| 65 | grind_double(s, v: d, po); |
| 66 | return d; |
| 67 | } |
| 68 | }; |
| 69 | |
| 70 | bool |
| 71 | within_1ulp(double x, double y) |
| 72 | { |
| 73 | std::uint64_t bx, by; |
| 74 | std::memcpy(dest: &bx, src: &x, n: sizeof(x)); |
| 75 | std::memcpy(dest: &by, src: &y, n: sizeof(y)); |
| 76 | |
| 77 | auto diff = bx - by; |
| 78 | switch (diff) |
| 79 | { |
| 80 | case 0: |
| 81 | case 1: |
| 82 | case 0xffffffffffffffff: |
| 83 | return true; |
| 84 | default: |
| 85 | break; |
| 86 | } |
| 87 | return false; |
| 88 | } |
| 89 | |
| 90 | static |
| 91 | value |
| 92 | from_string_test( |
| 93 | string_view s, |
| 94 | storage_ptr sp = {}, |
| 95 | const parse_options& po = parse_options()) |
| 96 | { |
| 97 | stream_parser p(storage_ptr(), po); |
| 98 | system::error_code ec; |
| 99 | p.reset(sp: std::move(sp)); |
| 100 | p.write(data: s.data(), size: s.size(), ec); |
| 101 | if(BOOST_TEST(! ec)) |
| 102 | p.finish(ec); |
| 103 | BOOST_TEST(! ec); |
| 104 | return p.release(); |
| 105 | } |
| 106 | |
| 107 | void |
| 108 | static |
| 109 | check_round_trip(value const& jv1, |
| 110 | const parse_options& po = parse_options()) |
| 111 | { |
| 112 | auto const s2 = |
| 113 | //to_string_test(jv1); // use this if serializer is broken |
| 114 | serialize(t: jv1); |
| 115 | auto jv2 = |
| 116 | from_string_test(s: s2, sp: {}, po); |
| 117 | BOOST_TEST(equal(jv1, jv2)); |
| 118 | } |
| 119 | |
| 120 | template<class F> |
| 121 | void |
| 122 | static |
| 123 | grind_one( |
| 124 | string_view s, |
| 125 | storage_ptr sp, |
| 126 | F const& f, |
| 127 | const parse_options& po = parse_options()) |
| 128 | { |
| 129 | auto const jv = |
| 130 | from_string_test(s, sp, po); |
| 131 | f(jv, po); |
| 132 | } |
| 133 | |
| 134 | static |
| 135 | void |
| 136 | grind_one(string_view s) |
| 137 | { |
| 138 | auto const jv = |
| 139 | from_string_test(s); |
| 140 | check_round_trip(jv1: jv); |
| 141 | } |
| 142 | |
| 143 | template<class F> |
| 144 | static |
| 145 | void |
| 146 | grind(string_view s, F const& f, |
| 147 | const parse_options& po = parse_options()) |
| 148 | { |
| 149 | try |
| 150 | { |
| 151 | grind_one(s, {}, f, po); |
| 152 | |
| 153 | fail_loop([&](storage_ptr const& sp) |
| 154 | { |
| 155 | grind_one(s, sp, f, po); |
| 156 | }); |
| 157 | |
| 158 | if(s.size() > 1) |
| 159 | { |
| 160 | // Destroy the stream_parser at every |
| 161 | // split point to check leaks. |
| 162 | for(std::size_t i = 1; |
| 163 | i < s.size(); ++i) |
| 164 | { |
| 165 | fail_resource mr; |
| 166 | mr.fail_max = 0; |
| 167 | stream_parser p(storage_ptr(), po); |
| 168 | system::error_code ec; |
| 169 | p.reset(sp: &mr); |
| 170 | p.write(data: s.data(), size: i, ec); |
| 171 | if(BOOST_TEST(! ec)) |
| 172 | p.write( |
| 173 | data: s.data() + i, |
| 174 | size: s.size() - i, ec); |
| 175 | if(BOOST_TEST(! ec)) |
| 176 | p.finish(ec); |
| 177 | if(BOOST_TEST(! ec)) |
| 178 | f(p.release(), po); |
| 179 | } |
| 180 | } |
| 181 | } |
| 182 | catch(std::exception const&) |
| 183 | { |
| 184 | BOOST_TEST_FAIL(); |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | static |
| 189 | void |
| 190 | grind(string_view s, |
| 191 | const parse_options& po = parse_options()) |
| 192 | { |
| 193 | grind(s, |
| 194 | f: [](value const& jv, const parse_options& po) |
| 195 | { |
| 196 | check_round_trip(jv1: jv, po); |
| 197 | }, po); |
| 198 | } |
| 199 | |
| 200 | static |
| 201 | void |
| 202 | grind_double(string_view s, double v, parse_options const& po = {}) |
| 203 | { |
| 204 | grind(s, |
| 205 | f: [v](value const& jv, const parse_options&) |
| 206 | { |
| 207 | if(! BOOST_TEST(jv.is_double())) |
| 208 | return; |
| 209 | if( std::isnan(x: v) ) |
| 210 | BOOST_TEST( std::isnan( jv.get_double() ) ); |
| 211 | else |
| 212 | BOOST_TEST( jv.get_double() == v ); |
| 213 | }, |
| 214 | po); |
| 215 | } |
| 216 | |
| 217 | // Verify that f converts to the |
| 218 | // same double produced by `strtod`. |
| 219 | // Requires `s` is not represented by an integral type. |
| 220 | template<class F> |
| 221 | void |
| 222 | fc(std::string const& s, F const& f) |
| 223 | { |
| 224 | char* str_end; |
| 225 | double const need = |
| 226 | std::strtod(nptr: s.c_str(), endptr: &str_end); |
| 227 | // BOOST_TEST(str_end == &s.back() + 1); |
| 228 | for (bool is_precise: {false, true}) |
| 229 | { |
| 230 | parse_options po; |
| 231 | po.numbers = is_precise ? |
| 232 | number_precision::precise : number_precision::imprecise; |
| 233 | double const got = f(s, po); |
| 234 | auto same = got == need; |
| 235 | auto close = same ? |
| 236 | true : within_1ulp(x: got, y: need); |
| 237 | |
| 238 | if( !BOOST_TEST(close) ) |
| 239 | { |
| 240 | std::cerr << "Failure on '" << s << "' (" |
| 241 | << (is_precise? "precise" : "imprecise" ) << "): " |
| 242 | << got << " != " << need << "\n" ; |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | // test that number_precision::none works |
| 247 | parse_options po; |
| 248 | po.numbers = number_precision::none; |
| 249 | double const got = f(s, po); |
| 250 | (void)got; |
| 251 | } |
| 252 | |
| 253 | void |
| 254 | fc(std::string const& s) |
| 255 | { |
| 256 | fc(s, f: f_boost{}); |
| 257 | fc(s: s + std::string( 64, ' ' ), f: f_boost{}); |
| 258 | } |
| 259 | |
| 260 | void |
| 261 | testDouble() |
| 262 | { |
| 263 | grind_double(s: "-1.010" , v: -1.01); |
| 264 | grind_double(s: "-0.010" , v: -0.01); |
| 265 | grind_double(s: "-0.0" , v: -0.0); |
| 266 | grind_double(s: "-0e0" , v: -0.0); |
| 267 | grind_double( s: "18.4" , v: 18.4); |
| 268 | grind_double(s: "-18.4" , v: -18.4); |
| 269 | grind_double( s: "18446744073709551616" , v: 1.8446744073709552e+19); |
| 270 | grind_double(s: "-18446744073709551616" , v: -1.8446744073709552e+19); |
| 271 | grind_double( s: "18446744073709551616.0" , v: 1.8446744073709552e+19); |
| 272 | grind_double( s: "18446744073709551616.00009" , v: 1.8446744073709552e+19); |
| 273 | grind_double( s: "1844674407370955161600000" , v: 1.8446744073709552e+24); |
| 274 | grind_double(s: "-1844674407370955161600000" , v: -1.8446744073709552e+24); |
| 275 | grind_double( s: "1844674407370955161600000.0" , v: 1.8446744073709552e+24); |
| 276 | grind_double( s: "1844674407370955161600000.00009" , v: 1.8446744073709552e+24); |
| 277 | grind_double( s: "19700720435664.186294290058937593e13" , v: 1.9700720435664185e+26); |
| 278 | |
| 279 | grind_double( s: "1.0" , v: 1.0); |
| 280 | grind_double( s: "1.1" , v: 1.1); |
| 281 | grind_double( s: "1.11" , v: 1.11); |
| 282 | grind_double( s: "1.11111" , v: 1.11111); |
| 283 | grind_double( s: "11.1111" , v: 11.1111); |
| 284 | grind_double( s: "111.111" , v: 111.111); |
| 285 | |
| 286 | fc(s: "-0.9999999999999999999999" ); |
| 287 | fc(s: "-0.9999999999999999" ); |
| 288 | fc(s: "-0.9007199254740991" ); |
| 289 | fc(s: "-0.999999999999999" ); |
| 290 | fc(s: "-0.99999999999999" ); |
| 291 | fc(s: "-0.9999999999999" ); |
| 292 | fc(s: "-0.999999999999" ); |
| 293 | fc(s: "-0.99999999999" ); |
| 294 | fc(s: "-0.9999999999" ); |
| 295 | fc(s: "-0.999999999" ); |
| 296 | fc(s: "-0.99999999" ); |
| 297 | fc(s: "-0.9999999" ); |
| 298 | fc(s: "-0.999999" ); |
| 299 | fc(s: "-0.99999" ); |
| 300 | fc(s: "-0.9999" ); |
| 301 | fc(s: "-0.8125" ); |
| 302 | fc(s: "-0.999" ); |
| 303 | fc(s: "-0.99" ); |
| 304 | fc(s: "-1.0" ); |
| 305 | fc(s: "-0.9" ); |
| 306 | fc(s: "-0.0" ); |
| 307 | fc(s: "0.0" ); |
| 308 | fc(s: "0.9" ); |
| 309 | fc(s: "0.99" ); |
| 310 | fc(s: "0.999" ); |
| 311 | fc(s: "0.8125" ); |
| 312 | fc(s: "0.9999" ); |
| 313 | fc(s: "0.99999" ); |
| 314 | fc(s: "0.999999" ); |
| 315 | fc(s: "0.9999999" ); |
| 316 | fc(s: "0.99999999" ); |
| 317 | fc(s: "0.999999999" ); |
| 318 | fc(s: "0.9999999999" ); |
| 319 | fc(s: "0.99999999999" ); |
| 320 | fc(s: "0.999999999999" ); |
| 321 | fc(s: "0.9999999999999" ); |
| 322 | fc(s: "0.99999999999999" ); |
| 323 | fc(s: "0.999999999999999" ); |
| 324 | fc(s: "0.9007199254740991" ); |
| 325 | fc(s: "0.9999999999999999" ); |
| 326 | fc(s: "0.9999999999999999999999" ); |
| 327 | fc(s: "0.999999999999999999999999999" ); |
| 328 | |
| 329 | fc(s: "-1e308" ); |
| 330 | fc(s: "-1e-308" ); |
| 331 | fc(s: "-9999e300" ); |
| 332 | fc(s: "-999e100" ); |
| 333 | fc(s: "-99e10" ); |
| 334 | fc(s: "-9e1" ); |
| 335 | fc(s: "9e1" ); |
| 336 | fc(s: "99e10" ); |
| 337 | fc(s: "999e100" ); |
| 338 | fc(s: "9999e300" ); |
| 339 | fc(s: "999999999999999999.0" ); |
| 340 | fc(s: "999999999999999999999.0" ); |
| 341 | fc(s: "999999999999999999999e5" ); |
| 342 | fc(s: "999999999999999999999.0e5" ); |
| 343 | |
| 344 | fc(s: "0.00000000000000001" ); |
| 345 | |
| 346 | fc(s: "-1e-1" ); |
| 347 | fc(s: "-1e0" ); |
| 348 | fc(s: "-1e1" ); |
| 349 | fc(s: "0e0" ); |
| 350 | fc(s: "1e0" ); |
| 351 | fc(s: "1e10" ); |
| 352 | |
| 353 | fc(s: "0." |
| 354 | "00000000000000000000000000000000000000000000000000" // 50 zeroes |
| 355 | "1e50" ); |
| 356 | fc(s: "-0." |
| 357 | "00000000000000000000000000000000000000000000000000" // 50 zeroes |
| 358 | "1e50" ); |
| 359 | |
| 360 | fc(s: "0." |
| 361 | "00000000000000000000000000000000000000000000000000" |
| 362 | "00000000000000000000000000000000000000000000000000" |
| 363 | "00000000000000000000000000000000000000000000000000" |
| 364 | "00000000000000000000000000000000000000000000000000" |
| 365 | "00000000000000000000000000000000000000000000000000" |
| 366 | "00000000000000000000000000000000000000000000000000" |
| 367 | "00000000000000000000000000000000000000000000000000" |
| 368 | "00000000000000000000000000000000000000000000000000" |
| 369 | "00000000000000000000000000000000000000000000000000" |
| 370 | "00000000000000000000000000000000000000000000000000" // 500 zeroes |
| 371 | "1e600" ); |
| 372 | fc(s: "-0." |
| 373 | "00000000000000000000000000000000000000000000000000" |
| 374 | "00000000000000000000000000000000000000000000000000" |
| 375 | "00000000000000000000000000000000000000000000000000" |
| 376 | "00000000000000000000000000000000000000000000000000" |
| 377 | "00000000000000000000000000000000000000000000000000" |
| 378 | "00000000000000000000000000000000000000000000000000" |
| 379 | "00000000000000000000000000000000000000000000000000" |
| 380 | "00000000000000000000000000000000000000000000000000" |
| 381 | "00000000000000000000000000000000000000000000000000" |
| 382 | "00000000000000000000000000000000000000000000000000" // 500 zeroes |
| 383 | "1e600" ); |
| 384 | |
| 385 | fc(s: "0e" |
| 386 | "00000000000000000000000000000000000000000000000000" |
| 387 | "00000000000000000000000000000000000000000000000000" |
| 388 | "00000000000000000000000000000000000000000000000000" |
| 389 | "00000000000000000000000000000000000000000000000000" |
| 390 | "00000000000000000000000000000000000000000000000000" |
| 391 | "00000000000000000000000000000000000000000000000000" |
| 392 | "00000000000000000000000000000000000000000000000000" |
| 393 | "00000000000000000000000000000000000000000000000000" |
| 394 | "00000000000000000000000000000000000000000000000000" |
| 395 | "00000000000000000000000000000000000000000000000000" // 500 zeroes |
| 396 | ); |
| 397 | } |
| 398 | |
| 399 | void checkAccuracy( |
| 400 | const char* nm, int max_ulp, parse_options const& opts = {}) |
| 401 | { |
| 402 | double x = std::strtod( nptr: nm, endptr: 0 ); |
| 403 | double y = boost::json::parse( s: nm, sp: {}, opt: opts ).as_double(); |
| 404 | std::uint64_t bx, by; |
| 405 | std::memcpy( dest: &bx, src: &x, n: sizeof(x) ); |
| 406 | std::memcpy( dest: &by, src: &y, n: sizeof(y) ); |
| 407 | std::int64_t diff = bx - by; |
| 408 | if (!BOOST_TEST(std::abs( diff ) <= max_ulp)) |
| 409 | std::fprintf(stderr, |
| 410 | format: "%s: difference %" PRId64 " ulp\n" |
| 411 | " strtod: %.13a %.16g\n" |
| 412 | " boost.json: %.13a %.16g\n\n" , |
| 413 | nm, diff, x, x, y, y ); |
| 414 | } |
| 415 | |
| 416 | void |
| 417 | testWithinULP() |
| 418 | { |
| 419 | std::mt19937_64 rng; |
| 420 | |
| 421 | checkAccuracy(nm: "10199214983525025199.13135016100190689227e-308" , max_ulp: 2); |
| 422 | |
| 423 | for( int i = 0; i < 1000000; ++i ) |
| 424 | { |
| 425 | unsigned long long x1 = rng(); |
| 426 | unsigned long long x2 = rng(); |
| 427 | int x3 = std::uniform_int_distribution<>( -308, +308 )( rng ); |
| 428 | |
| 429 | char buffer[ 128 ]; |
| 430 | sprintf( buf&: buffer, format: "%llu.%llue%d" , args&: x1, args&: x2, args&: x3 ); |
| 431 | |
| 432 | parse_options precise; |
| 433 | precise.numbers = number_precision::precise; |
| 434 | checkAccuracy( nm: buffer, max_ulp: 2 ); |
| 435 | checkAccuracy( nm: buffer, max_ulp: 0, opts: precise ); |
| 436 | } |
| 437 | |
| 438 | for( int i = -326; i <= +309; ++i ) |
| 439 | { |
| 440 | char buffer[ 128 ]; |
| 441 | sprintf( buf&: buffer, format: "1e%d" , args&: i ); |
| 442 | |
| 443 | checkAccuracy( nm: buffer, max_ulp: 0 ); |
| 444 | } |
| 445 | } |
| 446 | |
| 447 | void |
| 448 | () |
| 449 | { |
| 450 | parse_options opts; |
| 451 | opts.numbers = number_precision::precise; |
| 452 | BOOST_TEST( |
| 453 | parse("1002.9111801605201" , {}, opts) == 1002.9111801605201 ); |
| 454 | BOOST_TEST( |
| 455 | parse("-1.0346132515963697" , {}, opts) == -1.0346132515963697 ); |
| 456 | BOOST_TEST( |
| 457 | parse("-1207.1290929173115" , {}, opts) == -1207.1290929173115 ); |
| 458 | BOOST_TEST( |
| 459 | parse("-0.90521880279912548" , {}, opts) == -0.90521880279912548 ); |
| 460 | BOOST_TEST( |
| 461 | parse("370.91535570754445" , {}, opts) == 370.91535570754445 ); |
| 462 | BOOST_TEST( |
| 463 | parse("-2578.5523049665962" , {}, opts) == -2578.5523049665962 ); |
| 464 | |
| 465 | // test cases from https://www.icir.org/vern/papers/testbase-report.pdf |
| 466 | // (A Program for Testing IEEE Decimal–Binary Conversion by Vern Paxson) |
| 467 | BOOST_TEST( |
| 468 | parse("5e125" , {}, opts) == 5e125 ); |
| 469 | BOOST_TEST( |
| 470 | parse("69e267" , {}, opts) == 69e267 ); |
| 471 | BOOST_TEST( |
| 472 | parse("999e-026" , {}, opts) == 999e-026 ); |
| 473 | BOOST_TEST( |
| 474 | parse("7861e-034" , {}, opts) == 7861e-034 ); |
| 475 | BOOST_TEST( |
| 476 | parse("75569e-254" , {}, opts) == 75569e-254 ); |
| 477 | BOOST_TEST( |
| 478 | parse("928609e-261" , {}, opts) == 928609e-261 ); |
| 479 | BOOST_TEST( |
| 480 | parse("9210917e080" , {}, opts) == 9210917e080 ); |
| 481 | BOOST_TEST( |
| 482 | parse("84863171e114" , {}, opts) == 84863171e114 ); |
| 483 | BOOST_TEST( |
| 484 | parse("653777767e273" , {}, opts) == 653777767e273 ); |
| 485 | BOOST_TEST( |
| 486 | parse("5232604057e-298" , {}, opts) == 5232604057e-298 ); |
| 487 | BOOST_TEST( |
| 488 | parse("27235667517e-109" , {}, opts) == 27235667517e-109 ); |
| 489 | BOOST_TEST( |
| 490 | parse("653532977297e-123" , {}, opts) == 653532977297e-123 ); |
| 491 | BOOST_TEST( |
| 492 | parse("3142213164987e-294" , {}, opts) == 3142213164987e-294 ); |
| 493 | BOOST_TEST( |
| 494 | parse("46202199371337e-072" , {}, opts) == 46202199371337e-072 ); |
| 495 | BOOST_TEST( |
| 496 | parse("231010996856685e-073" , {}, opts) == 231010996856685e-073 ); |
| 497 | BOOST_TEST( |
| 498 | parse("9324754620109615e212" , {}, opts) == 9324754620109615e212 ); |
| 499 | BOOST_TEST( |
| 500 | parse("78459735791271921e049" , {}, opts) == 78459735791271921e049 ); |
| 501 | BOOST_TEST( |
| 502 | parse("272104041512242479e200" , {}, opts) == 272104041512242479e200 ); |
| 503 | BOOST_TEST( |
| 504 | parse("6802601037806061975e198" , {}, opts) == 6802601037806061975e198 ); |
| 505 | BOOST_TEST( |
| 506 | parse("20505426358836677347e-221" , {}, opts) == 20505426358836677347e-221 ); |
| 507 | BOOST_TEST( |
| 508 | parse("836168422905420598437e-234" , {}, opts) == 836168422905420598437e-234 ); |
| 509 | BOOST_TEST( |
| 510 | parse("4891559871276714924261e222" , {}, opts) == 4891559871276714924261e222 ); |
| 511 | BOOST_TEST( |
| 512 | parse("9e-265" , {}, opts) == 9e-265 ); |
| 513 | BOOST_TEST( |
| 514 | parse("85e-037" , {}, opts) == 85e-037 ); |
| 515 | BOOST_TEST( |
| 516 | parse("623e100" , {}, opts) == 623e100 ); |
| 517 | BOOST_TEST( |
| 518 | parse("3571e263" , {}, opts) == 3571e263 ); |
| 519 | BOOST_TEST( |
| 520 | parse("81661e153" , {}, opts) == 81661e153 ); |
| 521 | BOOST_TEST( |
| 522 | parse("920657e-023" , {}, opts) == 920657e-023 ); |
| 523 | BOOST_TEST( |
| 524 | parse("4603285e-024" , {}, opts) == 4603285e-024 ); |
| 525 | BOOST_TEST( |
| 526 | parse("87575437e-309" , {}, opts) == 87575437e-309 ); |
| 527 | BOOST_TEST( |
| 528 | parse("245540327e122" , {}, opts) == 245540327e122 ); |
| 529 | BOOST_TEST( |
| 530 | parse("6138508175e120" , {}, opts) == 6138508175e120 ); |
| 531 | BOOST_TEST( |
| 532 | parse("83356057653e193" , {}, opts) == 83356057653e193 ); |
| 533 | BOOST_TEST( |
| 534 | parse("619534293513e124" , {}, opts) == 619534293513e124 ); |
| 535 | BOOST_TEST( |
| 536 | parse("2335141086879e218" , {}, opts) == 2335141086879e218 ); |
| 537 | BOOST_TEST( |
| 538 | parse("36167929443327e-159" , {}, opts) == 36167929443327e-159 ); |
| 539 | BOOST_TEST( |
| 540 | parse("609610927149051e-255" , {}, opts) == 609610927149051e-255 ); |
| 541 | BOOST_TEST( |
| 542 | parse("3743626360493413e-165" , {}, opts) == 3743626360493413e-165 ); |
| 543 | BOOST_TEST( |
| 544 | parse("94080055902682397e-242" , {}, opts) == 94080055902682397e-242 ); |
| 545 | BOOST_TEST( |
| 546 | parse("899810892172646163e283" , {}, opts) == 899810892172646163e283 ); |
| 547 | BOOST_TEST( |
| 548 | parse("7120190517612959703e120" , {}, opts) == 7120190517612959703e120 ); |
| 549 | BOOST_TEST( |
| 550 | parse("25188282901709339043e-252" , {}, opts) == 25188282901709339043e-252 ); |
| 551 | BOOST_TEST( |
| 552 | parse("308984926168550152811e-052" , {}, opts) == 308984926168550152811e-052 ); |
| 553 | BOOST_TEST( |
| 554 | parse("6372891218502368041059e064" , {}, opts) == 6372891218502368041059e064 ); |
| 555 | } |
| 556 | |
| 557 | void |
| 558 | testSpecialNumbers() |
| 559 | { |
| 560 | parse_options with_special_numbers; |
| 561 | with_special_numbers.allow_infinity_and_nan = true; |
| 562 | |
| 563 | grind_double( |
| 564 | s: "Infinity" , |
| 565 | v: std::numeric_limits<double>::infinity(), |
| 566 | po: with_special_numbers); |
| 567 | |
| 568 | grind_double( |
| 569 | s: "-Infinity" , |
| 570 | v: -std::numeric_limits<double>::infinity(), |
| 571 | po: with_special_numbers); |
| 572 | |
| 573 | grind_double( |
| 574 | s: "NaN" , |
| 575 | v: std::numeric_limits<double>::quiet_NaN(), |
| 576 | po: with_special_numbers); |
| 577 | } |
| 578 | |
| 579 | void |
| 580 | run() |
| 581 | { |
| 582 | testDouble(); |
| 583 | testWithinULP(); |
| 584 | testExtraPrecision(); |
| 585 | testSpecialNumbers(); |
| 586 | } |
| 587 | }; |
| 588 | |
| 589 | TEST_SUITE(double_test, "boost.json.double" ); |
| 590 | |
| 591 | } // namespace json |
| 592 | } // namespace boost |
| 593 | |