2008-03-09 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

* src/Util.{h, cc}
	(parseUInt): New function.
	(alphaToNum): Now returns unsigned int and 0 when overflow 
detected.
	The actual range is uint32_t.
	* test/UtilTest.cc
	
	* src/ParameterizedStringParser.cc:
	Use Util::parseUInt() for loop variables.
	* test/ParameterizedStringParserTest.cc
	
	* src/PStringNumLoop.h: Make _startValue and _endValue unsigned 
int.
pull/1/head
Tatsuhiro Tsujikawa 2008-03-09 15:03:47 +00:00
parent 7f40794931
commit 68b84574ae
7 changed files with 115 additions and 39 deletions

View File

@ -1,3 +1,17 @@
2008-03-09 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
* src/Util.{h, cc}
(parseUInt): New function.
(alphaToNum): Now returns unsigned int and 0 when overflow detected.
The actual range is uint32_t.
* test/UtilTest.cc
* src/ParameterizedStringParser.cc:
Use Util::parseUInt() for loop variables.
* test/ParameterizedStringParserTest.cc
* src/PStringNumLoop.h: Make _startValue and _endValue unsigned int.
2008-03-09 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> 2008-03-09 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Rewritten the functions for binding port. Rewritten the functions for binding port.

View File

@ -45,9 +45,9 @@ class PStringNumLoop : public PStringDatum
{ {
private: private:
int _startValue; unsigned int _startValue;
int _endValue; unsigned int _endValue;
unsigned int _step; unsigned int _step;
@ -56,7 +56,8 @@ private:
PStringDatumHandle _next; PStringDatumHandle _next;
public: public:
PStringNumLoop(int startValue, int endValue, unsigned int step, PStringNumLoop(unsigned int startValue, unsigned int endValue,
unsigned int step,
const NumberDecoratorHandle& nd, const NumberDecoratorHandle& nd,
const PStringDatumHandle& next = 0): const PStringDatumHandle& next = 0):
_startValue(startValue), _startValue(startValue),
@ -69,7 +70,7 @@ public:
virtual void accept(PStringVisitor* visitor) virtual void accept(PStringVisitor* visitor)
{ {
for(int i = _startValue; i <= _endValue; i += _step) { for(unsigned int i = _startValue; i <= _endValue; i += _step) {
PStringSegment(_numberDecorator->decorate(i), _next).accept(visitor); PStringSegment(_numberDecorator->decorate(i), _next).accept(visitor);
} }
} }
@ -79,12 +80,12 @@ public:
return _next; return _next;
} }
int getStartValue() const unsigned int getStartValue() const
{ {
return _startValue; return _startValue;
} }
int getEndValue() const unsigned int getEndValue() const
{ {
return _endValue; return _endValue;
} }

View File

@ -113,10 +113,11 @@ PStringDatumHandle ParameterizedStringParser::createLoop(const std::string& src,
std::string::size_type colonIndex = loopStr.find(":"); std::string::size_type colonIndex = loopStr.find(":");
if(colonIndex != std::string::npos) { if(colonIndex != std::string::npos) {
std::string stepStr = loopStr.substr(colonIndex+1); std::string stepStr = loopStr.substr(colonIndex+1);
int sstep;
if(Util::isNumber(stepStr)) { if(Util::isNumber(stepStr)) {
step = Util::parseInt(stepStr); step = Util::parseUInt(stepStr);
} else { } else {
throw new FatalException("A step count must be a number."); throw new FatalException("A step count must be a positive number.");
} }
loopStr.erase(colonIndex); loopStr.erase(colonIndex);
} }
@ -125,12 +126,12 @@ PStringDatumHandle ParameterizedStringParser::createLoop(const std::string& src,
throw new FatalException("Loop range missing."); throw new FatalException("Loop range missing.");
} }
NumberDecoratorHandle nd = 0; NumberDecoratorHandle nd = 0;
int start; unsigned int start;
int end; unsigned int end;
if(Util::isNumber(range.first) && Util::isNumber(range.second)) { if(Util::isNumber(range.first) && Util::isNumber(range.second)) {
nd = new FixedWidthNumberDecorator(range.first.size()); nd = new FixedWidthNumberDecorator(range.first.size());
start = Util::parseInt(range.first); start = Util::parseUInt(range.first);
end = Util::parseInt(range.second); end = Util::parseUInt(range.second);
} else if(Util::isLowercase(range.first) && Util::isLowercase(range.second)) { } else if(Util::isLowercase(range.first) && Util::isLowercase(range.second)) {
nd = new AlphaNumberDecorator(range.first.size()); nd = new AlphaNumberDecorator(range.first.size());
start = Util::alphaToNum(range.first); start = Util::alphaToNum(range.first);

View File

@ -417,6 +417,31 @@ int32_t Util::parseInt(const std::string& s, int32_t base)
return v; return v;
} }
uint32_t Util::parseUInt(const std::string& s, int base)
{
std::string trimed = Util::trim(s);
if(trimed.empty()) {
throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
"empty string");
}
// We don't allow negative number.
if(trimed[0] == '-') {
throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
trimed.c_str());
}
char* stop;
errno = 0;
unsigned long int v = strtoul(trimed.c_str(), &stop, base);
if(*stop != '\0') {
throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
trimed.c_str());
} else if((v == ULONG_MAX) && errno == ERANGE || v > UINT32_MAX) {
throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
trimed.c_str());
}
return v;
}
int64_t Util::parseLLInt(const std::string& s, int32_t base) int64_t Util::parseLLInt(const std::string& s, int32_t base)
{ {
std::string trimed = Util::trim(s); std::string trimed = Util::trim(s);
@ -730,7 +755,7 @@ bool Util::isUppercase(const std::string& what)
return true; return true;
} }
int Util::alphaToNum(const std::string& alphabets) unsigned int Util::alphaToNum(const std::string& alphabets)
{ {
if(alphabets.empty()) { if(alphabets.empty()) {
return 0; return 0;
@ -741,10 +766,13 @@ int Util::alphaToNum(const std::string& alphabets)
} else { } else {
base = 'A'; base = 'A';
} }
int num = 0; uint64_t num = 0;
for(size_t i = 0; i < alphabets.size(); ++i) { for(size_t i = 0; i < alphabets.size(); ++i) {
int v = alphabets[i]-base; unsigned int v = alphabets[i]-base;
num = num*26+v; num = num*26+v;
if(num > UINT32_MAX) {
return 0;
}
} }
return num; return num;
} }

View File

@ -167,6 +167,8 @@ public:
static int32_t parseInt(const std::string& s, int32_t base = 10); static int32_t parseInt(const std::string& s, int32_t base = 10);
static unsigned int parseUInt(const std::string& s, int base = 10);
static int64_t parseLLInt(const std::string& s, int32_t base = 10); static int64_t parseLLInt(const std::string& s, int32_t base = 10);
static IntSequence parseIntRange(const std::string& src); static IntSequence parseIntRange(const std::string& src);
@ -205,14 +207,21 @@ public:
static void sleep(long seconds); static void sleep(long seconds);
static void usleep(long microseconds); static void usleep(long microseconds);
static bool isNumber(const std::string& what); static bool isNumber(const std::string& what);
static bool isLowercase(const std::string& what); static bool isLowercase(const std::string& what);
static bool isUppercase(const std::string& what); static bool isUppercase(const std::string& what);
static int alphaToNum(const std::string& alphabets); /**
* Converts alphabets to unsigned int, assuming alphabets as a base 26
* integer and 'a' or 'A' is 0.
* This function assumes alphabets includes only a-z.
* Upper case are allowed but all letters must be upper case.
* If overflow occurs, returns 0.
*/
static unsigned int alphaToNum(const std::string& alphabets);
static void mkdirs(const std::string& dirpath); static void mkdirs(const std::string& dirpath);

View File

@ -126,9 +126,9 @@ void ParameterizedStringParserTest::testParse_loop()
SharedHandle<PStringNumLoop> loop1 = ls; SharedHandle<PStringNumLoop> loop1 = ls;
CPPUNIT_ASSERT(!loop1.isNull()); CPPUNIT_ASSERT(!loop1.isNull());
CPPUNIT_ASSERT_EQUAL(1, loop1->getStartValue()); CPPUNIT_ASSERT_EQUAL(1U, loop1->getStartValue());
CPPUNIT_ASSERT_EQUAL(10, loop1->getEndValue()); CPPUNIT_ASSERT_EQUAL(10U, loop1->getEndValue());
CPPUNIT_ASSERT_EQUAL((unsigned int)2, loop1->getStep()); CPPUNIT_ASSERT_EQUAL(2U, loop1->getStep());
} }
void ParameterizedStringParserTest::testParse_loop_empty() void ParameterizedStringParserTest::testParse_loop_empty()
@ -189,9 +189,9 @@ void ParameterizedStringParserTest::testParse_alphaLoop()
SharedHandle<PStringNumLoop> loop1 = ls; SharedHandle<PStringNumLoop> loop1 = ls;
CPPUNIT_ASSERT(!loop1.isNull()); CPPUNIT_ASSERT(!loop1.isNull());
CPPUNIT_ASSERT_EQUAL(0, loop1->getStartValue()); CPPUNIT_ASSERT_EQUAL(0U, loop1->getStartValue());
CPPUNIT_ASSERT_EQUAL(25, loop1->getEndValue()); CPPUNIT_ASSERT_EQUAL(25U, loop1->getEndValue());
CPPUNIT_ASSERT_EQUAL((unsigned int)2, loop1->getStep()); CPPUNIT_ASSERT_EQUAL(2U, loop1->getStep());
} }
void ParameterizedStringParserTest::testParse_loop_mixedChar() void ParameterizedStringParserTest::testParse_loop_mixedChar()
@ -230,9 +230,9 @@ void ParameterizedStringParserTest::testParse_segment_loop()
SharedHandle<PStringNumLoop> loop1 = segment1->getNext(); SharedHandle<PStringNumLoop> loop1 = segment1->getNext();
CPPUNIT_ASSERT(!loop1.isNull()); CPPUNIT_ASSERT(!loop1.isNull());
CPPUNIT_ASSERT_EQUAL(1, loop1->getStartValue()); CPPUNIT_ASSERT_EQUAL(1U, loop1->getStartValue());
CPPUNIT_ASSERT_EQUAL(3, loop1->getEndValue()); CPPUNIT_ASSERT_EQUAL(3U, loop1->getEndValue());
CPPUNIT_ASSERT_EQUAL((unsigned int)1, loop1->getStep()); CPPUNIT_ASSERT_EQUAL(1U, loop1->getStep());
SharedHandle<PStringSegment> segment2 = loop1->getNext(); SharedHandle<PStringSegment> segment2 = loop1->getNext();
CPPUNIT_ASSERT(!segment2.isNull()); CPPUNIT_ASSERT(!segment2.isNull());

View File

@ -39,6 +39,7 @@ class UtilTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testParseIntRange); CPPUNIT_TEST(testParseIntRange);
CPPUNIT_TEST(testParseIntRange_invalidRange); CPPUNIT_TEST(testParseIntRange_invalidRange);
CPPUNIT_TEST(testParseInt); CPPUNIT_TEST(testParseInt);
CPPUNIT_TEST(testParseUInt);
CPPUNIT_TEST(testParseLLInt); CPPUNIT_TEST(testParseLLInt);
CPPUNIT_TEST(testToString_binaryStream); CPPUNIT_TEST(testToString_binaryStream);
CPPUNIT_TEST(testItos); CPPUNIT_TEST(testItos);
@ -75,6 +76,7 @@ public:
void testParseIntRange(); void testParseIntRange();
void testParseIntRange_invalidRange(); void testParseIntRange_invalidRange();
void testParseInt(); void testParseInt();
void testParseUInt();
void testParseLLInt(); void testParseLLInt();
void testToString_binaryStream(); void testToString_binaryStream();
void testItos(); void testItos();
@ -412,12 +414,14 @@ void UtilTest::testIsUppercase()
void UtilTest::testAlphaToNum() void UtilTest::testAlphaToNum()
{ {
CPPUNIT_ASSERT_EQUAL(0, Util::alphaToNum("a")); CPPUNIT_ASSERT_EQUAL(0U, Util::alphaToNum("a"));
CPPUNIT_ASSERT_EQUAL(0, Util::alphaToNum("aa")); CPPUNIT_ASSERT_EQUAL(0U, Util::alphaToNum("aa"));
CPPUNIT_ASSERT_EQUAL(1, Util::alphaToNum("b")); CPPUNIT_ASSERT_EQUAL(1U, Util::alphaToNum("b"));
CPPUNIT_ASSERT_EQUAL(675, Util::alphaToNum("zz")); // 25*26+25 CPPUNIT_ASSERT_EQUAL(675U, Util::alphaToNum("zz")); // 25*26+25
CPPUNIT_ASSERT_EQUAL(675, Util::alphaToNum("ZZ")); // 25*26+25 CPPUNIT_ASSERT_EQUAL(675U, Util::alphaToNum("ZZ")); // 25*26+25
CPPUNIT_ASSERT_EQUAL(0, Util::alphaToNum("")); CPPUNIT_ASSERT_EQUAL(0U, Util::alphaToNum(""));
CPPUNIT_ASSERT_EQUAL(4294967295U, Util::alphaToNum("NXMRLXV"));
CPPUNIT_ASSERT_EQUAL(0U, Util::alphaToNum("NXMRLXW")); // uint32_t overflow
} }
void UtilTest::testMkdirs() void UtilTest::testMkdirs()
@ -522,8 +526,8 @@ void UtilTest::testParseIntRange_invalidRange()
void UtilTest::testParseInt() void UtilTest::testParseInt()
{ {
CPPUNIT_ASSERT_EQUAL((int32_t)-1, Util::parseInt(" -1 ")); CPPUNIT_ASSERT_EQUAL(-1, Util::parseInt(" -1 "));
CPPUNIT_ASSERT_EQUAL((int32_t)2147483647, Util::parseInt("2147483647")); CPPUNIT_ASSERT_EQUAL(2147483647, Util::parseInt("2147483647"));
try { try {
Util::parseInt("2147483648"); Util::parseInt("2147483648");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
@ -554,10 +558,29 @@ void UtilTest::testParseInt()
} }
} }
void UtilTest::testParseUInt()
{
CPPUNIT_ASSERT_EQUAL(4294967295U, Util::parseUInt(" 4294967295 "));
try {
Util::parseUInt("-1");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
std::cerr << *e;
delete e;
}
try {
Util::parseUInt("4294967296");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
std::cerr << *e;
delete e;
}
}
void UtilTest::testParseLLInt() void UtilTest::testParseLLInt()
{ {
CPPUNIT_ASSERT_EQUAL((int64_t)-1, Util::parseLLInt(" -1 ")); CPPUNIT_ASSERT_EQUAL(-1LL, Util::parseLLInt(" -1 "));
CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775807LL, CPPUNIT_ASSERT_EQUAL(9223372036854775807LL,
Util::parseLLInt("9223372036854775807")); Util::parseLLInt("9223372036854775807"));
try { try {
Util::parseLLInt("9223372036854775808"); Util::parseLLInt("9223372036854775808");