Skip to content
This repository was archived by the owner on Jun 17, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ AC_SUBST(LIBUNIVALUE_AGE)
LT_INIT
LT_LANG([C++])

dnl Require C++11 compiler (no GNU extensions)
AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory], [nodefault])
dnl Require C++17 compiler (no GNU extensions)
AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory], [nodefault])

case $host in
*mingw*)
Expand Down
21 changes: 19 additions & 2 deletions include/univalue.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
#ifndef __UNIVALUE_H__
#define __UNIVALUE_H__

#include <charconv>
#include <cstdint>
#include <cstring>
#include <map>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <vector>

class UniValue {
Expand Down Expand Up @@ -166,10 +169,24 @@ class UniValue {
// value is of unexpected type
const std::vector<std::string>& getKeys() const;
const std::vector<UniValue>& getValues() const;
template <typename Int>
auto getInt() const
{
static_assert(std::is_integral<Int>::value);
if (typ != VNUM) {
throw std::runtime_error("JSON value is not an integer as expected");
}
Int result;
const auto [first_nonmatching, error_condition] = std::from_chars(val.data(), val.data() + val.size(), result);
if (first_nonmatching != val.data() + val.size() || error_condition != std::errc{}) {
throw std::runtime_error("JSON integer out of range");
}
return result;
}
bool get_bool() const;
const std::string& get_str() const;
int get_int() const;
int64_t get_int64() const;
auto get_int() const { return getInt<int>(); };
auto get_int64() const { return getInt<int64_t>(); };
double get_real() const;
const UniValue& get_obj() const;
const UniValue& get_array() const;
Expand Down
51 changes: 0 additions & 51 deletions lib/univalue_get.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,37 +29,6 @@ static bool ParsePrechecks(const std::string& str)
return true;
}

bool ParseInt32(const std::string& str, int32_t *out)
{
if (!ParsePrechecks(str))
return false;
char *endp = nullptr;
errno = 0; // strtol will not set errno if valid
long int n = strtol(str.c_str(), &endp, 10);
if(out) *out = (int32_t)n;
// Note that strtol returns a *long int*, so even if strtol doesn't report an over/underflow
// we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
// platforms the size of these types may be different.
return endp && *endp == 0 && !errno &&
n >= std::numeric_limits<int32_t>::min() &&
n <= std::numeric_limits<int32_t>::max();
}

bool ParseInt64(const std::string& str, int64_t *out)
{
if (!ParsePrechecks(str))
return false;
char *endp = nullptr;
errno = 0; // strtoll will not set errno if valid
long long int n = strtoll(str.c_str(), &endp, 10);
if(out) *out = (int64_t)n;
// Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow
// we still have to check that the returned value is within the range of an *int64_t*.
return endp && *endp == 0 && !errno &&
n >= std::numeric_limits<int64_t>::min() &&
n <= std::numeric_limits<int64_t>::max();
}

bool ParseDouble(const std::string& str, double *out)
{
if (!ParsePrechecks(str))
Expand Down Expand Up @@ -103,26 +72,6 @@ const std::string& UniValue::get_str() const
return getValStr();
}

int UniValue::get_int() const
{
if (typ != VNUM)
throw std::runtime_error("JSON value is not an integer as expected");
int32_t retval;
if (!ParseInt32(getValStr(), &retval))
throw std::runtime_error("JSON integer out of range");
return retval;
}

int64_t UniValue::get_int64() const
{
if (typ != VNUM)
throw std::runtime_error("JSON value is not an integer as expected");
int64_t retval;
if (!ParseInt64(getValStr(), &retval))
throw std::runtime_error("JSON integer out of range");
return retval;
}

double UniValue::get_real() const
{
if (typ != VNUM)
Expand Down