Changed parse*Int functions so that it accepts iterators.

pull/2/head
Tatsuhiro Tsujikawa 2011-11-03 18:51:31 +09:00
parent 6ef91d60b3
commit 9bb914b76e
24 changed files with 435 additions and 260 deletions

View File

@ -608,7 +608,7 @@ bool inNoProxy(const SharedHandle<Request>& req,
// evaluates against all of them
std::string ip = (*i).substr(0, slashpos);
uint32_t bits;
if(!util::parseUIntNoThrow(bits, (*i).substr(slashpos+1))) {
if(!util::parseUIntNoThrow(bits, (*i).begin()+slashpos+1, (*i).end())) {
continue;
}
if(util::inSameCidrBlock(ip, req->getHost(), bits)) {

View File

@ -96,7 +96,7 @@ bool ChunkedDecodingStreamFilter::readChunkSize
if(extPos == std::string::npos || crlfPos < extPos) {
extPos = crlfPos;
}
chunkSize_ = util::parseULLInt(buf_.substr(0, extPos), 16);
chunkSize_ = util::parseULLInt(buf_.begin(), buf_.begin()+extPos, 16);
assert(crlfPos+2 > pbufSize);
inbufOffset += crlfPos+2-pbufSize;
buf_.clear();

View File

@ -434,7 +434,7 @@ unsigned int FtpConnection::receiveSizeResponse(uint64_t& size)
if(response.first == 213) {
std::pair<std::string, std::string> rp;
util::divide(rp, response.second, ' ');
size = util::parseULLInt(rp.second);
size = util::parseULLInt(rp.second.begin(), rp.second.end());
}
return response.first;
} else {
@ -455,17 +455,12 @@ unsigned int FtpConnection::receiveMdtmResponse(Time& time)
// and included strptime doesn't parse data for this format.
struct tm tm;
memset(&tm, 0, sizeof(tm));
tm.tm_sec = util::parseInt(&buf[12]);
buf[12] = '\0';
tm.tm_min = util::parseInt(&buf[10]);
buf[10] = '\0';
tm.tm_hour = util::parseInt(&buf[8]);
buf[8] = '\0';
tm.tm_mday = util::parseInt(&buf[6]);
buf[6] = '\0';
tm.tm_mon = util::parseInt(&buf[4])-1;
buf[4] = '\0';
tm.tm_year = util::parseInt(&buf[0])-1900;
tm.tm_sec = util::parseInt(&buf[12], &buf[14]);
tm.tm_min = util::parseInt(&buf[10], &buf[12]);
tm.tm_hour = util::parseInt(&buf[8], &buf[10]);
tm.tm_mday = util::parseInt(&buf[6], &buf[8]);
tm.tm_mon = util::parseInt(&buf[4], &buf[6])-1;
tm.tm_year = util::parseInt(&buf[0], &buf[4])-1900;
time = Time(timegm(&tm));
} else {
time = Time::null();
@ -493,7 +488,8 @@ unsigned int FtpConnection::receiveEpsvResponse(uint16_t& port)
util::split(response.second.substr(leftParen+1, rightParen-(leftParen+1)),
std::back_inserter(rd), "|", true, true);
uint32_t portTemp = 0;
if(rd.size() == 5 && util::parseUIntNoThrow(portTemp, rd[3])) {
if(rd.size() == 5 &&
util::parseUIntNoThrow(portTemp, rd[3].begin(), rd[3].end())) {
if(0 < portTemp && portTemp <= UINT16_MAX) {
port = portTemp;
}

View File

@ -128,7 +128,7 @@ uint64_t HttpHeader::getFirstAsULLInt(const std::string& name) const {
if(value.empty()) {
return 0;
} else {
return util::parseULLInt(value);
return util::parseULLInt(value.begin(), value.end());
}
}
@ -136,11 +136,12 @@ RangeHandle HttpHeader::getRange() const
{
const std::string& rangeStr = getFirst(CONTENT_RANGE);
if(rangeStr.empty()) {
const std::string& contentLengthStr = getFirst(CONTENT_LENGTH);
if(contentLengthStr.empty()) {
const std::string& clenStr = getFirst(CONTENT_LENGTH);
if(clenStr.empty()) {
return SharedHandle<Range>(new Range());
} else {
uint64_t contentLength = util::parseULLInt(contentLengthStr);
uint64_t contentLength =
util::parseULLInt(clenStr.begin(), clenStr.end());
if(contentLength == 0) {
return SharedHandle<Range>(new Range());
} else {
@ -177,9 +178,9 @@ RangeHandle HttpHeader::getRange() const
if(minus == slash) {
return SharedHandle<Range>(new Range());
}
off_t startByte = util::parseLLInt(std::string(byteRangeSpec, minus));
off_t endByte = util::parseLLInt(std::string(minus+1, slash));
uint64_t entityLength = util::parseULLInt(std::string(slash+1, rangeStr.end()));
off_t startByte = util::parseLLInt(byteRangeSpec, minus);
off_t endByte = util::parseLLInt(minus+1, slash);
uint64_t entityLength = util::parseULLInt(slash+1, rangeStr.end());
return SharedHandle<Range>(new Range(startByte, endByte, entityLength));
}

View File

@ -112,7 +112,7 @@ SharedHandle<HttpHeader> HttpHeaderProcessor::getHttpResponseHeader()
throw DL_RETRY_EX(EX_NO_STATUS_HEADER);
}
int32_t statusCode;
if(!util::parseIntNoThrow(statusCode, buf_.substr(9, 3))) {
if(!util::parseIntNoThrow(statusCode, buf_.begin()+9, buf_.begin()+12)) {
throw DL_RETRY_EX("Status code could not be parsed as integer.");
}
HttpHeaderHandle httpHeader(new HttpHeader());

View File

@ -342,7 +342,7 @@ bool parseMetalinkHttpLink(MetalinkHttpEntry& result, const std::string& s)
}
} else if(name == "pri") {
int32_t priValue;
if(util::parseIntNoThrow(priValue, value)) {
if(util::parseIntNoThrow(priValue, value.begin(), value.end())) {
if(1 <= priValue && priValue <= 999999) {
result.pri = priValue;
}

View File

@ -230,7 +230,8 @@ SRCS = Socket.h\
console.cc console.h\
BufferedFile.cc BufferedFile.h\
SegList.h\
NullHandle.h
NullHandle.h\
a2iterator.h
if MINGW_BUILD
SRCS += WinConsoleFile.cc WinConsoleFile.h

View File

@ -155,7 +155,8 @@ void FileMetalinkParserState::beginElement
maxConnections = -1;
} else {
try {
maxConnections = util::parseInt((*itr).value);
maxConnections =
util::parseInt((*itr).value.begin(), (*itr).value.end());
} catch(RecoverableException& e) {
maxConnections = -1;
}
@ -185,7 +186,8 @@ void SizeMetalinkParserState::endElement
const std::string& characters)
{
try {
stm->setFileLengthOfEntry(util::parseULLInt(characters));
stm->setFileLengthOfEntry
(util::parseULLInt(characters.begin(), characters.end()));
} catch(RecoverableException& e) {
// current metalink specification doesn't require size element.
}
@ -251,7 +253,7 @@ void VerificationMetalinkParserState::beginElement
if(itr == attrs.end()) {
return;
} else {
length = util::parseInt((*itr).value);
length = util::parseInt((*itr).value.begin(), (*itr).value.end());
}
}
std::string type;
@ -317,7 +319,8 @@ void PiecesMetalinkParserState::beginElement
stm->cancelChunkChecksumTransaction();
} else {
try {
stm->createNewHashOfChunkChecksum(util::parseInt((*itr).value));
stm->createNewHashOfChunkChecksum
(util::parseInt((*itr).value.begin(), (*itr).value.end()));
} catch(RecoverableException& e) {
stm->cancelChunkChecksumTransaction();
}
@ -396,7 +399,8 @@ void ResourcesMetalinkParserState::beginElement
// In Metalink3Spec, highest prefernce value is 100. We
// uses Metalink4Spec priority unit system in which 1 is
// higest.
preference = 101-util::parseInt((*itr).value);
preference =
101-util::parseInt((*itr).value.begin(), (*itr).value.end());
} catch(RecoverableException& e) {
preference = MetalinkResource::getLowestPriority();
}
@ -409,7 +413,8 @@ void ResourcesMetalinkParserState::beginElement
maxConnections = -1;
} else {
try {
maxConnections = util::parseInt((*itr).value);
maxConnections =
util::parseInt((*itr).value.begin(), (*itr).value.end());
} catch(RecoverableException& e) {
maxConnections = -1;
}

View File

@ -151,7 +151,7 @@ void FileMetalinkParserStateV4::beginElement
priority = MetalinkResource::getLowestPriority();
} else {
try {
priority = util::parseInt((*itr).value);
priority = util::parseInt((*itr).value.begin(), (*itr).value.end());
if(priority < 1 || MetalinkResource::getLowestPriority() < priority) {
stm->logError("metaurl@priority is out of range");
return;
@ -192,7 +192,7 @@ void FileMetalinkParserStateV4::beginElement
priority = MetalinkResource::getLowestPriority();
} else {
try {
priority = util::parseInt((*itr).value);
priority = util::parseInt((*itr).value.begin(), (*itr).value.end());
if(priority < 1 || MetalinkResource::getLowestPriority() < priority) {
stm->logError("url@priority is out of range");
return;
@ -229,7 +229,7 @@ void FileMetalinkParserStateV4::beginElement
return;
} else {
try {
length = util::parseInt((*itr).value);
length = util::parseInt((*itr).value.begin(), (*itr).value.end());
} catch(RecoverableException& e) {
stm->logError("Bad pieces@length");
return;
@ -283,7 +283,8 @@ void SizeMetalinkParserStateV4::endElement
const std::string& characters)
{
try {
stm->setFileLengthOfEntry(util::parseULLInt(characters));
stm->setFileLengthOfEntry
(util::parseULLInt(characters.begin(), characters.end()));
} catch(RecoverableException& e) {
stm->cancelEntryTransaction();
stm->logError("Bad size");

View File

@ -71,7 +71,7 @@ bool parseNsCookie
return false;
}
int64_t expiryTime;
if(!util::parseLLIntNoThrow(expiryTime, vs[4])) {
if(!util::parseLLIntNoThrow(expiryTime, vs[4].begin(), vs[4].end())) {
return false;
}
if(std::numeric_limits<time_t>::max() < expiryTime) {

View File

@ -152,7 +152,7 @@ NumberOptionHandler::~NumberOptionHandler() {}
void NumberOptionHandler::parseArg(Option& option, const std::string& optarg)
{
int64_t num = util::parseLLInt(optarg);
int64_t num = util::parseLLInt(optarg.begin(), optarg.end());
parseArg(option, num);
}

View File

@ -118,7 +118,7 @@ ParameterizedStringParser::createLoop(const std::string& src, int& offset)
if(colonIndex != std::string::npos) {
std::string stepStr = loopStr.substr(colonIndex+1);
if(util::isNumber(stepStr)) {
step = util::parseUInt(stepStr);
step = util::parseUInt(loopStr.begin()+colonIndex+1, loopStr.end());
} else {
throw DL_ABORT_EX("A step count must be a positive number.");
}
@ -134,8 +134,8 @@ ParameterizedStringParser::createLoop(const std::string& src, int& offset)
unsigned int end;
if(util::isNumber(range.first) && util::isNumber(range.second)) {
nd.reset(new FixedWidthNumberDecorator(range.first.size()));
start = util::parseUInt(range.first);
end = util::parseUInt(range.second);
start = util::parseUInt(range.first.begin(), range.first.end());
end = util::parseUInt(range.second.begin(), range.second.end());
} else if(util::isLowercase(range.first) && util::isLowercase(range.second)) {
nd.reset(new AlphaNumberDecorator(range.first.size()));
start = util::alphaToNum(range.first);

View File

@ -197,7 +197,7 @@ namespace {
a2_gid_t str2Gid(const String* str)
{
assert(str);
return util::parseLLInt(str->s());
return util::parseLLInt(str->s().begin(), str->s().end());
}
} // namespace

View File

@ -171,20 +171,26 @@ bool ServerStatMan::load(const std::string& filename)
}
SharedHandle<ServerStat> sstat(new ServerStat(m[S_HOST], m[S_PROTOCOL]));
try {
sstat->setDownloadSpeed(util::parseUInt(m[S_DL_SPEED]));
const std::string& dlSpeed = m[S_DL_SPEED];
sstat->setDownloadSpeed(util::parseUInt(dlSpeed.begin(), dlSpeed.end()));
// Old serverstat file doesn't contains SC_AVG_SPEED
if(m.find(S_SC_AVG_SPEED) != m.end()) {
sstat->setSingleConnectionAvgSpeed(util::parseUInt(m[S_SC_AVG_SPEED]));
const std::string& s = m[S_SC_AVG_SPEED];
sstat->setSingleConnectionAvgSpeed(util::parseUInt(s.begin(), s.end()));
}
// Old serverstat file doesn't contains MC_AVG_SPEED
if(m.find(S_MC_AVG_SPEED) != m.end()) {
sstat->setMultiConnectionAvgSpeed(util::parseUInt(m[S_MC_AVG_SPEED]));
const std::string& s = m[S_MC_AVG_SPEED];
sstat->setMultiConnectionAvgSpeed(util::parseUInt(s.begin(), s.end()));
}
// Old serverstat file doesn't contains COUNTER_SPEED
if(m.find(S_COUNTER) != m.end()) {
sstat->setCounter(util::parseUInt(m[S_COUNTER]));
const std::string& s = m[S_COUNTER];
sstat->setCounter(util::parseUInt(s.begin(), s.end()));
}
sstat->setLastUpdated(Time(util::parseInt(m[S_LAST_UPDATED])));
const std::string& lastUpdated = m[S_LAST_UPDATED];
sstat->setLastUpdated
(Time(util::parseInt(lastUpdated.begin(), lastUpdated.end())));
sstat->setStatus(m[S_STATUS]);
add(sstat);
} catch(RecoverableException& e) {

View File

@ -82,9 +82,10 @@ std::string toString(const char* str)
} // namespace
namespace {
bool parseTime(int64_t& time, const std::string& s)
template<typename InputIterator>
bool parseTime(int64_t& time, InputIterator first, InputIterator last)
{
if(!util::parseLLIntNoThrow(time, s)) {
if(!util::parseLLIntNoThrow(time, first, last)) {
return false;
}
if(std::numeric_limits<time_t>::max() < time) {
@ -112,11 +113,13 @@ int cookieRowMapper(void* data, int columns, char** values, char** names)
return 0;
}
int64_t expiryTime;
if(!parseTime(expiryTime, toString(values[3]))) {
if(!values[3] ||
!parseTime(expiryTime, &values[3][0], &values[3][strlen(values[3])])) {
return 0;
}
int64_t lastAccessTime;
if(!parseTime(lastAccessTime, toString(values[6]))) {
if(!values[6] ||
!parseTime(lastAccessTime, &values[6][0], &values[6][strlen(values[6])])) {
return 0;
}
Cookie c(cookieName,
@ -124,9 +127,10 @@ int cookieRowMapper(void* data, int columns, char** values, char** names)
expiryTime,
true, // persistent
cookieDomain,
util::isNumericHost(cookieDomain) || values[0][0] != '.', // hostOnly
util::isNumericHost(cookieDomain) ||
(values[0] && values[0][0] != '.'), // hostOnly
cookiePath,
strcmp(toString(values[2]).c_str(), "1") == 0, //secure
values[2] && strcmp(values[2], "1") == 0, //secure
false,
lastAccessTime // creation time. Set this later.
);
@ -151,8 +155,7 @@ void Sqlite3CookieParser::parse(std::vector<Cookie>& cookies)
}
if(SQLITE_OK != ret) {
throw DL_ABORT_EX
(fmt("Failed to read SQLite3 database: %s",
errMsg.c_str()));
(fmt("Failed to read SQLite3 database: %s", errMsg.c_str()));
}
cookies.swap(tcookies);
}

View File

@ -198,7 +198,7 @@ void IntXmlRpcRequestParserState::endElement
const std::string& characters)
{
try {
int64_t value = util::parseLLInt(characters);
int64_t value = util::parseLLInt(characters.begin(), characters.end());
stm->setCurrentFrameValue(Integer::g(value));
} catch(RecoverableException& e) {
// nothing to do here: We just leave current frame value to null.

52
src/a2iterator.h Normal file
View File

@ -0,0 +1,52 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_A2_ITERATOR_H
#define D_A2_ITERATOR_H
#include "common.h"
#include <string>
namespace aria2 {
typedef std::pair<std::string::const_iterator,
std::string::const_iterator> Scip;
typedef std::pair<std::string::iterator,
std::string::iterator> Sip;
} // namespace aria2
#endif // D_A2_ITERATOR_H

View File

@ -117,9 +117,9 @@ bool parseDate
goto NOT_TIME;
}
foundTime = true;
hour = util::parseInt(std::string((*i).begin(), hEnd));
minute = util::parseInt(std::string(hEnd+1, mEnd));
second = util::parseInt(std::string(mEnd+1, sEnd));
hour = util::parseInt((*i).begin(), hEnd);
minute = util::parseInt(hEnd+1, mEnd);
second = util::parseInt(mEnd+1, sEnd);
continue;
NOT_TIME:
;
@ -129,7 +129,7 @@ bool parseDate
size_t len = std::distance((*i).begin(), j);
if(1 <= len && len <= 2) {
foundDayOfMonth = true;
dayOfMonth = util::parseInt(std::string((*i).begin(), j));
dayOfMonth = util::parseInt((*i).begin(), j);
continue;
}
}
@ -154,7 +154,7 @@ bool parseDate
size_t len = std::distance((*i).begin(), j);
if(1 <= len && len <= 4) {
foundYear = true;
year = util::parseInt(std::string((*i).begin(), j));
year = util::parseInt((*i).begin(), j);
continue;
}
}
@ -273,8 +273,7 @@ bool parse
}
}
int64_t delta;
if(util::parseLLIntNoThrow(delta,
std::string(attrp.first, attrp.second))) {
if(util::parseLLIntNoThrow(delta, attrp.first, attrp.second)) {
foundMaxAge = true;
if(delta <= 0) {
maxAge = 0;

View File

@ -161,13 +161,12 @@ decodeString
checkEof(first, last);
if(*first == 'u') {
++first;
std::string uchars;
std::string::const_iterator uchars = first;
for(int i = 0; i < 4; ++i, ++first) {
checkEof(first, last);
uchars += *first;
}
checkEof(first, last);
uint16_t codepoint = util::parseUInt(uchars, 16);
uint16_t codepoint = util::parseUInt(uchars, first, 16);
if(codepoint <= 0x007fu) {
s += static_cast<char>(codepoint);
} else if(codepoint <= 0x07ffu) {
@ -183,13 +182,12 @@ decodeString
error_code::JSON_PARSE_ERROR);
}
first += 2;
std::string uchars;
std::string::const_iterator uchars = first;
for(int i = 0; i < 4; ++i, ++first) {
checkEof(first, last);
uchars += *first;
}
checkEof(first, last);
uint16_t codepoint2 = util::parseUInt(uchars, 16);
uint16_t codepoint2 = util::parseUInt(uchars, first, 16);
if(!in(codepoint2, 0xDC00u, 0xDFFFu)) {
throw DL_ABORT_EX2("JSON decoding failed: bad UTF-8 sequence.",
error_code::JSON_PARSE_ERROR);
@ -290,7 +288,7 @@ decodeNumber
checkEof(first, last);
checkEmptyDigit(offset, first);
checkLeadingZero(offset, first);
s += std::string(offset, first);
s.append(offset, first);
bool fp = false;
if(*first == '.') {
fp = true;
@ -302,7 +300,7 @@ decodeNumber
}
checkEof(first, last);
checkEmptyDigit(offset, first);
s += std::string(offset, first);
s.append(offset, first);
}
if(*first == 'e') {
fp = true;
@ -319,14 +317,14 @@ decodeNumber
}
checkEof(first, last);
checkEmptyDigit(offset, first);
s += std::string(offset, first);
s.append(offset, first);
}
if(fp) {
// Since we don't have floating point coutner part in ValueBase,
// we just treat it as string.
return std::make_pair(String::g(s), first);
} else {
Integer::ValueType val = util::parseLLInt(s);
Integer::ValueType val = util::parseLLInt(s.begin(), s.end());
return std::make_pair(Integer::g(val), first);
}
}

View File

@ -211,7 +211,7 @@ bool parse(UriStruct& result, const std::string& uri)
result.port = defPort;
} else {
uint32_t tempPort;
if(util::parseUIntNoThrow(tempPort, std::string(portFirst, authorityLast))){
if(util::parseUIntNoThrow(tempPort, portFirst, authorityLast)) {
if(65535 < tempPort) {
return false;
}

View File

@ -35,8 +35,6 @@
#include "util.h"
#include <signal.h>
#include <limits.h>
#include <stdint.h>
#include <cerrno>
#include <cassert>
@ -51,15 +49,12 @@
#include "SimpleRandomizer.h"
#include "File.h"
#include "message.h"
#include "Randomizer.h"
#include "a2netcompat.h"
#include "DlAbortEx.h"
#include "BitfieldMan.h"
#include "DefaultDiskWriter.h"
#include "FatalException.h"
#include "FileEntry.h"
#include "fmt.h"
#include "A2STR.h"
#include "array_fun.h"
#include "bitfield.h"
@ -496,7 +491,7 @@ std::string percentDecode(const std::string& target) {
if(*itr == '%') {
if(itr+1 != target.end() && itr+2 != target.end() &&
isHexDigit(*(itr+1)) && isHexDigit(*(itr+2))) {
result += parseInt(std::string(itr+1, itr+3), 16);
result += parseInt(itr+1, itr+3, 16);
itr += 2;
} else {
result += *itr;
@ -625,133 +620,6 @@ int getNum(const char* buf, int offset, size_t length) {
return x;
}
int32_t parseInt(const std::string& s, int32_t base)
{
int64_t v = parseLLInt(s, base);
if(v < INT32_MIN || INT32_MAX < v) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
s.c_str()));
}
return v;
}
bool parseIntNoThrow(int32_t& result, const std::string& s, int base)
{
// Without trim, strtol(" -1 ",..) emits error.
std::string trimed = strip(s);
if(trimed.empty()) {
return false;
}
char* stop;
errno = 0;
long int v = strtol(trimed.c_str(), &stop, base);
if(*stop != '\0') {
return false;
} else if(((v == LONG_MAX || v == LONG_MIN) && (errno == ERANGE)) ||
v < INT32_MIN || INT32_MAX < v) {
return false;
}
result = v;
return true;
}
uint32_t parseUInt(const std::string& s, int base)
{
uint64_t v = parseULLInt(s, base);
if(UINT32_MAX < v) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
s.c_str()));
}
return v;
}
bool parseUIntNoThrow(uint32_t& result, const std::string& s, int base)
{
// Without trim, strtol(" -1 ",..) emits error.
std::string trimed = strip(s);
if(trimed.empty()) {
return false;
}
// We don't allow negative number.
if(trimed[0] == '-') {
return false;
}
char* stop;
errno = 0;
unsigned long int v = strtoul(trimed.c_str(), &stop, base);
if(*stop != '\0') {
return false;
} else if(((v == ULONG_MAX) && (errno == ERANGE)) || (v > UINT32_MAX)) {
return false;
}
result = v;
return true;
}
int64_t parseLLInt(const std::string& s, int32_t base)
{
std::string trimed = strip(s);
if(trimed.empty()) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
"empty string"));
}
char* stop;
errno = 0;
int64_t v = strtoll(trimed.c_str(), &stop, base);
if(*stop != '\0') {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
trimed.c_str()));
} else if(((v == INT64_MIN) || (v == INT64_MAX)) && (errno == ERANGE)) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
trimed.c_str()));
}
return v;
}
bool parseLLIntNoThrow(int64_t& result, const std::string& s, int base)
{
// Without trim, strtol(" -1 ",..) emits error.
std::string trimed = strip(s);
if(trimed.empty()) {
return false;
}
char* stop;
errno = 0;
int64_t v = strtoll(trimed.c_str(), &stop, base);
if(*stop != '\0') {
return false;
} else if(((v == INT64_MIN) || (v == INT64_MAX)) && (errno == ERANGE)) {
return false;
}
result = v;
return true;
}
uint64_t parseULLInt(const std::string& s, int base)
{
std::string trimed = strip(s);
if(trimed.empty()) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
"empty string"));
}
// We don't allow negative number.
if(trimed[0] == '-') {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
trimed.c_str()));
}
char* stop;
errno = 0;
uint64_t v = strtoull(trimed.c_str(), &stop, base);
if(*stop != '\0') {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
trimed.c_str()));
} else if((v == ULLONG_MAX) && (errno == ERANGE)) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
trimed.c_str()));
}
return v;
}
void parseIntSegments(SegList<int>& sgl, const std::string& src)
{
for(std::string::const_iterator i = src.begin(), eoi = src.end(); i != eoi;) {
@ -762,13 +630,13 @@ void parseIntSegments(SegList<int>& sgl, const std::string& src)
}
std::string::const_iterator p = std::find(i, j, '-');
if(p == j) {
int a = parseInt(std::string(i, j));
int a = parseInt(i, j);
sgl.add(a, a+1);
} else if(p == i || p+1 == j) {
throw DL_ABORT_EX(fmt(MSG_INCOMPLETE_RANGE, std::string(i, j).c_str()));
} else {
int a = parseInt(std::string(i, p));
int b = parseInt(std::string(p+1, j));
int a = parseInt(i, p);
int b = parseInt(p+1, j);
sgl.add(a, b+1);
}
if(j == eoi) {
@ -1139,7 +1007,7 @@ int64_t getRealSize(const std::string& sizeWithUnit)
}
size = sizeWithUnit.substr(0, p);
}
int64_t v = parseLLInt(size);
int64_t v = parseLLInt(size.begin(), size.end());
if(v < 0) {
throw DL_ABORT_EX(fmt("Negative value detected: %s", sizeWithUnit.c_str()));
@ -1381,7 +1249,7 @@ parseIndexPath(const std::string& line)
{
std::pair<std::string, std::string> p;
divide(p, line, '=');
size_t index = parseUInt(p.first);
size_t index = parseUInt(p.first.begin(), p.first.end());
if(p.second.empty()) {
throw DL_ABORT_EX(fmt("Path with index=%u is empty.",
static_cast<unsigned int>(index)));

View File

@ -38,6 +38,8 @@
#include "common.h"
#include <sys/time.h>
#include <limits.h>
#include <stdint.h>
#include <cstdio>
#include <string>
@ -55,6 +57,10 @@
#include "a2netcompat.h"
#include "a2functional.h"
#include "SegList.h"
#include "a2iterator.h"
#include "message.h"
#include "DlAbortEx.h"
#include "fmt.h"
namespace aria2 {
@ -201,19 +207,174 @@ bool isPowerOf(int num, int base);
std::string secfmt(time_t sec);
int32_t parseInt(const std::string& s, int32_t base = 10);
template<typename InputIterator>
bool parseIntNoThrow
(int32_t& result, InputIterator first, InputIterator last, int base = 10)
{
// Without strip, strtol(" -1 ",..) emits error.
Scip p = util::stripIter(first, last);
if(p.first == p.second) {
return false;
}
char buf[32];
size_t len = std::distance(p.first, p.second);
if(len+1 > sizeof(buf)) {
return false;
}
std::copy(p.first, p.second, &buf[0]);
buf[len] = '\0';
char* stop;
errno = 0;
long int v = strtol(buf, &stop, base);
if(*stop != '\0') {
return false;
} else if(((v == LONG_MAX || v == LONG_MIN) && (errno == ERANGE)) ||
v < INT32_MIN || INT32_MAX < v) {
return false;
}
result = v;
return true;
}
bool parseIntNoThrow(int32_t& result, const std::string& s, int base = 10);
template<typename InputIterator>
bool parseUIntNoThrow
(uint32_t& result, InputIterator first, InputIterator last, int base = 10)
{
// Without strip, strtol(" -1 ",..) emits error.
Scip p = util::stripIter(first, last);
if(p.first == p.second) {
return false;
}
char buf[32];
size_t len = std::distance(p.first, p.second);
if(len+1 > sizeof(buf)) {
return false;
}
std::copy(p.first, p.second, &buf[0]);
buf[len] = '\0';
// We don't allow negative number.
if(buf[0] == '-') {
return false;
}
char* stop;
errno = 0;
unsigned long int v = strtoul(buf, &stop, base);
if(*stop != '\0') {
return false;
} else if(((v == ULONG_MAX) && (errno == ERANGE)) || (v > UINT32_MAX)) {
return false;
}
result = v;
return true;
}
uint32_t parseUInt(const std::string& s, int base = 10);
bool parseUIntNoThrow(uint32_t& result, const std::string& s, int base = 10);
template<typename InputIterator>
bool parseLLIntNoThrow
(int64_t& result, InputIterator first, InputIterator last, int base = 10)
{
// Without strip, strtol(" -1 ",..) emits error.
Scip p = util::stripIter(first, last);
if(p.first == p.second) {
return false;
}
char buf[32];
size_t len = std::distance(p.first, p.second);
if(len+1 > sizeof(buf)) {
return false;
}
std::copy(p.first, p.second, &buf[0]);
buf[len] = '\0';
char* stop;
errno = 0;
int64_t v = strtoll(buf, &stop, base);
if(*stop != '\0') {
return false;
} else if(((v == INT64_MIN) || (v == INT64_MAX)) && (errno == ERANGE)) {
return false;
}
result = v;
return true;
}
int64_t parseLLInt(const std::string& s, int32_t base = 10);
template<typename InputIterator>
int64_t parseLLInt(InputIterator first, InputIterator last, int base = 10)
{
Scip p = util::stripIter(first, last);
if(p.first == p.second) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
"empty string"));
}
char buf[32];
size_t len = std::distance(p.first, p.second);
if(len+1 > sizeof(buf)) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
"too large"));
}
std::copy(p.first, p.second, &buf[0]);
buf[len] = '\0';
char* stop;
errno = 0;
int64_t v = strtoll(buf, &stop, base);
if(*stop != '\0') {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE, buf));
} else if(((v == INT64_MIN) || (v == INT64_MAX)) && (errno == ERANGE)) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE, buf));
}
return v;
}
bool parseLLIntNoThrow(int64_t& result, const std::string& s, int base = 10);
template<typename InputIterator>
int32_t parseInt(InputIterator first, InputIterator last, int base = 10)
{
int64_t v = util::parseLLInt(first, last, base);
if(v < INT32_MIN || INT32_MAX < v) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
std::string(first, last).c_str()));
}
return v;
}
uint64_t parseULLInt(const std::string& s, int base = 10);
template<typename InputIterator>
uint64_t parseULLInt(InputIterator first, InputIterator last, int base = 10)
{
Scip p = util::stripIter(first, last);
if(p.first == p.second) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
"empty string"));
}
char buf[32];
size_t len = std::distance(p.first, p.second);
if(len+1 > sizeof(buf)) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
"too large"));
}
std::copy(p.first, p.second, &buf[0]);
buf[len] = '\0';
// We don't allow negative number.
if(buf[0] == '-') {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE, buf));
}
char* stop;
errno = 0;
uint64_t v = strtoull(buf, &stop, base);
if(*stop != '\0') {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE, buf));
} else if((v == ULLONG_MAX) && (errno == ERANGE)) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE, buf));
}
return v;
}
template<typename InputIterator>
uint32_t parseUInt(InputIterator first, InputIterator last, int base = 10)
{
uint64_t v = util::parseULLInt(first, last, base);
if(UINT32_MAX < v) {
throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
std::string(first, last).c_str()));
}
return v;
}
void parseIntSegments(SegList<int>& sgl, const std::string& src);

View File

@ -30,7 +30,7 @@ void GZipEncoderTest::testEncode()
inputs.push_back("Fox");
encoder << inputs[0];
encoder << util::parseLLInt(inputs[1]);
encoder << util::parseLLInt(inputs[1].begin(), inputs[1].end());
encoder << inputs[2].c_str();
std::string gzippedData = encoder.str();

View File

@ -23,6 +23,7 @@ class UtilTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(UtilTest);
CPPUNIT_TEST(testStrip);
CPPUNIT_TEST(testStripIter);
CPPUNIT_TEST(testDivide);
CPPUNIT_TEST(testSplit);
CPPUNIT_TEST(testEndsWith);
@ -83,6 +84,7 @@ public:
}
void testStrip();
void testStripIter();
void testDivide();
void testSplit();
void testEndsWith();
@ -161,6 +163,54 @@ void UtilTest::testStrip()
CPPUNIT_ASSERT_EQUAL(str4, util::strip(" A "));
}
void UtilTest::testStripIter()
{
Scip p;
std::string str1 = "aria2";
std::string s = "aria2";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str1, std::string(p.first, p.second));
s = " aria2";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str1, std::string(p.first, p.second));
s = "aria2 ";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str1, std::string(p.first, p.second));
s = " aria2 ";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str1, std::string(p.first, p.second));
s = " aria2 ";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str1, std::string(p.first, p.second));
std::string str2 = "aria2 debut";
s = "aria2 debut";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str2, std::string(p.first, p.second));
s = " aria2 debut ";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str2, std::string(p.first, p.second));
std::string str3 = "";
s = "";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str3, std::string(p.first, p.second));
s = " ";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str3, std::string(p.first, p.second));
s = " ";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str3, std::string(p.first, p.second));
std::string str4 = "A";
s = "A";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str4, std::string(p.first, p.second));
s = " A ";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str4, std::string(p.first, p.second));
s = " A ";
p = util::stripIter(s.begin(), s.end());
CPPUNIT_ASSERT_EQUAL(str4, std::string(p.first, p.second));
}
void UtilTest::testDivide() {
std::pair<std::string, std::string> p1;
util::divide(p1, "name=value", '=');
@ -757,76 +807,92 @@ void UtilTest::testParseIntSegments_invalidRange()
void UtilTest::testParseInt()
{
CPPUNIT_ASSERT_EQUAL(-1, util::parseInt(" -1 "));
CPPUNIT_ASSERT_EQUAL(2147483647, util::parseInt("2147483647"));
std::string s;
s = " -1 ";
CPPUNIT_ASSERT_EQUAL(-1, util::parseInt(s.begin(), s.end()));
s = "2147483647";
CPPUNIT_ASSERT_EQUAL(2147483647, util::parseInt(s.begin(), s.end()));
try {
util::parseInt("2147483648");
s = "2147483648";
util::parseInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
try {
util::parseInt("-2147483649");
s = "-2147483649";
util::parseInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
try {
util::parseInt("12x");
s = "12x";
util::parseInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
try {
util::parseInt("");
s = "";
util::parseInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
}
void UtilTest::testParseUInt()
{
CPPUNIT_ASSERT_EQUAL(4294967295U, util::parseUInt(" 4294967295 "));
std::string s;
s = " 4294967295 ";
CPPUNIT_ASSERT_EQUAL(4294967295U, util::parseUInt(s.begin(), s.end()));
try {
util::parseUInt("-1");
s = "-1";
util::parseUInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
try {
util::parseUInt("4294967296");
s = "4294967296";
util::parseUInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
}
void UtilTest::testParseLLInt()
{
CPPUNIT_ASSERT_EQUAL((int64_t)-1LL, util::parseLLInt(" -1 "));
CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775807LL,
util::parseLLInt("9223372036854775807"));
std::string s;
{
s = " -1 ";
CPPUNIT_ASSERT_EQUAL((int64_t)-1LL, util::parseLLInt(s.begin(), s.end()));
}
{
s = "9223372036854775807";
CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775807LL,
util::parseLLInt(s.begin(), s.end()));
}
try {
util::parseLLInt("9223372036854775808");
s = "9223372036854775808";
util::parseLLInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
try {
util::parseLLInt("-9223372036854775809");
s = "-9223372036854775809";
util::parseLLInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
try {
util::parseLLInt("12x");
s = "12x";
util::parseLLInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
try {
util::parseLLInt("");
s = "";
util::parseLLInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
@ -835,56 +901,74 @@ void UtilTest::testParseLLInt()
void UtilTest::testParseULLInt()
{
std::string s;
s = "18446744073709551615";
CPPUNIT_ASSERT_EQUAL((uint64_t)18446744073709551615ULL,
util::parseULLInt("18446744073709551615"));
util::parseULLInt(s.begin(), s.end()));
try {
util::parseUInt("-1");
s = "-1";
util::parseULLInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
try {
util::parseLLInt("18446744073709551616");
s = "18446744073709551616";
util::parseULLInt(s.begin(), s.end());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace();
}
}
void UtilTest::testParseIntNoThrow()
{
std::string s;
int32_t n;
CPPUNIT_ASSERT(util::parseIntNoThrow(n, " -1 "));
s = " -1 ";
CPPUNIT_ASSERT(util::parseIntNoThrow(n, s.begin(), s.end()));
CPPUNIT_ASSERT_EQUAL((int32_t)-1, n);
CPPUNIT_ASSERT(util::parseIntNoThrow(n, "2147483647"));
s = "2147483647";
CPPUNIT_ASSERT(util::parseIntNoThrow(n, s.begin(), s.end()));
CPPUNIT_ASSERT_EQUAL((int32_t)2147483647, n);
CPPUNIT_ASSERT(!util::parseIntNoThrow(n, "2147483648"));
CPPUNIT_ASSERT(!util::parseIntNoThrow(n, "-2147483649"));
s = "2147483648";
CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s.begin(), s.end()));
s = "-2147483649";
CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s.begin(), s.end()));
CPPUNIT_ASSERT(!util::parseIntNoThrow(n, "12x"));
CPPUNIT_ASSERT(!util::parseIntNoThrow(n, ""));
s = "12x";
CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s.begin(), s.end()));
s = "";
CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s.begin(), s.end()));
}
void UtilTest::testParseUIntNoThrow()
{
std::string s;
uint32_t n;
CPPUNIT_ASSERT(util::parseUIntNoThrow(n, " 4294967295 "));
s = " 4294967295 ";
CPPUNIT_ASSERT(util::parseUIntNoThrow(n, s.begin(), s.end()));
CPPUNIT_ASSERT_EQUAL((uint32_t)UINT32_MAX, n);
CPPUNIT_ASSERT(!util::parseUIntNoThrow(n, "4294967296"));
CPPUNIT_ASSERT(!util::parseUIntNoThrow(n, "-1"));
s = "4294967296";
CPPUNIT_ASSERT(!util::parseUIntNoThrow(n, s.begin(), s.end()));
s = "-1";
CPPUNIT_ASSERT(!util::parseUIntNoThrow(n, s.begin(), s.end()));
}
void UtilTest::testParseLLIntNoThrow()
{
std::string s;
int64_t n;
CPPUNIT_ASSERT(util::parseLLIntNoThrow(n, " 9223372036854775807 "));
s = " 9223372036854775807 ";
CPPUNIT_ASSERT(util::parseLLIntNoThrow(n, s.begin(), s.end()));
CPPUNIT_ASSERT_EQUAL((int64_t)INT64_MAX, n);
CPPUNIT_ASSERT(!util::parseLLIntNoThrow(n, "9223372036854775808"));
CPPUNIT_ASSERT(util::parseLLIntNoThrow(n, "-9223372036854775808"));
s = "9223372036854775808";
CPPUNIT_ASSERT(!util::parseLLIntNoThrow(n, s.begin(), s.end()));
s = "-9223372036854775808";
CPPUNIT_ASSERT(util::parseLLIntNoThrow(n, s.begin(), s.end()));
CPPUNIT_ASSERT_EQUAL((int64_t)INT64_MIN, n);
CPPUNIT_ASSERT(!util::parseLLIntNoThrow(n, "-9223372036854775809"));
s = "-9223372036854775809";
CPPUNIT_ASSERT(!util::parseLLIntNoThrow(n, s.begin(), s.end()));
}
void UtilTest::testToString_binaryStream()