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
This commit is contained in:
parent
8835aae3e3
commit
5341e1aa9e
2 changed files with 22 additions and 10 deletions
30
base/str.cc
30
base/str.cc
|
@ -74,25 +74,31 @@ tokenize(vector<string>& v, const string &s, char token, bool ignore)
|
||||||
v.push_back(s.substr(first));
|
v.push_back(s.substr(first));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo This function will not handle the smallest negative decimal
|
||||||
|
* value for a signed type
|
||||||
|
*/
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline bool
|
inline bool
|
||||||
__to_number(string value, T &retval)
|
__to_number(string value, T &retval)
|
||||||
{
|
{
|
||||||
static const T maxnum = ((T)-1);
|
static const T maxnum = ((T)-1);
|
||||||
static const bool sign = maxnum < 0;
|
static const bool sign = maxnum < 0;
|
||||||
static const T hexmax = maxnum & (((T)1 << (sizeof(T) * 8 - 4)) - 1);
|
static const int bits = sizeof(T) * 8;
|
||||||
static const T octmax = maxnum & (((T)1 << (sizeof(T) * 8 - 3)) - 1);
|
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 =
|
static const T signmax =
|
||||||
(sign) ? maxnum & (((T)1 << (sizeof(T) * 8 - 1)) - 1) : maxnum;
|
(sign) ? maxnum & (((T)1 << (bits - 1)) - 1) : maxnum;
|
||||||
static const T decmax = signmax / 10 - 1;
|
static const T decmax = signmax / 10;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
cout << "maxnum = 0x" << hex << maxnum << "\n"
|
cout << "maxnum = 0x" << hex << (unsigned long long)maxnum << "\n"
|
||||||
<< "sign = 0x" << hex << sign << "\n"
|
<< "sign = 0x" << hex << (unsigned long long)sign << "\n"
|
||||||
<< "hexmax = 0x" << hex << hexmax << "\n"
|
<< "hexmax = 0x" << hex << (unsigned long long)hexmax << "\n"
|
||||||
<< "octmax = 0x" << hex << octmax << "\n"
|
<< "octmax = 0x" << hex << (unsigned long long)octmax << "\n"
|
||||||
<< "signmax = 0x" << hex << signmax << "\n"
|
<< "signmax = 0x" << hex << (unsigned long long)signmax << "\n"
|
||||||
<< "decmax = 0x" << hex << decmax << "\n";
|
<< "decmax = 0x" << hex << (unsigned long long)decmax << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
eat_white(value);
|
eat_white(value);
|
||||||
|
@ -180,8 +186,10 @@ __to_number(string value, T &retval)
|
||||||
goto multiply;
|
goto multiply;
|
||||||
|
|
||||||
if (retval > decmax) return false;
|
if (retval > decmax) return false;
|
||||||
|
bool atmax = retval == decmax;
|
||||||
retval *= 10;
|
retval *= 10;
|
||||||
retval += c - '0';
|
retval += c - '0';
|
||||||
|
if (atmax && retval < decmax) return false;
|
||||||
if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
|
if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -190,8 +198,10 @@ __to_number(string value, T &retval)
|
||||||
if (IsDec(c)) {
|
if (IsDec(c)) {
|
||||||
|
|
||||||
if (retval > decmax) return false;
|
if (retval > decmax) return false;
|
||||||
|
bool atmax = retval == decmax;
|
||||||
retval *= 10;
|
retval *= 10;
|
||||||
retval += c - '0';
|
retval += c - '0';
|
||||||
|
if (atmax && retval < decmax) return false;
|
||||||
if (sign && negative) {
|
if (sign && negative) {
|
||||||
if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
|
if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
|
||||||
retval >= (T)-signmax)
|
retval >= (T)-signmax)
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
|
|
||||||
#include "base/str.hh"
|
#include "base/str.hh"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue