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>
Rewritten the functions for binding port.

View File

@ -45,9 +45,9 @@ class PStringNumLoop : public PStringDatum
{
private:
int _startValue;
unsigned int _startValue;
int _endValue;
unsigned int _endValue;
unsigned int _step;
@ -56,7 +56,8 @@ private:
PStringDatumHandle _next;
public:
PStringNumLoop(int startValue, int endValue, unsigned int step,
PStringNumLoop(unsigned int startValue, unsigned int endValue,
unsigned int step,
const NumberDecoratorHandle& nd,
const PStringDatumHandle& next = 0):
_startValue(startValue),
@ -69,7 +70,7 @@ public:
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);
}
}
@ -79,12 +80,12 @@ public:
return _next;
}
int getStartValue() const
unsigned int getStartValue() const
{
return _startValue;
}
int getEndValue() const
unsigned int getEndValue() const
{
return _endValue;
}

View File

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

View File

@ -417,6 +417,31 @@ int32_t Util::parseInt(const std::string& s, int32_t base)
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)
{
std::string trimed = Util::trim(s);
@ -730,7 +755,7 @@ bool Util::isUppercase(const std::string& what)
return true;
}
int Util::alphaToNum(const std::string& alphabets)
unsigned int Util::alphaToNum(const std::string& alphabets)
{
if(alphabets.empty()) {
return 0;
@ -741,10 +766,13 @@ int Util::alphaToNum(const std::string& alphabets)
} else {
base = 'A';
}
int num = 0;
uint64_t num = 0;
for(size_t i = 0; i < alphabets.size(); ++i) {
int v = alphabets[i]-base;
unsigned int v = alphabets[i]-base;
num = num*26+v;
if(num > UINT32_MAX) {
return 0;
}
}
return num;
}

View File

@ -167,6 +167,8 @@ public:
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 IntSequence parseIntRange(const std::string& src);
@ -205,14 +207,21 @@ public:
static void sleep(long seconds);
static void usleep(long microseconds);
static bool isNumber(const std::string& what);
static bool isLowercase(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);

View File

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

View File

@ -39,6 +39,7 @@ class UtilTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testParseIntRange);
CPPUNIT_TEST(testParseIntRange_invalidRange);
CPPUNIT_TEST(testParseInt);
CPPUNIT_TEST(testParseUInt);
CPPUNIT_TEST(testParseLLInt);
CPPUNIT_TEST(testToString_binaryStream);
CPPUNIT_TEST(testItos);
@ -75,6 +76,7 @@ public:
void testParseIntRange();
void testParseIntRange_invalidRange();
void testParseInt();
void testParseUInt();
void testParseLLInt();
void testToString_binaryStream();
void testItos();
@ -412,12 +414,14 @@ void UtilTest::testIsUppercase()
void UtilTest::testAlphaToNum()
{
CPPUNIT_ASSERT_EQUAL(0, Util::alphaToNum("a"));
CPPUNIT_ASSERT_EQUAL(0, Util::alphaToNum("aa"));
CPPUNIT_ASSERT_EQUAL(1, Util::alphaToNum("b"));
CPPUNIT_ASSERT_EQUAL(675, Util::alphaToNum("zz")); // 25*26+25
CPPUNIT_ASSERT_EQUAL(675, Util::alphaToNum("ZZ")); // 25*26+25
CPPUNIT_ASSERT_EQUAL(0, Util::alphaToNum(""));
CPPUNIT_ASSERT_EQUAL(0U, Util::alphaToNum("a"));
CPPUNIT_ASSERT_EQUAL(0U, Util::alphaToNum("aa"));
CPPUNIT_ASSERT_EQUAL(1U, Util::alphaToNum("b"));
CPPUNIT_ASSERT_EQUAL(675U, Util::alphaToNum("zz")); // 25*26+25
CPPUNIT_ASSERT_EQUAL(675U, Util::alphaToNum("ZZ")); // 25*26+25
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()
@ -522,8 +526,8 @@ void UtilTest::testParseIntRange_invalidRange()
void UtilTest::testParseInt()
{
CPPUNIT_ASSERT_EQUAL((int32_t)-1, Util::parseInt(" -1 "));
CPPUNIT_ASSERT_EQUAL((int32_t)2147483647, Util::parseInt("2147483647"));
CPPUNIT_ASSERT_EQUAL(-1, Util::parseInt(" -1 "));
CPPUNIT_ASSERT_EQUAL(2147483647, Util::parseInt("2147483647"));
try {
Util::parseInt("2147483648");
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()
{
CPPUNIT_ASSERT_EQUAL((int64_t)-1, Util::parseLLInt(" -1 "));
CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775807LL,
CPPUNIT_ASSERT_EQUAL(-1LL, Util::parseLLInt(" -1 "));
CPPUNIT_ASSERT_EQUAL(9223372036854775807LL,
Util::parseLLInt("9223372036854775807"));
try {
Util::parseLLInt("9223372036854775808");