diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2011-11-03 18:51:31 +0900 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2011-11-03 18:51:31 +0900 |
| commit | 9bb914b76e61dfed6044afee529eb92344bbca7a (patch) | |
| tree | 016f9b4f6cdd1449398d05d6ce469b07463fa28c /src/util.h | |
| parent | 6ef91d60b34a2a93b397b6db4daabfe8017d31fb (diff) | |
Changed parse*Int functions so that it accepts iterators.
Diffstat (limited to 'src/util.h')
| -rw-r--r-- | src/util.h | 177 |
1 files changed, 169 insertions, 8 deletions
@@ -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; +} + +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; +} -int64_t parseLLInt(const std::string& s, int32_t 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; +} -bool parseLLIntNoThrow(int64_t& result, 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; +} -uint64_t parseULLInt(const std::string& s, int base = 10); +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); |
