2015-10-01 10:37:19 +02:00
|
|
|
// Copyright 2014 BitPay Inc.
|
|
|
|
// Copyright 2015 Bitcoin Core Developers
|
|
|
|
// Distributed under the MIT software license, see the accompanying
|
2021-10-11 20:45:56 +08:00
|
|
|
// file COPYING or https://opensource.org/licenses/mit-license.php.
|
2015-10-01 10:37:19 +02:00
|
|
|
|
2022-06-11 14:29:09 +01:00
|
|
|
#ifndef BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
|
|
|
|
#define BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
|
2015-10-01 10:37:19 +02:00
|
|
|
|
2022-05-12 11:51:51 +02:00
|
|
|
#include <charconv>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <cstring>
|
|
|
|
#include <map>
|
|
|
|
#include <stdexcept>
|
2015-10-01 10:37:19 +02:00
|
|
|
#include <string>
|
2022-05-12 11:51:51 +02:00
|
|
|
#include <type_traits>
|
2015-10-01 10:37:19 +02:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
class UniValue {
|
|
|
|
public:
|
|
|
|
enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
|
|
|
|
|
|
|
|
UniValue() { typ = VNULL; }
|
|
|
|
UniValue(UniValue::VType initialType, const std::string& initialStr = "") {
|
|
|
|
typ = initialType;
|
|
|
|
val = initialStr;
|
|
|
|
}
|
2022-07-14 11:20:31 +02:00
|
|
|
template <typename Ref, typename T = std::remove_cv_t<std::remove_reference_t<Ref>>,
|
|
|
|
std::enable_if_t<std::is_floating_point_v<T> || // setFloat
|
|
|
|
std::is_same_v<bool, T> || // setBool
|
|
|
|
std::is_signed_v<T> || std::is_unsigned_v<T> || // setInt
|
|
|
|
std::is_constructible_v<std::string, T>, // setStr
|
|
|
|
bool> = true>
|
|
|
|
UniValue(Ref&& val)
|
|
|
|
{
|
|
|
|
if constexpr (std::is_floating_point_v<T>) {
|
|
|
|
setFloat(val);
|
|
|
|
} else if constexpr (std::is_same_v<bool, T>) {
|
|
|
|
setBool(val);
|
|
|
|
} else if constexpr (std::is_signed_v<T>) {
|
|
|
|
setInt(int64_t{val});
|
|
|
|
} else if constexpr (std::is_unsigned_v<T>) {
|
|
|
|
setInt(uint64_t{val});
|
|
|
|
} else {
|
|
|
|
setStr(std::string{std::forward<Ref>(val)});
|
|
|
|
}
|
2015-10-01 10:37:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void clear();
|
|
|
|
|
2022-07-29 15:23:04 +02:00
|
|
|
void setNull();
|
|
|
|
void setBool(bool val);
|
|
|
|
void setNumStr(const std::string& val);
|
|
|
|
void setInt(uint64_t val);
|
|
|
|
void setInt(int64_t val);
|
|
|
|
void setInt(int val_) { return setInt(int64_t{val_}); }
|
|
|
|
void setFloat(double val);
|
|
|
|
void setStr(const std::string& val);
|
|
|
|
void setArray();
|
|
|
|
void setObject();
|
2015-10-01 10:37:19 +02:00
|
|
|
|
|
|
|
enum VType getType() const { return typ; }
|
|
|
|
const std::string& getValStr() const { return val; }
|
|
|
|
bool empty() const { return (values.size() == 0); }
|
|
|
|
|
|
|
|
size_t size() const { return values.size(); }
|
|
|
|
|
|
|
|
bool getBool() const { return isTrue(); }
|
2017-09-29 14:27:20 +02:00
|
|
|
void getObjMap(std::map<std::string,UniValue>& kv) const;
|
|
|
|
bool checkObject(const std::map<std::string,UniValue::VType>& memberTypes) const;
|
2015-10-01 10:37:19 +02:00
|
|
|
const UniValue& operator[](const std::string& key) const;
|
2017-09-29 14:27:20 +02:00
|
|
|
const UniValue& operator[](size_t index) const;
|
|
|
|
bool exists(const std::string& key) const { size_t i; return findKey(key, i); }
|
2015-10-01 10:37:19 +02:00
|
|
|
|
|
|
|
bool isNull() const { return (typ == VNULL); }
|
|
|
|
bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
|
|
|
|
bool isFalse() const { return (typ == VBOOL) && (val != "1"); }
|
|
|
|
bool isBool() const { return (typ == VBOOL); }
|
|
|
|
bool isStr() const { return (typ == VSTR); }
|
|
|
|
bool isNum() const { return (typ == VNUM); }
|
|
|
|
bool isArray() const { return (typ == VARR); }
|
|
|
|
bool isObject() const { return (typ == VOBJ); }
|
|
|
|
|
2022-07-06 11:46:41 +02:00
|
|
|
void push_back(const UniValue& val);
|
|
|
|
void push_backV(const std::vector<UniValue>& vec);
|
2022-06-23 21:48:43 +02:00
|
|
|
template <class It>
|
2022-07-06 11:46:41 +02:00
|
|
|
void push_backV(It first, It last);
|
2015-10-01 10:37:19 +02:00
|
|
|
|
2017-09-29 14:27:20 +02:00
|
|
|
void __pushKV(const std::string& key, const UniValue& val);
|
2022-07-06 11:46:41 +02:00
|
|
|
void pushKV(const std::string& key, const UniValue& val);
|
|
|
|
void pushKVs(const UniValue& obj);
|
2015-10-01 10:37:19 +02:00
|
|
|
|
|
|
|
std::string write(unsigned int prettyIndent = 0,
|
|
|
|
unsigned int indentLevel = 0) const;
|
|
|
|
|
2017-09-29 14:27:20 +02:00
|
|
|
bool read(const char *raw, size_t len);
|
|
|
|
bool read(const char *raw) { return read(raw, strlen(raw)); }
|
2015-10-01 10:37:19 +02:00
|
|
|
bool read(const std::string& rawStr) {
|
2017-09-29 14:27:20 +02:00
|
|
|
return read(rawStr.data(), rawStr.size());
|
2015-10-01 10:37:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
UniValue::VType typ;
|
|
|
|
std::string val; // numbers are stored as C++ strings
|
|
|
|
std::vector<std::string> keys;
|
|
|
|
std::vector<UniValue> values;
|
|
|
|
|
2022-07-18 11:13:22 +02:00
|
|
|
void checkType(const VType& expected) const;
|
2017-09-29 14:27:20 +02:00
|
|
|
bool findKey(const std::string& key, size_t& retIdx) const;
|
2015-10-01 10:37:19 +02:00
|
|
|
void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
|
|
|
|
void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
|
|
|
|
|
|
|
|
public:
|
|
|
|
// Strict type-specific getters, these throw std::runtime_error if the
|
|
|
|
// value is of unexpected type
|
2016-09-30 19:58:11 +02:00
|
|
|
const std::vector<std::string>& getKeys() const;
|
|
|
|
const std::vector<UniValue>& getValues() const;
|
2022-05-12 11:51:51 +02:00
|
|
|
template <typename Int>
|
2022-07-14 18:03:22 +02:00
|
|
|
Int getInt() const;
|
2015-10-01 10:37:19 +02:00
|
|
|
bool get_bool() const;
|
2016-09-30 19:58:11 +02:00
|
|
|
const std::string& get_str() const;
|
2015-10-01 10:37:19 +02:00
|
|
|
double get_real() const;
|
|
|
|
const UniValue& get_obj() const;
|
|
|
|
const UniValue& get_array() const;
|
|
|
|
|
|
|
|
enum VType type() const { return getType(); }
|
|
|
|
friend const UniValue& find_value( const UniValue& obj, const std::string& name);
|
|
|
|
};
|
|
|
|
|
2022-06-23 21:48:43 +02:00
|
|
|
template <class It>
|
2022-07-06 11:46:41 +02:00
|
|
|
void UniValue::push_backV(It first, It last)
|
2022-06-23 21:48:43 +02:00
|
|
|
{
|
2022-07-18 11:13:22 +02:00
|
|
|
checkType(VARR);
|
2022-06-23 21:48:43 +02:00
|
|
|
values.insert(values.end(), first, last);
|
|
|
|
}
|
|
|
|
|
2022-07-14 18:03:22 +02:00
|
|
|
template <typename Int>
|
|
|
|
Int UniValue::getInt() const
|
|
|
|
{
|
|
|
|
static_assert(std::is_integral<Int>::value);
|
2022-07-18 11:13:22 +02:00
|
|
|
checkType(VNUM);
|
2022-07-14 18:03:22 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-10-01 10:37:19 +02:00
|
|
|
enum jtokentype {
|
|
|
|
JTOK_ERR = -1,
|
|
|
|
JTOK_NONE = 0, // eof
|
|
|
|
JTOK_OBJ_OPEN,
|
|
|
|
JTOK_OBJ_CLOSE,
|
|
|
|
JTOK_ARR_OPEN,
|
|
|
|
JTOK_ARR_CLOSE,
|
|
|
|
JTOK_COLON,
|
|
|
|
JTOK_COMMA,
|
|
|
|
JTOK_KW_NULL,
|
|
|
|
JTOK_KW_TRUE,
|
|
|
|
JTOK_KW_FALSE,
|
|
|
|
JTOK_NUMBER,
|
|
|
|
JTOK_STRING,
|
|
|
|
};
|
|
|
|
|
|
|
|
extern enum jtokentype getJsonToken(std::string& tokenVal,
|
2017-09-29 14:27:20 +02:00
|
|
|
unsigned int& consumed, const char *raw, const char *end);
|
2015-10-01 10:37:19 +02:00
|
|
|
extern const char *uvTypeName(UniValue::VType t);
|
|
|
|
|
2015-12-02 12:26:24 +01:00
|
|
|
static inline bool jsonTokenIsValue(enum jtokentype jtt)
|
|
|
|
{
|
|
|
|
switch (jtt) {
|
|
|
|
case JTOK_KW_NULL:
|
|
|
|
case JTOK_KW_TRUE:
|
|
|
|
case JTOK_KW_FALSE:
|
|
|
|
case JTOK_NUMBER:
|
|
|
|
case JTOK_STRING:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// not reached
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool json_isspace(int ch)
|
|
|
|
{
|
|
|
|
switch (ch) {
|
|
|
|
case 0x20:
|
|
|
|
case 0x09:
|
|
|
|
case 0x0a:
|
|
|
|
case 0x0d:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// not reached
|
|
|
|
}
|
|
|
|
|
2015-10-01 10:37:19 +02:00
|
|
|
extern const UniValue NullUniValue;
|
|
|
|
|
|
|
|
const UniValue& find_value( const UniValue& obj, const std::string& name);
|
|
|
|
|
2022-06-11 14:29:09 +01:00
|
|
|
#endif // BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
|