diff --git a/src/tl/tl/tlString.cc b/src/tl/tl/tlString.cc index 52d7f6715..aaf8ab3a0 100644 --- a/src/tl/tl/tlString.cc +++ b/src/tl/tl/tlString.cc @@ -831,186 +831,160 @@ tl::Extractor::read_quoted (std::string &value) return *this; } -bool +namespace +{ + template struct overflow_msg_func; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on long long integer")); + } + }; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on unsigned long long integer")); + } + }; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on long integer")); + } + }; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on unsigned long integer")); + } + }; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on integer")); + } + }; + + template <> struct overflow_msg_func + { + std::string operator() () const + { + return tl::to_string (QObject::tr ("Range overflow on unsigned integer")); + } + }; +} + +template bool +tl::Extractor::try_read_signed_int (T &value) +{ + if (! *skip ()) { + return false; + } + + bool minus = false; + if (*m_cp == '-') { + minus = true; + ++m_cp; + } else if (*m_cp == '+') { + ++m_cp; + } + + if (! isdigit (*m_cp)) { + return false; + } + + value = 0; + while (isdigit (*m_cp)) { + if (value > std::numeric_limits::max () / 10) { + throw tl::Exception (overflow_msg_func () ()); + } + value *= 10; + if (value > std::numeric_limits::max () - (*m_cp - '0')) { + throw tl::Exception (overflow_msg_func () ()); + } + value += (*m_cp - '0'); + ++m_cp; + } + + if (minus) { + value = -value; + } + + return true; +} + +template bool +tl::Extractor::try_read_unsigned_int (T &value) +{ + if (! *skip ()) { + return false; + } + + if (! isdigit (*m_cp)) { + return false; + } + + value = 0; + while (isdigit (*m_cp)) { + if (value > std::numeric_limits::max () / 10) { + throw tl::Exception (overflow_msg_func () ()); + } + value *= 10; + if (value > std::numeric_limits::max () - (*m_cp - '0')) { + throw tl::Exception (overflow_msg_func () ()); + } + value += (*m_cp - '0'); + ++m_cp; + } + + return true; +} + +bool tl::Extractor::try_read (unsigned int &value) { - if (! *skip ()) { - return false; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on unsigned integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - return true; + return try_read_unsigned_int (value); } -bool -tl::Extractor::try_read (int &value) -{ - if (! *skip ()) { - return false; - } - - bool minus = false; - if (*m_cp == '-') { - minus = true; - ++m_cp; - } else if (*m_cp == '+') { - ++m_cp; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - if (minus) { - value = -value; - } - - return true; -} - -bool +bool tl::Extractor::try_read (unsigned long &value) { - if (! *skip ()) { - return false; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on unsigned long integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - return true; + return try_read_unsigned_int (value); } -bool +bool tl::Extractor::try_read (unsigned long long &value) { - if (! *skip ()) { - return false; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on unsigned long long integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - return true; + return try_read_unsigned_int (value); } -bool +bool +tl::Extractor::try_read (int &value) +{ + return try_read_signed_int (value); +} + +bool tl::Extractor::try_read (long &value) { - if (! *skip ()) { - return false; - } - - bool minus = false; - if (*m_cp == '-') { - minus = true; - ++m_cp; - } else if (*m_cp == '+') { - ++m_cp; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on long integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - if (minus) { - value = -value; - } - - return true; + return try_read_signed_int (value); } -bool +bool tl::Extractor::try_read (long long &value) { - if (! *skip ()) { - return false; - } - - bool minus = false; - if (*m_cp == '-') { - minus = true; - ++m_cp; - } else if (*m_cp == '+') { - ++m_cp; - } - - if (! isdigit (*m_cp)) { - return false; - } - - value = 0; - while (isdigit (*m_cp)) { - if ((value * 10) / 10 != value) { - throw tl::Exception (tl::to_string (QObject::tr ("Range overflow on long long integer"))); - } - value *= 10; - value += (*m_cp - '0'); - ++m_cp; - } - - if (minus) { - value = -value; - } - - return true; + return try_read_signed_int (value); } - bool tl::Extractor::try_read (double &value) { diff --git a/src/tl/tl/tlString.h b/src/tl/tl/tlString.h index 718b2c169..11c8b05a4 100644 --- a/src/tl/tl/tlString.h +++ b/src/tl/tl/tlString.h @@ -732,6 +732,9 @@ public: } private: + template bool try_read_signed_int (T &value); + template bool try_read_unsigned_int (T &value); + const char *m_cp; std::string m_str; }; diff --git a/src/tl/tl/tlVariant.h b/src/tl/tl/tlVariant.h index 967c753de..df9fda803 100644 --- a/src/tl/tl/tlVariant.h +++ b/src/tl/tl/tlVariant.h @@ -1268,7 +1268,7 @@ public: */ bool is_longlong () const { - return m_type == t_longlong || is_long (); + return m_type == t_longlong; } /** @@ -1276,7 +1276,7 @@ public: */ bool is_ulonglong () const { - return m_type == t_ulonglong || is_ulong (); + return m_type == t_ulonglong; } #if defined(HAVE_64BIT_COORD) diff --git a/src/tl/unit_tests/tlVariant.cc b/src/tl/unit_tests/tlVariant.cc index d3a25748c..5a8b688d7 100644 --- a/src/tl/unit_tests/tlVariant.cc +++ b/src/tl/unit_tests/tlVariant.cc @@ -137,7 +137,7 @@ TEST(1) EXPECT_EQ (v.is_cstring (), false); EXPECT_EQ (v.is_id (), false); EXPECT_EQ (v.is_ulong (), true); - EXPECT_EQ (v.is_ulonglong (), true); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_long (), false); EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_double (), false); @@ -172,7 +172,7 @@ TEST(1) EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is_ulong (), true); - EXPECT_EQ (v.is_ulonglong (), true); + EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_long (), false); EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_id (), false); @@ -202,7 +202,7 @@ TEST(1) EXPECT_EQ (v.is_list (), false); EXPECT_EQ (v.is_cstring (), false); EXPECT_EQ (v.is_long (), true); - EXPECT_EQ (v.is_longlong (), true); + EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_ulong (), false); EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is (), false); @@ -389,7 +389,7 @@ TEST(1) EXPECT_EQ (v.is_char (), false); EXPECT_EQ (v.is_long (), true); EXPECT_EQ (v.is_ulong (), false); - EXPECT_EQ (v.is_longlong (), true); + EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_double (), false); EXPECT_EQ (v.to_parsable_string (), "#2");