spirit/test/x3/uint1.cpp
Han Wang b8b82630ac fix x3::uint_parser<T(signed)> overflow problem
According to spirit document,

  "All numeric parsers check for overflow conditions based on the type T the corresponding uint_parser<> has been instantiated with. If the parsed number overflows this type the parsing fails. Please be aware that the overflow check is not based on the type of the supplied attribute but solely depends on the template parameter T."

the valid input range of x3::uint_parser<T> should be 0 - std::numeric_limits<T>::max(). However, the current implementation takes values from std::numeric_limits<T>::max()+1 - std::numeric_limits<std::make_unsigned_t<T>>::max() also as valid input.
2017-11-27 17:47:10 +01:00

212 lines
7.3 KiB
C++

/*=============================================================================
Copyright (c) 2001-2015 Joel de Guzman
Copyright (c) 2001-2011 Hartmut Kaiser
Copyright (c) 2011 Bryce Lelbach
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#include "uint.hpp"
#include <boost/spirit/home/x3.hpp>
int
main()
{
using spirit_test::test;
using spirit_test::test_attr;
///////////////////////////////////////////////////////////////////////////
// unsigned tests
///////////////////////////////////////////////////////////////////////////
{
using boost::spirit::x3::uint_;
unsigned u;
BOOST_TEST(test("123456", uint_));
BOOST_TEST(test_attr("123456", uint_, u));
BOOST_TEST(u == 123456);
BOOST_TEST(test(max_unsigned, uint_));
BOOST_TEST(test_attr(max_unsigned, uint_, u));
BOOST_TEST(u == UINT_MAX);
BOOST_TEST(!test(unsigned_overflow, uint_));
BOOST_TEST(!test_attr(unsigned_overflow, uint_, u));
}
///////////////////////////////////////////////////////////////////////////
// binary tests
///////////////////////////////////////////////////////////////////////////
{
using boost::spirit::x3::bin;
unsigned u;
BOOST_TEST(test("11111110", bin));
BOOST_TEST(test_attr("11111110", bin, u));
BOOST_TEST(u == 0xFE);
BOOST_TEST(test(max_binary, bin));
BOOST_TEST(test_attr(max_binary, bin, u));
BOOST_TEST(u == UINT_MAX);
BOOST_TEST(!test(binary_overflow, bin));
BOOST_TEST(!test_attr(binary_overflow, bin, u));
}
///////////////////////////////////////////////////////////////////////////
// octal tests
///////////////////////////////////////////////////////////////////////////
{
using boost::spirit::x3::oct;
unsigned u;
BOOST_TEST(test("12545674515", oct));
BOOST_TEST(test_attr("12545674515", oct, u));
BOOST_TEST(u == 012545674515);
BOOST_TEST(test(max_octal, oct));
BOOST_TEST(test_attr(max_octal, oct, u));
BOOST_TEST(u == UINT_MAX);
BOOST_TEST(!test(octal_overflow, oct));
BOOST_TEST(!test_attr(octal_overflow, oct, u));
}
///////////////////////////////////////////////////////////////////////////
// hex tests
///////////////////////////////////////////////////////////////////////////
{
using boost::spirit::x3::hex;
unsigned u;
BOOST_TEST(test("95BC8DF", hex));
BOOST_TEST(test_attr("95BC8DF", hex, u));
BOOST_TEST(u == 0x95BC8DF);
BOOST_TEST(test("abcdef12", hex));
BOOST_TEST(test_attr("abcdef12", hex, u));
BOOST_TEST(u == 0xabcdef12);
BOOST_TEST(test(max_hex, hex));
BOOST_TEST(test_attr(max_hex, hex, u));
BOOST_TEST(u == UINT_MAX);
BOOST_TEST(!test(hex_overflow, hex));
BOOST_TEST(!test_attr(hex_overflow, hex, u));
}
///////////////////////////////////////////////////////////////////////////
// limited fieldwidth
///////////////////////////////////////////////////////////////////////////
{
unsigned u;
using boost::spirit::x3::uint_parser;
uint_parser<unsigned, 10, 1, 3> uint3;
BOOST_TEST(test("123456", uint3, false));
BOOST_TEST(test_attr("123456", uint3, u, false));
BOOST_TEST(u == 123);
uint_parser<unsigned, 10, 2, 4> uint4;
BOOST_TEST(test("123456", uint4, false));
BOOST_TEST(test_attr("123456", uint4, u, false));
BOOST_TEST(u == 1234);
char const * first = "0000000";
char const * last = first + std::strlen(first);
uint_parser<unsigned, 10, 4, 4> uint_exact4;
BOOST_TEST(boost::spirit::x3::parse(first, last, uint_exact4, u)
&& first != last && (last-first == 3) && u == 0);
first = "0001400";
last = first + std::strlen(first);
BOOST_TEST(boost::spirit::x3::parse(first, last, uint_exact4, u)
&& first != last && (last-first == 3) && u == 1);
BOOST_TEST(!test("1", uint4));
BOOST_TEST(!test_attr("1", uint4, u));
BOOST_TEST(test_attr("014567", uint4, u, false) && u == 145);
}
///////////////////////////////////////////////////////////////////////////
// action tests
///////////////////////////////////////////////////////////////////////////
{
using boost::spirit::x3::_attr;
using boost::spirit::x3::uint_;
using boost::spirit::x3::ascii::space;
int n;
auto f = [&](auto& ctx){ n = _attr(ctx); };
BOOST_TEST(test("123", uint_[f]));
BOOST_TEST(n == 123);
BOOST_TEST(test(" 456", uint_[f], space));
BOOST_TEST(n == 456);
}
///////////////////////////////////////////////////////////////////////////
// Check overflow is parse error
///////////////////////////////////////////////////////////////////////////
{
boost::spirit::x3::uint_parser<boost::uint8_t> uint8_;
boost::uint8_t u8;
BOOST_TEST(!test_attr("999", uint8_, u8));
BOOST_TEST(!test_attr("256", uint8_, u8));
BOOST_TEST(test_attr("255", uint8_, u8));
boost::spirit::x3::uint_parser<boost::uint16_t> uint16_;
boost::uint16_t u16;
BOOST_TEST(!test_attr("99999", uint16_, u16));
BOOST_TEST(!test_attr("65536", uint16_, u16));
BOOST_TEST(test_attr("65535", uint16_, u16));
boost::spirit::x3::uint_parser<boost::uint32_t> uint32_;
boost::uint32_t u32;
BOOST_TEST(!test_attr("9999999999", uint32_, u32));
BOOST_TEST(!test_attr("4294967296", uint32_, u32));
BOOST_TEST(test_attr("4294967295", uint32_, u32));
boost::spirit::x3::uint_parser<boost::int8_t> u_int8_;
BOOST_TEST(!test_attr("999", u_int8_, u8));
BOOST_TEST(!test_attr("-1", u_int8_, u8));
BOOST_TEST(!test_attr("128", u_int8_, u8));
BOOST_TEST(test_attr("127", u_int8_, u8));
BOOST_TEST(test_attr("0", u_int8_, u8));
boost::spirit::x3::uint_parser<boost::int16_t> u_int16_;
BOOST_TEST(!test_attr("99999", u_int16_, u16));
BOOST_TEST(!test_attr("-1", u_int16_, u16));
BOOST_TEST(!test_attr("32768", u_int16_, u16));
BOOST_TEST(test_attr("32767", u_int16_, u16));
BOOST_TEST(test_attr("0", u_int16_, u16));
boost::spirit::x3::uint_parser<boost::int32_t> u_int32_;
BOOST_TEST(!test_attr("9999999999", u_int32_, u32));
BOOST_TEST(!test_attr("-1", u_int32_, u32));
BOOST_TEST(!test_attr("2147483648", u_int32_, u32));
BOOST_TEST(test_attr("2147483647", u_int32_, u32));
BOOST_TEST(test_attr("0", u_int32_, u32));
}
///////////////////////////////////////////////////////////////////////////
// custom uint tests
///////////////////////////////////////////////////////////////////////////
{
using boost::spirit::x3::uint_;
using boost::spirit::x3::uint_parser;
custom_uint u;
BOOST_TEST(test_attr("123456", uint_, u));
uint_parser<custom_uint, 10, 1, 2> uint2;
BOOST_TEST(test_attr("12", uint2, u));
}
return boost::report_errors();
}