Jelajahi Sumber

Rewritten parse*Int

Tatsuhiro Tsujikawa 14 tahun lalu
induk
melakukan
2f4393d17c

+ 1 - 1
src/AbstractCommand.cc

@@ -611,7 +611,7 @@ bool inNoProxy(const SharedHandle<Request>& 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)) {

+ 2 - 1
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();

+ 9 - 8
src/FtpConnection.cc

@@ -427,7 +427,7 @@ unsigned int FtpConnection::receiveSizeResponse(uint64_t& size)
     if(response.first == 213) {
       std::pair<Sip, Sip> 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;
         }

+ 6 - 6
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<Range>(new Range());
     } else {
-      uint64_t contentLength =
-        util::parseULLInt(clenStr.begin(), clenStr.end());
+      uint64_t contentLength = util::parseULLInt(clenStr);
       if(contentLength == 0) {
         return SharedHandle<Range>(new Range());
       } else {
@@ -167,9 +166,10 @@ RangeHandle HttpHeader::getRange() const
   if(minus == slash) {
     return SharedHandle<Range>(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<Range>(new Range(startByte, endByte, entityLength));
 }
 

+ 2 - 1
src/HttpHeaderProcessor.cc

@@ -112,7 +112,8 @@ SharedHandle<HttpHeader> 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());

+ 1 - 1
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;
           }

+ 11 - 13
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<XmlAttr>::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;
         }

+ 7 - 9
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<XmlAttr>::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();

+ 2 - 1
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<time_t>::max() < expiryTime) {

+ 1 - 2
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)

+ 1 - 1
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
 

+ 5 - 6
src/ServerStatMan.cc

@@ -171,25 +171,24 @@ bool ServerStatMan::load(const std::string& filename)
     SharedHandle<ServerStat> 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) {

+ 4 - 7
src/Sqlite3CookieParser.cc

@@ -82,10 +82,9 @@ std::string toString(const char* str)
 } // namespace
 
 namespace {
-template<typename InputIterator>
-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<time_t>::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,

+ 3 - 3
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.
   }
 }

+ 3 - 2
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);

+ 7 - 6
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;

+ 3 - 3
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<char>(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);
   }
 }

+ 3 - 3
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) {

+ 2 - 1
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;
       }

+ 131 - 6
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<typename T, typename F>
+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<int32_t>::min() &&
+     t <= std::numeric_limits<int32_t>::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<int32_t>::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<int64_t>::min() &&
+     t <= std::numeric_limits<int64_t>::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<int64_t>::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<int>& 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<int>& 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<Scip, Scip> 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<unsigned int>(index)));

+ 10 - 165
src/util.h

@@ -264,174 +264,19 @@ bool isPowerOf(int num, int base);
 
 std::string secfmt(time_t sec);
 
-template<typename InputIterator>
-bool parseIntNoThrow
-(int32_t& result, InputIterator first, InputIterator last, int base = 10)
-{
-  // Without strip, strtol("  -1  ",..) emits error.
-  std::pair<InputIterator, InputIterator> 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<typename InputIterator>
-bool parseUIntNoThrow
-(uint32_t& result, InputIterator first, InputIterator last, int base = 10)
-{
-  // Without strip, strtol("  -1  ",..) emits error.
-  std::pair<InputIterator, InputIterator> 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<typename InputIterator>
-bool parseLLIntNoThrow
-(int64_t& result, InputIterator first, InputIterator last, int base = 10)
-{
-  // Without strip, strtol("  -1  ",..) emits error.
-  std::pair<InputIterator, InputIterator> 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<typename InputIterator>
-int64_t parseLLInt(InputIterator first, InputIterator last, int base = 10)
-{
-  std::pair<InputIterator, InputIterator> 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<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;
-}
-
-template<typename InputIterator>
-uint64_t parseULLInt(InputIterator first, InputIterator last, int base = 10)
-{
-  std::pair<InputIterator, InputIterator> 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;
-}
+// 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<int>& sgl, const std::string& src);
 

+ 3 - 3
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<unsigned char> msg =
-      reinterpret_cast<const unsigned char*>("ffffffffffffffff\r\n");
+      reinterpret_cast<const unsigned char*>("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<unsigned char> msg =
-      reinterpret_cast<const unsigned char*>("10000000000000000\r\n");
+      reinterpret_cast<const unsigned char*>("ffffffffffffffff\r\n");
     try {
       filter_->transform(writer_, segment_, msg.data(), msg.size());
       CPPUNIT_FAIL("exception must be thrown.");

+ 1 - 1
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();

+ 39 - 39
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()