util: Add ParseUInt32 and ParseUInt64

Add error and range-checking parsers for unsigned 32 and 64 bit numbers.
The 32-bit variant is required for parsing sequence numbers from the
command line in `bitcoin-tx` (see #8164 for discussion). I've thrown in
the 64-bit variant as a bonus, as I'm sure it will be needed at some
point.

Also adds tests, and updates `developer-notes.md`.
This commit is contained in:
Wladimir J. van der Laan
2016-06-08 10:23:25 +02:00
committed by lateminer
parent c6ac3b5c34
commit 853cd3845c
4 changed files with 112 additions and 1 deletions

View File

@@ -461,6 +461,40 @@ bool ParseInt64(const std::string& str, int64_t *out)
n <= std::numeric_limits<int64_t>::max();
}
bool ParseUInt32(const std::string& str, uint32_t *out)
{
if (!ParsePrechecks(str))
return false;
if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoul accepts these by default if they fit in the range
return false;
char *endp = NULL;
errno = 0; // strtoul will not set errno if valid
unsigned long int n = strtoul(str.c_str(), &endp, 10);
if(out) *out = (uint32_t)n;
// Note that strtoul returns a *unsigned long int*, so even if it doesn't report a over/underflow
// we still have to check that the returned value is within the range of an *uint32_t*. On 64-bit
// platforms the size of these types may be different.
return endp && *endp == 0 && !errno &&
n <= std::numeric_limits<uint32_t>::max();
}
bool ParseUInt64(const std::string& str, uint64_t *out)
{
if (!ParsePrechecks(str))
return false;
if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoull accepts these by default if they fit in the range
return false;
char *endp = NULL;
errno = 0; // strtoull will not set errno if valid
unsigned long long int n = strtoull(str.c_str(), &endp, 10);
if(out) *out = (uint64_t)n;
// Note that strtoull returns a *unsigned long long int*, so even if it doesn't report a over/underflow
// we still have to check that the returned value is within the range of an *uint64_t*.
return endp && *endp == 0 && !errno &&
n <= std::numeric_limits<uint64_t>::max();
}
bool ParseDouble(const std::string& str, double *out)
{
if (!ParsePrechecks(str))