Search code examples
c++boost-spiritboost-spirit-qi

Boost spirit do not check for int overflow


I am trying to parse some integers with boost spirit, and I have to check data for overflow and spirit doc says that all integer parsers do check for overflow, however it only works for unsigned types, if I try to parse signed integers spirit won't check for overflow anymore.

char const* b = "6600452345243524352340";
char const* e = b + strlen("6600452345243524352340");
int32_t res = 0;
bool valid = boost::spirit::qi::parse(b, e, boost::spirit::qi::int_, res);
std::cout << valid << " " << res << std::endl;

Is there a way to make spirit check for signed overflows? I am using boost 1.55, gcc 4.9.


Solution

  • Both check for overflow just fine:

    Live On Coliru

    #include <boost/spirit/include/qi.hpp>
    #include <boost/multiprecision/cpp_int.hpp>
    
    using boost::multiprecision::int128_t;
    using boost::multiprecision::int256_t;
    using boost::multiprecision::uint128_t;
    using boost::multiprecision::uint256_t;
    
    template <typename T>
    bool try_parse(char const* s) {
        auto b = s, e = b + strlen(s);
        T res = 0;
        namespace qi = boost::spirit::qi;
        bool valid = qi::parse(b, e, qi::int_parser<T, 10>(), res);
        if (!valid)
            std::cout << "Unparsed (" << __PRETTY_FUNCTION__ << ")\n";
        else
            std::cout << "Valid: " << res << "(" << __PRETTY_FUNCTION__ << ")\n";;
    
        if (b!=e)
            std::cout << " --> remaining: '" << std::string(b,e) << "'\n";
    
        return valid;
    }
    
    int main() {
        try_parse<int8_t>    ("6600452345243524352340");
        try_parse<uint8_t>   ("6600452345243524352340");
    
        try_parse<int16_t>   ("6600452345243524352340");
        try_parse<uint16_t>  ("6600452345243524352340");
    
        try_parse<int32_t>   ("6600452345243524352340");
        try_parse<uint32_t>  ("6600452345243524352340");
    
        try_parse<int64_t>   ("6600452345243524352340");
        try_parse<uint64_t>  ("6600452345243524352340");
    
        try_parse<int128_t>  ("6600452345243524352340");
        try_parse<uint128_t> ("6600452345243524352340");
    }
    

    Prints

    Unparsed (bool try_parse(const char *) [T = signed char])
    --> remaining: '6600452345243524352340'
    Unparsed (bool try_parse(const char *) [T = unsigned char])
    --> remaining: '6600452345243524352340'
    Unparsed (bool try_parse(const char *) [T = short])
    --> remaining: '6600452345243524352340'
    Unparsed (bool try_parse(const char *) [T = unsigned short])
    --> remaining: '6600452345243524352340'
    Unparsed (bool try_parse(const char *) [T = int])
    --> remaining: '6600452345243524352340'
    Unparsed (bool try_parse(const char *) [T = unsigned int])
    --> remaining: '6600452345243524352340'
    Unparsed (bool try_parse(const char *) [T = long])
    --> remaining: '6600452345243524352340'
    Unparsed (bool try_parse(const char *) [T = unsigned long])
    --> remaining: '6600452345243524352340'
    Valid: 6600452345243524352340 (bool try_parse(const char *) [T = boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<128, 128, boost::multiprecision::cpp_integer_type::signed_magnitude, boost::multiprecision::cpp_int_check_type::unchecked, void>, boost::multiprecision::expression_template_option::et_off>])
    Valid: 6600452345243524352340 (bool try_parse(const char *) [T = boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<128, 128, boost::multiprecision::cpp_integer_type::unsigned_magnitude, boost::multiprecision::cpp_int_check_type::unchecked, void>, boost::multiprecision::expression_template_option::et_off>])