From 5341e1aa9e3562d5217f3db87ca77238bf63f93e Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 31 Oct 2003 18:27:17 -0500 Subject: Make the to_number function work better. base/str.cc: Make some fixes for the to_number function. Fix overflow calculation for maximum decimal value. (Note: minimum decimal value for signed numbers does not work correctly, e.g. it will overflow on -128 for a signed char though -127 will work) Fix overflow calculation for hex values being converted into signed types Fix up the debugging stuff a little to make sure the values are always printed as numbers. test/strnumtest.cc: using namespace std for g++ 3 --HG-- extra : convert_revision : b00bb1296c85c3d64d8864283c9374e1563bfa31 --- base/str.cc | 30 ++++++++++++++++++++---------- test/strnumtest.cc | 2 ++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/base/str.cc b/base/str.cc index 9c3964ce3..5ba23b55f 100644 --- a/base/str.cc +++ b/base/str.cc @@ -74,25 +74,31 @@ tokenize(vector& v, const string &s, char token, bool ignore) v.push_back(s.substr(first)); } +/** + * @todo This function will not handle the smallest negative decimal + * value for a signed type + */ + template inline bool __to_number(string value, T &retval) { static const T maxnum = ((T)-1); static const bool sign = maxnum < 0; - static const T hexmax = maxnum & (((T)1 << (sizeof(T) * 8 - 4)) - 1); - static const T octmax = maxnum & (((T)1 << (sizeof(T) * 8 - 3)) - 1); + static const int bits = sizeof(T) * 8; + static const T hexmax = maxnum & (((T)1 << (bits - 4 - sign)) - 1); + static const T octmax = maxnum & (((T)1 << (bits - 3 - sign)) - 1); static const T signmax = - (sign) ? maxnum & (((T)1 << (sizeof(T) * 8 - 1)) - 1) : maxnum; - static const T decmax = signmax / 10 - 1; + (sign) ? maxnum & (((T)1 << (bits - 1)) - 1) : maxnum; + static const T decmax = signmax / 10; #if 0 - cout << "maxnum = 0x" << hex << maxnum << "\n" - << "sign = 0x" << hex << sign << "\n" - << "hexmax = 0x" << hex << hexmax << "\n" - << "octmax = 0x" << hex << octmax << "\n" - << "signmax = 0x" << hex << signmax << "\n" - << "decmax = 0x" << hex << decmax << "\n"; + cout << "maxnum = 0x" << hex << (unsigned long long)maxnum << "\n" + << "sign = 0x" << hex << (unsigned long long)sign << "\n" + << "hexmax = 0x" << hex << (unsigned long long)hexmax << "\n" + << "octmax = 0x" << hex << (unsigned long long)octmax << "\n" + << "signmax = 0x" << hex << (unsigned long long)signmax << "\n" + << "decmax = 0x" << hex << (unsigned long long)decmax << "\n"; #endif eat_white(value); @@ -180,8 +186,10 @@ __to_number(string value, T &retval) goto multiply; if (retval > decmax) return false; + bool atmax = retval == decmax; retval *= 10; retval += c - '0'; + if (atmax && retval < decmax) return false; if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1)))) return false; } @@ -190,8 +198,10 @@ __to_number(string value, T &retval) if (IsDec(c)) { if (retval > decmax) return false; + bool atmax = retval == decmax; retval *= 10; retval += c - '0'; + if (atmax && retval < decmax) return false; if (sign && negative) { if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) && retval >= (T)-signmax) diff --git a/test/strnumtest.cc b/test/strnumtest.cc index e971a7dfd..d491b8b5d 100644 --- a/test/strnumtest.cc +++ b/test/strnumtest.cc @@ -33,6 +33,8 @@ #include "base/str.hh" +using namespace std; + int main(int argc, char *argv[]) { -- cgit v1.2.3