From 2f4393d17c7120912ad7b2b820b46124010a5a5e Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 12 Nov 2011 01:06:52 +0900 Subject: [PATCH] Rewritten parse*Int --- src/AbstractCommand.cc | 2 +- src/ChunkedDecodingStreamFilter.cc | 3 +- src/FtpConnection.cc | 17 +-- src/HttpHeader.cc | 12 +- src/HttpHeaderProcessor.cc | 3 +- src/HttpResponse.cc | 2 +- src/MetalinkParserStateV3Impl.cc | 24 ++-- src/MetalinkParserStateV4Impl.cc | 16 +-- src/NsCookieParser.cc | 3 +- src/OptionHandlerImpl.cc | 3 +- src/RpcMethodImpl.cc | 2 +- src/ServerStatMan.cc | 11 +- src/Sqlite3CookieParser.cc | 11 +- src/XmlRpcRequestParserStateImpl.cc | 6 +- src/bencode2.cc | 5 +- src/cookie_helper.cc | 13 +- src/json.cc | 6 +- src/paramed_string.h | 6 +- src/uri.cc | 3 +- src/util.cc | 137 ++++++++++++++++++- src/util.h | 175 ++---------------------- test/ChunkedDecodingStreamFilterTest.cc | 6 +- test/GZipEncoderTest.cc | 2 +- test/UtilTest.cc | 78 +++++------ 24 files changed, 257 insertions(+), 289 deletions(-) diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index 9dd0ac39..d658d657 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -611,7 +611,7 @@ bool inNoProxy(const SharedHandle& req, // evaluates against all of them std::string ip((*i).first, slashpos); uint32_t bits; - if(!util::parseUIntNoThrow(bits, slashpos+1, (*i).second)) { + if(!util::parseUIntNoThrow(bits, std::string(slashpos+1, (*i).second))) { continue; } if(util::inSameCidrBlock(ip, req->getHost(), bits)) { diff --git a/src/ChunkedDecodingStreamFilter.cc b/src/ChunkedDecodingStreamFilter.cc index c84374ea..b1f98bdf 100644 --- a/src/ChunkedDecodingStreamFilter.cc +++ b/src/ChunkedDecodingStreamFilter.cc @@ -96,7 +96,8 @@ bool ChunkedDecodingStreamFilter::readChunkSize if(extPos == std::string::npos || crlfPos < extPos) { extPos = crlfPos; } - chunkSize_ = util::parseULLInt(buf_.begin(), buf_.begin()+extPos, 16); + chunkSize_ = util::parseULLInt + (std::string(buf_.begin(), buf_.begin()+extPos), 16); assert(crlfPos+2 > pbufSize); inbufOffset += crlfPos+2-pbufSize; buf_.clear(); diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc index 30638fa2..de11fb51 100644 --- a/src/FtpConnection.cc +++ b/src/FtpConnection.cc @@ -427,7 +427,7 @@ unsigned int FtpConnection::receiveSizeResponse(uint64_t& size) if(response.first == 213) { std::pair rp; util::divide(rp, response.second.begin(), response.second.end(), ' '); - size = util::parseULLInt(rp.second.first, rp.second.second); + size = util::parseULLInt(std::string(rp.second.first, rp.second.second)); } return response.first; } else { @@ -448,12 +448,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[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; + tm.tm_sec = util::parseInt(std::string(&buf[12], &buf[14])); + tm.tm_min = util::parseInt(std::string(&buf[10], &buf[12])); + tm.tm_hour = util::parseInt(std::string(&buf[8], &buf[10])); + tm.tm_mday = util::parseInt(std::string(&buf[6], &buf[8])); + tm.tm_mon = util::parseInt(std::string(&buf[4], &buf[6]))-1; + tm.tm_year = util::parseInt(std::string(&buf[0], &buf[4]))-1900; time = Time(timegm(&tm)); } else { time = Time::null(); @@ -483,7 +483,8 @@ unsigned int FtpConnection::receiveEpsvResponse(uint16_t& port) std::back_inserter(rd), '|', true, true); uint32_t portTemp = 0; if(rd.size() == 5 && - util::parseUIntNoThrow(portTemp, rd[3].first, rd[3].second)) { + util::parseUIntNoThrow(portTemp, + std::string(rd[3].first, rd[3].second))) { if(0 < portTemp && portTemp <= UINT16_MAX) { port = portTemp; } diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc index efb036ec..29e92cae 100644 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -117,7 +117,7 @@ uint64_t HttpHeader::findAsULLInt(const std::string& name) const { if(value.empty()) { return 0; } else { - return util::parseULLInt(value.begin(), value.end()); + return util::parseULLInt(value); } } @@ -129,8 +129,7 @@ RangeHandle HttpHeader::getRange() const if(clenStr.empty()) { return SharedHandle(new Range()); } else { - uint64_t contentLength = - util::parseULLInt(clenStr.begin(), clenStr.end()); + uint64_t contentLength = util::parseULLInt(clenStr); if(contentLength == 0) { return SharedHandle(new Range()); } else { @@ -167,9 +166,10 @@ RangeHandle HttpHeader::getRange() const if(minus == slash) { return SharedHandle(new Range()); } - off_t startByte = util::parseLLInt(byteRangeSpec, minus); - off_t endByte = util::parseLLInt(minus+1, slash); - uint64_t entityLength = util::parseULLInt(slash+1, rangeStr.end()); + 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())); return SharedHandle(new Range(startByte, endByte, entityLength)); } diff --git a/src/HttpHeaderProcessor.cc b/src/HttpHeaderProcessor.cc index b86e58c3..c48bac61 100644 --- a/src/HttpHeaderProcessor.cc +++ b/src/HttpHeaderProcessor.cc @@ -112,7 +112,8 @@ SharedHandle HttpHeaderProcessor::getHttpResponseHeader() throw DL_RETRY_EX(EX_NO_STATUS_HEADER); } int32_t statusCode; - if(!util::parseIntNoThrow(statusCode, buf_.begin()+9, buf_.begin()+12)) { + if(!util::parseIntNoThrow(statusCode, + std::string(buf_.begin()+9, buf_.begin()+12))) { throw DL_RETRY_EX("Status code could not be parsed as integer."); } HttpHeaderHandle httpHeader(new HttpHeader()); diff --git a/src/HttpResponse.cc b/src/HttpResponse.cc index d1cad443..682a7279 100644 --- a/src/HttpResponse.cc +++ b/src/HttpResponse.cc @@ -354,7 +354,7 @@ bool parseMetalinkHttpLink(MetalinkHttpEntry& result, const std::string& s) } } else if(name == "pri") { int32_t priValue; - if(util::parseIntNoThrow(priValue, value.begin(), value.end())) { + if(util::parseIntNoThrow(priValue, value)) { if(1 <= priValue && priValue <= 999999) { result.pri = priValue; } diff --git a/src/MetalinkParserStateV3Impl.cc b/src/MetalinkParserStateV3Impl.cc index 857add9e..783f0e69 100644 --- a/src/MetalinkParserStateV3Impl.cc +++ b/src/MetalinkParserStateV3Impl.cc @@ -119,7 +119,7 @@ void FileMetalinkParserState::beginElement maxConnections = -1; } else { if(!util::parseIntNoThrow - (maxConnections,(*itr).value, (*itr).value+(*itr).valueLength) || + (maxConnections, std::string((*itr).value, (*itr).valueLength)) || maxConnections <= 0) { maxConnections = -1; } @@ -148,9 +148,8 @@ void SizeMetalinkParserState::endElement const std::string& characters) { // current metalink specification doesn't require size element. - int64_t size; - if(util::parseLLIntNoThrow(size, characters.begin(), characters.end()) && - size >= 0) { + uint64_t size; + if(util::parseULLIntNoThrow(size, characters)) { psm->setFileLengthOfEntry(size); } } @@ -208,16 +207,15 @@ void VerificationMetalinkParserState::beginElement } } else if(strcmp(localname, "pieces") == 0) { psm->setPiecesState(); - int32_t length; + uint32_t length; { std::vector::const_iterator itr = findAttr(attrs, "length", METALINK3_NAMESPACE_URI); if(itr == attrs.end()) { return; } else { - if(!util::parseIntNoThrow - (length, (*itr).value, (*itr).value+(*itr).valueLength) || - length < 0) { + if(!util::parseUIntNoThrow + (length, std::string((*itr).value, (*itr).valueLength))) { return; } } @@ -286,9 +284,9 @@ void PiecesMetalinkParserState::beginElement if(itr == attrs.end()) { psm->cancelChunkChecksumTransaction(); } else { - int32_t idx; - if(util::parseIntNoThrow - (idx, (*itr).value, (*itr).value+(*itr).valueLength) && idx >= 0) { + uint32_t idx; + if(util::parseUIntNoThrow + (idx, std::string((*itr).value, (*itr).valueLength))) { psm->createNewHashOfChunkChecksum(idx); } else { psm->cancelChunkChecksumTransaction(); @@ -368,7 +366,7 @@ void ResourcesMetalinkParserState::beginElement preference = MetalinkResource::getLowestPriority(); } else { if(util::parseIntNoThrow - (preference, (*itr).value, (*itr).value+(*itr).valueLength) && + (preference, std::string((*itr).value, (*itr).valueLength)) && preference >= 0) { // In Metalink3Spec, highest prefernce value is 100. We // use Metalink4Spec priority unit system in which 1 is @@ -387,7 +385,7 @@ void ResourcesMetalinkParserState::beginElement maxConnections = -1; } else { if(!util::parseIntNoThrow - (maxConnections, (*itr).value, (*itr).value+(*itr).valueLength) || + (maxConnections, std::string((*itr).value, (*itr).valueLength)) || maxConnections <= 0) { maxConnections = -1; } diff --git a/src/MetalinkParserStateV4Impl.cc b/src/MetalinkParserStateV4Impl.cc index 7a22b98e..2ba07297 100644 --- a/src/MetalinkParserStateV4Impl.cc +++ b/src/MetalinkParserStateV4Impl.cc @@ -119,7 +119,7 @@ void FileMetalinkParserStateV4::beginElement priority = MetalinkResource::getLowestPriority(); } else { if(util::parseIntNoThrow - (priority, (*itr).value, (*itr).value+(*itr).valueLength)) { + (priority, std::string((*itr).value, (*itr).valueLength))) { if(priority < 1 || MetalinkResource::getLowestPriority() < priority) { psm->logError("metaurl@priority is out of range"); return; @@ -163,7 +163,7 @@ void FileMetalinkParserStateV4::beginElement priority = MetalinkResource::getLowestPriority(); } else { if(util::parseIntNoThrow - (priority, (*itr).value, (*itr).value+(*itr).valueLength)) { + (priority, std::string((*itr).value, (*itr).valueLength))) { if(priority < 1 || MetalinkResource::getLowestPriority() < priority) { psm->logError("url@priority is out of range"); return; @@ -192,16 +192,15 @@ void FileMetalinkParserStateV4::beginElement } } else if(strcmp(localname, "pieces") == 0) { psm->setPiecesStateV4(); - int32_t length; + uint32_t length; { std::vector::const_iterator itr = findAttr(attrs, "length", METALINK4_NAMESPACE_URI); if(itr == attrs.end() || (*itr).valueLength == 0) { psm->logError("Missing pieces@length"); return; - } else if(!util::parseIntNoThrow - (length, (*itr).value, (*itr).value+(*itr).valueLength) || - length < 0) { + } else if(!util::parseUIntNoThrow + (length, std::string((*itr).value, (*itr).valueLength))) { psm->logError("Bad pieces@length"); return; } @@ -254,9 +253,8 @@ void SizeMetalinkParserStateV4::endElement const char* nsUri, const std::string& characters) { - int64_t size; - if(util::parseLLIntNoThrow(size, characters.begin(), characters.end()) && - size >= 0) { + uint64_t size; + if(util::parseULLIntNoThrow(size, characters)) { psm->setFileLengthOfEntry(size); } else { psm->cancelEntryTransaction(); diff --git a/src/NsCookieParser.cc b/src/NsCookieParser.cc index d3cd222a..b5854f1e 100644 --- a/src/NsCookieParser.cc +++ b/src/NsCookieParser.cc @@ -68,7 +68,8 @@ bool parseNsCookie return false; } int64_t expiryTime; - if(!util::parseLLIntNoThrow(expiryTime, vs[4].first, vs[4].second)) { + if(!util::parseLLIntNoThrow(expiryTime, + std::string(vs[4].first, vs[4].second))) { return false; } if(std::numeric_limits::max() < expiryTime) { diff --git a/src/OptionHandlerImpl.cc b/src/OptionHandlerImpl.cc index a511ece2..e34b7ace 100644 --- a/src/OptionHandlerImpl.cc +++ b/src/OptionHandlerImpl.cc @@ -154,8 +154,7 @@ NumberOptionHandler::~NumberOptionHandler() {} void NumberOptionHandler::parseArg(Option& option, const std::string& optarg) { - int64_t num = util::parseLLInt(optarg.begin(), optarg.end()); - parseArg(option, num); + parseArg(option, util::parseLLInt(optarg)); } void NumberOptionHandler::parseArg(Option& option, int64_t number) diff --git a/src/RpcMethodImpl.cc b/src/RpcMethodImpl.cc index 73453b6f..a9dcf0f3 100644 --- a/src/RpcMethodImpl.cc +++ b/src/RpcMethodImpl.cc @@ -197,7 +197,7 @@ namespace { a2_gid_t str2Gid(const String* str) { assert(str); - return util::parseLLInt(str->s().begin(), str->s().end()); + return util::parseLLInt(str->s()); } } // namespace diff --git a/src/ServerStatMan.cc b/src/ServerStatMan.cc index 2c4b9f76..de00165a 100644 --- a/src/ServerStatMan.cc +++ b/src/ServerStatMan.cc @@ -171,25 +171,24 @@ bool ServerStatMan::load(const std::string& filename) SharedHandle sstat(new ServerStat(m[S_HOST], m[S_PROTOCOL])); try { const std::string& dlSpeed = m[S_DL_SPEED]; - sstat->setDownloadSpeed(util::parseUInt(dlSpeed.begin(), dlSpeed.end())); + sstat->setDownloadSpeed(util::parseUInt(dlSpeed)); // Old serverstat file doesn't contains SC_AVG_SPEED if(m.find(S_SC_AVG_SPEED) != m.end()) { const std::string& s = m[S_SC_AVG_SPEED]; - sstat->setSingleConnectionAvgSpeed(util::parseUInt(s.begin(), s.end())); + sstat->setSingleConnectionAvgSpeed(util::parseUInt(s)); } // Old serverstat file doesn't contains MC_AVG_SPEED if(m.find(S_MC_AVG_SPEED) != m.end()) { const std::string& s = m[S_MC_AVG_SPEED]; - sstat->setMultiConnectionAvgSpeed(util::parseUInt(s.begin(), s.end())); + sstat->setMultiConnectionAvgSpeed(util::parseUInt(s)); } // Old serverstat file doesn't contains COUNTER_SPEED if(m.find(S_COUNTER) != m.end()) { const std::string& s = m[S_COUNTER]; - sstat->setCounter(util::parseUInt(s.begin(), s.end())); + sstat->setCounter(util::parseUInt(s)); } const std::string& lastUpdated = m[S_LAST_UPDATED]; - sstat->setLastUpdated - (Time(util::parseInt(lastUpdated.begin(), lastUpdated.end()))); + sstat->setLastUpdated(Time(util::parseInt(lastUpdated))); sstat->setStatus(m[S_STATUS]); add(sstat); } catch(RecoverableException& e) { diff --git a/src/Sqlite3CookieParser.cc b/src/Sqlite3CookieParser.cc index 667b40a3..b9d705d0 100644 --- a/src/Sqlite3CookieParser.cc +++ b/src/Sqlite3CookieParser.cc @@ -82,10 +82,9 @@ std::string toString(const char* str) } // namespace namespace { -template -bool parseTime(int64_t& time, InputIterator first, InputIterator last) +bool parseTime(int64_t& time, const std::string& s) { - if(!util::parseLLIntNoThrow(time, first, last)) { + if(!util::parseLLIntNoThrow(time, s)) { return false; } if(std::numeric_limits::max() < time) { @@ -116,13 +115,11 @@ int cookieRowMapper(void* data, int columns, char** values, char** names) return 0; } int64_t expiryTime; - if(!values[3] || - !parseTime(expiryTime, &values[3][0], &values[3][strlen(values[3])])) { + if(!values[3] || !parseTime(expiryTime, values[3])) { return 0; } int64_t lastAccessTime; - if(!values[6] || - !parseTime(lastAccessTime, &values[6][0], &values[6][strlen(values[6])])) { + if(!values[6] || !parseTime(lastAccessTime, values[6])) { return 0; } Cookie c(cookieName, diff --git a/src/XmlRpcRequestParserStateImpl.cc b/src/XmlRpcRequestParserStateImpl.cc index a71ec3e8..947a378a 100644 --- a/src/XmlRpcRequestParserStateImpl.cc +++ b/src/XmlRpcRequestParserStateImpl.cc @@ -200,10 +200,10 @@ void IntXmlRpcRequestParserState::endElement const char* name, const std::string& characters) { - try { - int64_t value = util::parseLLInt(characters.begin(), characters.end()); + int64_t value; + if(util::parseLLIntNoThrow(value, characters)) { psm->setCurrentFrameValue(Integer::g(value)); - } catch(RecoverableException& e) { + } else { // nothing to do here: We just leave current frame value to null. } } diff --git a/src/bencode2.cc b/src/bencode2.cc index 74198b0d..78071879 100644 --- a/src/bencode2.cc +++ b/src/bencode2.cc @@ -63,7 +63,8 @@ decoderawstring(InputIterator first, InputIterator last) InputIterator i = first; int32_t len; for(; i != last && *i != ':'; ++i); - if(i == last || i == first || !util::parseIntNoThrow(len, first, i) || + if(i == last || i == first || + !util::parseIntNoThrow(len, std::string(first, i)) || len < 0) { throw DL_ABORT_EX2("Bencode decoding failed:" " A positive integer expected but none found.", @@ -100,7 +101,7 @@ decodeinteger(InputIterator first, InputIterator last) InputIterator i = first; for(; i != last && *i != 'e'; ++i); Integer::ValueType iv; - if(i == last || !util::parseLLIntNoThrow(iv, first, i)) { + if(i == last || !util::parseLLIntNoThrow(iv, std::string(first, i))) { throw DL_ABORT_EX2("Bencode decoding failed:" " Integer expected but none found", error_code::BENCODE_PARSE_ERROR); diff --git a/src/cookie_helper.cc b/src/cookie_helper.cc index 1ebf47a7..a8be1119 100644 --- a/src/cookie_helper.cc +++ b/src/cookie_helper.cc @@ -117,9 +117,9 @@ bool parseDate goto NOT_TIME; } foundTime = true; - hour = util::parseInt((*i).begin(), hEnd); - minute = util::parseInt(hEnd+1, mEnd); - second = util::parseInt(mEnd+1, sEnd); + hour = util::parseInt(std::string((*i).begin(), hEnd)); + minute = util::parseInt(std::string(hEnd+1, mEnd)); + second = util::parseInt(std::string(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((*i).begin(), j); + dayOfMonth = util::parseInt(std::string((*i).begin(), j)); continue; } } @@ -160,7 +160,7 @@ bool parseDate size_t len = std::distance((*i).begin(), j); if(1 <= len && len <= 4) { foundYear = true; - year = util::parseInt((*i).begin(), j); + year = util::parseInt(std::string((*i).begin(), j)); continue; } } @@ -283,7 +283,8 @@ bool parse } } int64_t delta; - if(util::parseLLIntNoThrow(delta, attrp.first, attrp.second)) { + if(util::parseLLIntNoThrow(delta, + std::string(attrp.first, attrp.second))) { foundMaxAge = true; if(delta <= 0) { maxAge = 0; diff --git a/src/json.cc b/src/json.cc index e9c260eb..df3ac534 100644 --- a/src/json.cc +++ b/src/json.cc @@ -166,7 +166,7 @@ decodeString checkEof(first, last); } checkEof(first, last); - uint16_t codepoint = util::parseUInt(uchars, first, 16); + uint16_t codepoint = util::parseUInt(std::string(uchars, first), 16); if(codepoint <= 0x007fu) { s += static_cast(codepoint); } else if(codepoint <= 0x07ffu) { @@ -187,7 +187,7 @@ decodeString checkEof(first, last); } checkEof(first, last); - uint16_t codepoint2 = util::parseUInt(uchars, first, 16); + uint16_t codepoint2 = util::parseUInt(std::string(uchars, first), 16); if(!in(codepoint2, 0xDC00u, 0xDFFFu)) { throw DL_ABORT_EX2("JSON decoding failed: bad UTF-8 sequence.", error_code::JSON_PARSE_ERROR); @@ -324,7 +324,7 @@ decodeNumber // we just treat it as string. return std::make_pair(String::g(s), first); } else { - Integer::ValueType val = util::parseLLInt(s.begin(), s.end()); + Integer::ValueType val = util::parseLLInt(s); return std::make_pair(Integer::g(val), first); } } diff --git a/src/paramed_string.h b/src/paramed_string.h index ffc28e9b..7ebee8cd 100644 --- a/src/paramed_string.h +++ b/src/paramed_string.h @@ -104,7 +104,7 @@ InputIterator expandLoop if(colon == i) { step = 1; } else { - if(!util::parseUIntNoThrow(step, colon+1, i)) { + if(!util::parseUIntNoThrow(step, std::string(colon+1, i))) { throw DL_ABORT_EX("A step count must be a positive number."); } if(step > UINT16_MAX) { @@ -117,8 +117,8 @@ InputIterator expandLoop } if(util::isNumber(first, minus) && util::isNumber(minus+1, colon)) { uint32_t start, end; - if(!util::parseUIntNoThrow(start, first, minus) || - !util::parseUIntNoThrow(end, minus+1, colon)) { + if(!util::parseUIntNoThrow(start, std::string(first, minus)) || + !util::parseUIntNoThrow(end, std::string(minus+1, colon))) { throw DL_ABORT_EX("Loop range missing."); } if(start > UINT16_MAX || end > UINT16_MAX) { diff --git a/src/uri.cc b/src/uri.cc index 629e1b62..300c33ac 100644 --- a/src/uri.cc +++ b/src/uri.cc @@ -211,7 +211,8 @@ bool parse(UriStruct& result, const std::string& uri) result.port = defPort; } else { uint32_t tempPort; - if(util::parseUIntNoThrow(tempPort, portFirst, authorityLast)) { + if(util::parseUIntNoThrow(tempPort, + std::string(portFirst, authorityLast))) { if(65535 < tempPort) { return false; } diff --git a/src/util.cc b/src/util.cc index bb345dbf..303143ef 100644 --- a/src/util.cc +++ b/src/util.cc @@ -445,7 +445,7 @@ std::string percentDecode if(*first == '%') { if(first+1 != last && first+2 != last && isHexDigit(*(first+1)) && isHexDigit(*(first+2))) { - result += parseInt(first+1, first+3, 16); + result += parseInt(std::string(first+1, first+3), 16); first += 2; } else { result += *first; @@ -553,6 +553,131 @@ int getNum(const char* buf, int offset, size_t length) { return x; } +namespace { +template +bool parseLong(T& res, F f, const std::string& s, int base) +{ + if(s.empty()) { + return false; + } + char* endptr; + errno = 0; + res = f(s.c_str(), &endptr, base); + if(errno == ERANGE) { + return false; + } + if(*endptr != '\0') { + for(const char* i = endptr, *eoi = s.c_str()+s.size(); i < eoi; ++i) { + if(!isspace(*i)) { + return false; + } + } + } + return true; +} +} // namespace + +bool parseIntNoThrow(int32_t& res, const std::string& s, int base) +{ + long int t; + if(parseLong(t, strtol, s, base) && + t >= std::numeric_limits::min() && + t <= std::numeric_limits::max()) { + res = t; + return true; + } else { + return false; + } +} + +int32_t parseInt(const std::string& s, int base) +{ + int32_t res; + if(parseIntNoThrow(res, s, base)) { + return res; + } else { + throw DL_ABORT_EX + (fmt("Failed to convert string into 32bit signed integer. '%s'", + s.c_str())); + } +} + +bool parseUIntNoThrow(uint32_t& res, const std::string& s, int base) +{ + long int t; + if(parseLong(t, strtol, s, base) && + t >= 0 && + t <= std::numeric_limits::max()) { + res = t; + return true; + } else { + return false; + } +} + +uint32_t parseUInt(const std::string& s, int base) +{ + uint32_t res; + if(parseUIntNoThrow(res, s, base)) { + return res; + } else { + throw DL_ABORT_EX + (fmt("Failed to convert string into 32bit unsigned integer. '%s'", + s.c_str())); + } +} + +bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base) +{ + long long int t; + if(parseLong(t, strtoll, s, base) && + t >= std::numeric_limits::min() && + t <= std::numeric_limits::max()) { + res = t; + return true; + } else { + return false; + } +} + +int64_t parseLLInt(const std::string& s, int base) +{ + int64_t res; + if(parseLLIntNoThrow(res, s, base)) { + return res; + } else { + throw DL_ABORT_EX + (fmt("Failed to convert string into 64bit signed integer. '%s'", + s.c_str())); + } +} + +bool parseULLIntNoThrow(uint64_t& res, const std::string& s, int base) +{ + long int t; + if(parseLong(t, strtoll, s, base) && + t >= 0 && + t <= std::numeric_limits::max()) { + res = t; + return true; + } else { + return false; + } +} + +uint64_t parseULLInt(const std::string& s, int base) +{ + uint64_t res; + if(parseULLIntNoThrow(res, s, base)) { + return res; + } else { + throw DL_ABORT_EX + (fmt("Failed to convert string into 64bit unsigned integer. '%s'", + s.c_str())); + } +} + + void parseIntSegments(SegList& sgl, const std::string& src) { for(std::string::const_iterator i = src.begin(), eoi = src.end(); i != eoi;) { @@ -563,13 +688,13 @@ void parseIntSegments(SegList& sgl, const std::string& src) } std::string::const_iterator p = std::find(i, j, '-'); if(p == j) { - int a = parseInt(i, j); + int a = parseInt(std::string(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(i, p); - int b = parseInt(p+1, j); + int a = parseInt(std::string(i, p)); + int b = parseInt(std::string(p+1, j)); sgl.add(a, b+1); } if(j == eoi) { @@ -946,7 +1071,7 @@ int64_t getRealSize(const std::string& sizeWithUnit) } size.assign(sizeWithUnit.begin(), sizeWithUnit.begin()+p); } - int64_t v = parseLLInt(size.begin(), size.end()); + int64_t v = parseLLInt(size); if(v < 0) { throw DL_ABORT_EX(fmt("Negative value detected: %s", sizeWithUnit.c_str())); @@ -1148,7 +1273,7 @@ parseIndexPath(const std::string& line) { std::pair p; divide(p, line.begin(), line.end(), '='); - size_t index = parseUInt(p.first.first, p.first.second); + size_t index = parseUInt(std::string(p.first.first, p.first.second)); if(p.second.first == p.second.second) { throw DL_ABORT_EX(fmt("Path with index=%u is empty.", static_cast(index))); diff --git a/src/util.h b/src/util.h index 9aa1f58a..7a9cdb3a 100644 --- a/src/util.h +++ b/src/util.h @@ -264,174 +264,19 @@ bool isPowerOf(int num, int base); std::string secfmt(time_t sec); -template -bool parseIntNoThrow -(int32_t& result, InputIterator first, InputIterator last, int base = 10) -{ - // Without strip, strtol(" -1 ",..) emits error. - std::pair 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& res, const std::string& s, int base = 10); +int32_t parseInt(const std::string& s, int base = 10); -template -bool parseUIntNoThrow -(uint32_t& result, InputIterator first, InputIterator last, int base = 10) -{ - // Without strip, strtol(" -1 ",..) emits error. - std::pair 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; -} +// Valid range: [0, INT32_MAX] +bool parseUIntNoThrow(uint32_t& res, const std::string& s, int base = 10); +uint32_t parseUInt(const std::string& s, int base = 10); -template -bool parseLLIntNoThrow -(int64_t& result, InputIterator first, InputIterator last, int base = 10) -{ - // Without strip, strtol(" -1 ",..) emits error. - std::pair 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; -} +bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base = 10); +int64_t parseLLInt(const std::string& s, int base = 10); -template -int64_t parseLLInt(InputIterator first, InputIterator last, int base = 10) -{ - std::pair 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; -} - -template -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; -} - -template -uint64_t parseULLInt(InputIterator first, InputIterator last, int base = 10) -{ - std::pair 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 -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; -} +// Valid range: [0, INT64_MAX] +bool parseULLIntNoThrow(uint64_t& res, const std::string& s, int base = 10); +uint64_t parseULLInt(const std::string& s, int base = 10); void parseIntSegments(SegList& sgl, const std::string& src); diff --git a/test/ChunkedDecodingStreamFilterTest.cc b/test/ChunkedDecodingStreamFilterTest.cc index 8dea7bd1..5f623e92 100644 --- a/test/ChunkedDecodingStreamFilterTest.cc +++ b/test/ChunkedDecodingStreamFilterTest.cc @@ -196,10 +196,10 @@ void ChunkedDecodingStreamFilterTest::testTransform_with2Trailers() void ChunkedDecodingStreamFilterTest::testTransform_largeChunkSize() { - // chunkSize should be under 2^64-1 + // chunkSize should be under 2^63-1 { std::basic_string msg = - reinterpret_cast("ffffffffffffffff\r\n"); + reinterpret_cast("7fffffffffffffff\r\n"); filter_->transform(writer_, segment_, msg.data(), msg.size()); } } @@ -209,7 +209,7 @@ void ChunkedDecodingStreamFilterTest::testTransform_tooLargeChunkSize() // chunkSize 2^64 causes error { std::basic_string msg = - reinterpret_cast("10000000000000000\r\n"); + reinterpret_cast("ffffffffffffffff\r\n"); try { filter_->transform(writer_, segment_, msg.data(), msg.size()); CPPUNIT_FAIL("exception must be thrown."); diff --git a/test/GZipEncoderTest.cc b/test/GZipEncoderTest.cc index 193023f6..8322d4a1 100644 --- a/test/GZipEncoderTest.cc +++ b/test/GZipEncoderTest.cc @@ -30,7 +30,7 @@ void GZipEncoderTest::testEncode() inputs.push_back("Fox"); encoder << inputs[0]; - encoder << util::parseLLInt(inputs[1].begin(), inputs[1].end()); + encoder << util::parseLLInt(inputs[1]); encoder << inputs[2].c_str(); std::string gzippedData = encoder.str(); diff --git a/test/UtilTest.cc b/test/UtilTest.cc index 1c319913..fb855656 100644 --- a/test/UtilTest.cc +++ b/test/UtilTest.cc @@ -1251,30 +1251,30 @@ void UtilTest::testParseInt() { std::string s; s = " -1 "; - CPPUNIT_ASSERT_EQUAL(-1, util::parseInt(s.begin(), s.end())); + CPPUNIT_ASSERT_EQUAL(-1, util::parseInt(s)); s = "2147483647"; - CPPUNIT_ASSERT_EQUAL(2147483647, util::parseInt(s.begin(), s.end())); + CPPUNIT_ASSERT_EQUAL(2147483647, util::parseInt(s)); try { s = "2147483648"; - util::parseInt(s.begin(), s.end()); + util::parseInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { } try { s = "-2147483649"; - util::parseInt(s.begin(), s.end()); + util::parseInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { } try { s = "12x"; - util::parseInt(s.begin(), s.end()); + util::parseInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { } try { s = ""; - util::parseInt(s.begin(), s.end()); + util::parseInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { } @@ -1283,17 +1283,17 @@ void UtilTest::testParseInt() void UtilTest::testParseUInt() { std::string s; - s = " 4294967295 "; - CPPUNIT_ASSERT_EQUAL(4294967295U, util::parseUInt(s.begin(), s.end())); + s = " 2147483647 "; + CPPUNIT_ASSERT_EQUAL(2147483647U, util::parseUInt(s)); try { s = "-1"; - util::parseUInt(s.begin(), s.end()); + util::parseUInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { } try { - s = "4294967296"; - util::parseUInt(s.begin(), s.end()); + s = "2147483648"; + util::parseUInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { } @@ -1304,37 +1304,37 @@ void UtilTest::testParseLLInt() std::string s; { s = " -1 "; - CPPUNIT_ASSERT_EQUAL((int64_t)-1LL, util::parseLLInt(s.begin(), s.end())); + CPPUNIT_ASSERT_EQUAL((int64_t)-1LL, util::parseLLInt(s)); } { s = "9223372036854775807"; CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775807LL, - util::parseLLInt(s.begin(), s.end())); + util::parseLLInt(s)); } try { s = "9223372036854775808"; - util::parseLLInt(s.begin(), s.end()); + util::parseLLInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { std::cerr << e.stackTrace(); } try { s = "-9223372036854775809"; - util::parseLLInt(s.begin(), s.end()); + util::parseLLInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { std::cerr << e.stackTrace(); } try { s = "12x"; - util::parseLLInt(s.begin(), s.end()); + util::parseLLInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { std::cerr << e.stackTrace(); } try { s = ""; - util::parseLLInt(s.begin(), s.end()); + util::parseLLInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { std::cerr << e.stackTrace(); @@ -1344,18 +1344,18 @@ void UtilTest::testParseLLInt() void UtilTest::testParseULLInt() { std::string s; - s = "18446744073709551615"; - CPPUNIT_ASSERT_EQUAL((uint64_t)18446744073709551615ULL, - util::parseULLInt(s.begin(), s.end())); + s = "9223372036854775807"; + CPPUNIT_ASSERT_EQUAL((uint64_t)9223372036854775807LL, + util::parseULLInt(s)); try { s = "-1"; - util::parseULLInt(s.begin(), s.end()); + util::parseULLInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { } try { - s = "18446744073709551616"; - util::parseULLInt(s.begin(), s.end()); + s = "9223372036854775808"; + util::parseULLInt(s); CPPUNIT_FAIL("exception must be thrown."); } catch(Exception& e) { } @@ -1366,35 +1366,35 @@ void UtilTest::testParseIntNoThrow() std::string s; int32_t n; s = " -1 "; - CPPUNIT_ASSERT(util::parseIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(util::parseIntNoThrow(n, s)); CPPUNIT_ASSERT_EQUAL((int32_t)-1, n); s = "2147483647"; - CPPUNIT_ASSERT(util::parseIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(util::parseIntNoThrow(n, s)); CPPUNIT_ASSERT_EQUAL((int32_t)2147483647, n); s = "2147483648"; - CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s)); s = "-2147483649"; - CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s)); s = "12x"; - CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s)); s = ""; - CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(!util::parseIntNoThrow(n, s)); } void UtilTest::testParseUIntNoThrow() { std::string s; uint32_t n; - s = " 4294967295 "; - CPPUNIT_ASSERT(util::parseUIntNoThrow(n, s.begin(), s.end())); - CPPUNIT_ASSERT_EQUAL((uint32_t)UINT32_MAX, n); - s = "4294967296"; - CPPUNIT_ASSERT(!util::parseUIntNoThrow(n, s.begin(), s.end())); + s = " 2147483647 "; + CPPUNIT_ASSERT(util::parseUIntNoThrow(n, s)); + CPPUNIT_ASSERT_EQUAL((uint32_t)INT32_MAX, n); + s = "2147483648"; + CPPUNIT_ASSERT(!util::parseUIntNoThrow(n, s)); s = "-1"; - CPPUNIT_ASSERT(!util::parseUIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(!util::parseUIntNoThrow(n, s)); } void UtilTest::testParseLLIntNoThrow() @@ -1402,15 +1402,15 @@ void UtilTest::testParseLLIntNoThrow() std::string s; int64_t n; s = " 9223372036854775807 "; - CPPUNIT_ASSERT(util::parseLLIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(util::parseLLIntNoThrow(n, s)); CPPUNIT_ASSERT_EQUAL((int64_t)INT64_MAX, n); s = "9223372036854775808"; - CPPUNIT_ASSERT(!util::parseLLIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(!util::parseLLIntNoThrow(n, s)); s = "-9223372036854775808"; - CPPUNIT_ASSERT(util::parseLLIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(util::parseLLIntNoThrow(n, s)); CPPUNIT_ASSERT_EQUAL((int64_t)INT64_MIN, n); s = "-9223372036854775809"; - CPPUNIT_ASSERT(!util::parseLLIntNoThrow(n, s.begin(), s.end())); + CPPUNIT_ASSERT(!util::parseLLIntNoThrow(n, s)); } void UtilTest::testToString_binaryStream()