mirror of https://github.com/aria2/aria2
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
parent
7f40794931
commit
68b84574ae
14
ChangeLog
14
ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
34
src/Util.cc
34
src/Util.cc
|
@ -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;
|
||||
}
|
||||
|
|
19
src/Util.h
19
src/Util.h
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue