migrate from dynamic::Value to dv::value & total erase namespace 'dynamic'
This commit is contained in:
+64
-67
@@ -23,16 +23,12 @@ namespace dv {
|
||||
}
|
||||
|
||||
value& value::operator[](const key_t& key) {
|
||||
if (type == value_type::object) {
|
||||
return (*val.object)[key];
|
||||
}
|
||||
throw std::runtime_error("value is not an object");
|
||||
check_type(type, value_type::object);
|
||||
return (*val.object)[key];
|
||||
}
|
||||
const value& value::operator[](const key_t& key) const {
|
||||
if (type == value_type::object) {
|
||||
return (*val.object)[key];
|
||||
}
|
||||
throw std::runtime_error("value is not an object");
|
||||
check_type(type, value_type::object);
|
||||
return (*val.object)[key];
|
||||
}
|
||||
|
||||
value& value::operator=(const objects::Bytes& bytes) {
|
||||
@@ -40,23 +36,17 @@ namespace dv {
|
||||
}
|
||||
|
||||
value& value::operator[](size_t index) {
|
||||
if (type == value_type::list) {
|
||||
return (*val.list)[index];
|
||||
}
|
||||
throw std::runtime_error("value is not a list");
|
||||
check_type(type, value_type::list);
|
||||
return (*val.list)[index];
|
||||
}
|
||||
const value& value::operator[](size_t index) const {
|
||||
if (type == value_type::list) {
|
||||
return (*val.list)[index];
|
||||
}
|
||||
throw std::runtime_error("value is not a list");
|
||||
check_type(type, value_type::list);
|
||||
return (*val.list)[index];
|
||||
}
|
||||
|
||||
void value::add(value v) {
|
||||
if (type == value_type::list) {
|
||||
return val.list->push(std::move(v));
|
||||
}
|
||||
throw std::runtime_error("value is not a list");
|
||||
check_type(type, value_type::list);
|
||||
return val.list->push_back(std::move(v));
|
||||
}
|
||||
|
||||
value& value::object(const key_t& key) {
|
||||
@@ -72,54 +62,42 @@ namespace dv {
|
||||
}
|
||||
|
||||
value& value::object() {
|
||||
if (type == value_type::list) {
|
||||
return val.list->add(std::make_shared<objects::Object>());
|
||||
}
|
||||
throw std::runtime_error("value is not a list");
|
||||
check_type(type, value_type::list);
|
||||
val.list->push_back(std::make_shared<objects::Object>());
|
||||
return val.list->operator[](val.list->size()-1);
|
||||
}
|
||||
|
||||
value& value::list() {
|
||||
if (type == value_type::list) {
|
||||
return val.list->add(std::make_shared<objects::List>());
|
||||
}
|
||||
throw std::runtime_error("value is not a list");
|
||||
check_type(type, value_type::list);
|
||||
val.list->push_back(std::make_shared<objects::List>());
|
||||
return val.list->operator[](val.list->size()-1);
|
||||
}
|
||||
|
||||
list_t::iterator value::begin() {
|
||||
if (type == value_type::list) {
|
||||
return val.list->begin();
|
||||
}
|
||||
throw std::runtime_error("value is not a list");
|
||||
check_type(type, value_type::list);
|
||||
return val.list->begin();
|
||||
}
|
||||
|
||||
list_t::iterator value::end() {
|
||||
if (type == value_type::list) {
|
||||
return val.list->end();
|
||||
}
|
||||
throw std::runtime_error("value is not a list");
|
||||
check_type(type, value_type::list);
|
||||
return val.list->end();
|
||||
}
|
||||
|
||||
list_t::const_iterator value::begin() const {
|
||||
if (type == value_type::list) {
|
||||
const auto& constlist = *val.list;
|
||||
return constlist.begin();
|
||||
}
|
||||
throw std::runtime_error("value is not a list");
|
||||
check_type(type, value_type::list);
|
||||
const auto& constlist = *val.list;
|
||||
return constlist.begin();
|
||||
}
|
||||
|
||||
list_t::const_iterator value::end() const {
|
||||
if (type == value_type::list) {
|
||||
const auto& constlist = *val.list;
|
||||
return constlist.end();
|
||||
}
|
||||
throw std::runtime_error("value is not a list");
|
||||
check_type(type, value_type::list);
|
||||
const auto& constlist = *val.list;
|
||||
return constlist.end();
|
||||
}
|
||||
|
||||
const std::string& value::asString() const {
|
||||
if (type == value_type::string) {
|
||||
return *val.string;
|
||||
}
|
||||
throw std::runtime_error("type error");
|
||||
check_type(type, value_type::string);
|
||||
return *val.string;
|
||||
}
|
||||
|
||||
integer_t value::asInteger() const {
|
||||
@@ -128,7 +106,8 @@ namespace dv {
|
||||
} else if (type == value_type::number) {
|
||||
return static_cast<integer_t>(val.number);
|
||||
}
|
||||
throw std::runtime_error("type error");
|
||||
throw_type_error(type, value_type::integer);
|
||||
return 0; // unreachable
|
||||
}
|
||||
|
||||
number_t value::asNumber() const {
|
||||
@@ -137,7 +116,8 @@ namespace dv {
|
||||
} else if (type == value_type::integer) {
|
||||
return static_cast<number_t>(val.integer);
|
||||
}
|
||||
throw std::runtime_error("type error");
|
||||
throw_type_error(type, value_type::integer);
|
||||
return 0; // unreachable
|
||||
}
|
||||
|
||||
boolean_t value::asBoolean() const {
|
||||
@@ -146,31 +126,26 @@ namespace dv {
|
||||
} else if (type == value_type::integer) {
|
||||
return val.integer != 0;
|
||||
}
|
||||
throw std::runtime_error("type error");
|
||||
throw_type_error(type, value_type::boolean);
|
||||
return false; // unreachable
|
||||
}
|
||||
|
||||
objects::Bytes& value::asBytes() {
|
||||
if (type == value_type::bytes) {
|
||||
return *val.bytes;
|
||||
}
|
||||
throw std::runtime_error("type error");
|
||||
check_type(type, value_type::bytes);
|
||||
return *val.bytes;
|
||||
}
|
||||
|
||||
const objects::Bytes& value::asBytes() const {
|
||||
if (type == value_type::bytes) {
|
||||
return *val.bytes;
|
||||
}
|
||||
throw std::runtime_error("type error");
|
||||
check_type(type, value_type::bytes);
|
||||
return *val.bytes;
|
||||
}
|
||||
|
||||
const objects::Object& value::asObject() const {
|
||||
if (type == value_type::object) {
|
||||
return *val.object;
|
||||
}
|
||||
throw std::runtime_error("type error");
|
||||
check_type(type, value_type::object);
|
||||
return *val.object;
|
||||
}
|
||||
|
||||
const size_t value::size() const {
|
||||
size_t value::size() const {
|
||||
switch (type) {
|
||||
case value_type::list:
|
||||
return val.list->size();
|
||||
@@ -179,8 +154,30 @@ namespace dv {
|
||||
case value_type::string:
|
||||
return val.string->size();
|
||||
default:
|
||||
throw std::runtime_error("type error");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool value::has(const key_t& k) const {
|
||||
if (type == value_type::object) {
|
||||
return val.object->find(k) != val.object->end();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void value::erase(const key_t& key) {
|
||||
check_type(type, value_type::object);
|
||||
val.object->erase(key);
|
||||
}
|
||||
|
||||
void value::erase(size_t index) {
|
||||
check_type(type, value_type::list);
|
||||
val.list->erase(val.list->begin() + index);
|
||||
}
|
||||
}
|
||||
|
||||
#include "coders/json.hpp"
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const dv::value& value) {
|
||||
return stream << json::stringify(value, false);
|
||||
}
|
||||
|
||||
+233
-77
@@ -6,6 +6,7 @@
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace util {
|
||||
@@ -30,10 +31,18 @@ namespace dv {
|
||||
string
|
||||
};
|
||||
|
||||
namespace objects {
|
||||
class Object;
|
||||
class List;
|
||||
using Bytes = util::Buffer<byte_t>;
|
||||
inline const std::string& type_name(value_type type) {
|
||||
static std::string type_names[] = {
|
||||
"none",
|
||||
"number",
|
||||
"boolean",
|
||||
"integer",
|
||||
"object",
|
||||
"list",
|
||||
"bytes",
|
||||
"string"
|
||||
};
|
||||
return type_names[static_cast<int>(type)];
|
||||
}
|
||||
|
||||
class value;
|
||||
@@ -45,6 +54,58 @@ namespace dv {
|
||||
using reference = value&;
|
||||
using const_reference = const value&;
|
||||
|
||||
namespace objects {
|
||||
using Object = std::unordered_map<key_t, value>;
|
||||
using List = std::vector<value>;
|
||||
using Bytes = util::Buffer<byte_t>;
|
||||
}
|
||||
|
||||
/// @brief nullable value reference returned by value.at(...)
|
||||
struct elementreference {
|
||||
value* ptr;
|
||||
|
||||
elementreference(value* ptr) : ptr(ptr) {}
|
||||
|
||||
inline operator bool() const {
|
||||
return ptr != nullptr;
|
||||
}
|
||||
|
||||
inline value& operator*() {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline const value& operator*() const {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
bool get(std::string& dst) const;
|
||||
bool get(bool& dst) const;
|
||||
bool get(int8_t& dst) const;
|
||||
bool get(int16_t& dst) const;
|
||||
bool get(int32_t& dst) const;
|
||||
bool get(int64_t& dst) const;
|
||||
bool get(uint8_t& dst) const;
|
||||
bool get(uint16_t& dst) const;
|
||||
bool get(uint32_t& dst) const;
|
||||
bool get(uint64_t& dst) const;
|
||||
bool get(float& dst) const;
|
||||
bool get(double& dst) const;
|
||||
};
|
||||
|
||||
inline void throw_type_error(value_type got, value_type expected) {
|
||||
// place breakpoint here to find cause
|
||||
throw std::runtime_error(
|
||||
"type error: expected " + type_name(expected) + ", got " +
|
||||
type_name(got)
|
||||
);
|
||||
}
|
||||
|
||||
inline void check_type(value_type got, value_type expected) {
|
||||
if (got != expected) {
|
||||
throw_type_error(got, expected);
|
||||
}
|
||||
}
|
||||
|
||||
class value {
|
||||
value_type type = value_type::none;
|
||||
union value_u {
|
||||
@@ -149,6 +210,10 @@ namespace dv {
|
||||
}
|
||||
}
|
||||
|
||||
inline value& operator=(std::nullptr_t) {
|
||||
return setNone();
|
||||
}
|
||||
|
||||
inline value& operator=(int8_t v) {
|
||||
return setInteger(v);
|
||||
}
|
||||
@@ -302,6 +367,10 @@ namespace dv {
|
||||
return add(value(v));
|
||||
}
|
||||
|
||||
void erase(const key_t& key);
|
||||
|
||||
void erase(size_t index);
|
||||
|
||||
value& operator[](const key_t& key);
|
||||
|
||||
const value& operator[](const key_t& key) const;
|
||||
@@ -310,6 +379,14 @@ namespace dv {
|
||||
|
||||
const value& operator[](size_t index) const;
|
||||
|
||||
bool operator!=(std::nullptr_t) const noexcept {
|
||||
return type != value_type::none;
|
||||
}
|
||||
|
||||
bool operator==(std::nullptr_t) const noexcept {
|
||||
return type == value_type::none;
|
||||
}
|
||||
|
||||
value& object(const key_t& key);
|
||||
|
||||
value& list(const key_t& key);
|
||||
@@ -342,93 +419,109 @@ namespace dv {
|
||||
return type;
|
||||
}
|
||||
|
||||
const size_t size() const;
|
||||
std::string asString(std::string def) const {
|
||||
if (type != value_type::string) {
|
||||
return def;
|
||||
}
|
||||
return *val.string;
|
||||
}
|
||||
|
||||
const size_t length() const {
|
||||
std::string asString(const char* s) const {
|
||||
return asString(std::string(s));
|
||||
}
|
||||
|
||||
integer_t asBoolean(boolean_t def) const {
|
||||
switch (type) {
|
||||
case value_type::boolean:
|
||||
return val.boolean;
|
||||
default:
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
integer_t asInteger(integer_t def) const {
|
||||
switch (type) {
|
||||
case value_type::integer:
|
||||
return val.integer;
|
||||
case value_type::number:
|
||||
return static_cast<integer_t>(val.number);
|
||||
default:
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
integer_t asNumber(integer_t def) const {
|
||||
switch (type) {
|
||||
case value_type::integer:
|
||||
return static_cast<number_t>(val.integer);
|
||||
case value_type::number:
|
||||
return val.number;
|
||||
default:
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
elementreference at(const key_t& k) const {
|
||||
check_type(type, value_type::object);
|
||||
const auto& found = val.object->find(k);
|
||||
if (found == val.object->end()) {
|
||||
return elementreference(nullptr);
|
||||
}
|
||||
return elementreference(&found->second);
|
||||
}
|
||||
|
||||
elementreference at(size_t index) {
|
||||
check_type(type, value_type::list);
|
||||
return elementreference(&val.list->at(index));
|
||||
}
|
||||
|
||||
const elementreference at(size_t index) const {
|
||||
check_type(type, value_type::list);
|
||||
return elementreference(&val.list->at(index));
|
||||
}
|
||||
|
||||
bool has(const key_t& k) const;
|
||||
|
||||
size_t size() const;
|
||||
|
||||
size_t length() const {
|
||||
return size();
|
||||
}
|
||||
inline bool empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
inline bool isString() const {
|
||||
return type == value_type::string;
|
||||
}
|
||||
inline bool isObject() const {
|
||||
return type == value_type::object;
|
||||
}
|
||||
inline bool isList() const {
|
||||
return type == value_type::list;
|
||||
}
|
||||
inline bool isInteger() const {
|
||||
return type == value_type::integer;
|
||||
}
|
||||
inline bool isNumber() const {
|
||||
return type == value_type::number;
|
||||
}
|
||||
};
|
||||
|
||||
inline value none = value();
|
||||
}
|
||||
|
||||
namespace dv::objects {
|
||||
class Object {
|
||||
map_t map;
|
||||
public:
|
||||
Object() = default;
|
||||
Object(std::initializer_list<pair> pairs) : map(pairs) {}
|
||||
Object(const Object&) = delete;
|
||||
~Object() = default;
|
||||
inline bool is_numeric(const value& val) {
|
||||
return val.isInteger() && val.isNumber();
|
||||
}
|
||||
|
||||
reference operator[](const key_t& key) {
|
||||
return map[key];
|
||||
}
|
||||
const_reference operator[](const key_t& key) const {
|
||||
return map.at(key);
|
||||
}
|
||||
|
||||
map_t::const_iterator begin() const {
|
||||
return map.begin();
|
||||
}
|
||||
map_t::const_iterator end() const {
|
||||
return map.end();
|
||||
}
|
||||
|
||||
const size_t size() const {
|
||||
return map.size();
|
||||
}
|
||||
};
|
||||
|
||||
class List {
|
||||
list_t list;
|
||||
public:
|
||||
List() = default;
|
||||
List(std::initializer_list<value> values) : list(values) {}
|
||||
List(const List&) = delete;
|
||||
~List() = default;
|
||||
|
||||
reference operator[](std::size_t index) {
|
||||
return list.at(index);
|
||||
}
|
||||
|
||||
const_reference operator[](std::size_t index) const {
|
||||
return list.at(index);
|
||||
}
|
||||
|
||||
void push(value v) {
|
||||
list.push_back(std::move(v));
|
||||
}
|
||||
|
||||
reference add(value v) {
|
||||
list.push_back(std::move(v));
|
||||
return list[list.size()-1];
|
||||
}
|
||||
|
||||
auto begin() {
|
||||
return list.begin();
|
||||
}
|
||||
auto end() {
|
||||
return list.end();
|
||||
}
|
||||
|
||||
list_t::const_iterator begin() const {
|
||||
return list.begin();
|
||||
}
|
||||
list_t::const_iterator end() const {
|
||||
return list.end();
|
||||
}
|
||||
|
||||
const size_t size() const {
|
||||
return list.size();
|
||||
}
|
||||
};
|
||||
using to_string_func = std::function<std::string(const value&)>;
|
||||
}
|
||||
|
||||
namespace dv {
|
||||
inline const std::string& type_name(const value& value) {
|
||||
return type_name(value.getType());
|
||||
}
|
||||
|
||||
inline value object() {
|
||||
return std::make_shared<objects::Object>();
|
||||
}
|
||||
@@ -440,4 +533,67 @@ namespace dv {
|
||||
inline value list(std::initializer_list<value> values) {
|
||||
return std::make_shared<objects::List>(values);
|
||||
}
|
||||
|
||||
template<typename T> inline bool get_to_int(value* ptr, T& dst) {
|
||||
if (ptr) {
|
||||
dst = ptr->asInteger();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template<typename T> inline bool get_to_num(value* ptr, T& dst) {
|
||||
if (ptr) {
|
||||
dst = ptr->asNumber();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline bool elementreference::get(std::string& dst) const {
|
||||
if (ptr) {
|
||||
dst = ptr->asString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool elementreference::get(bool& dst) const {
|
||||
if (ptr) {
|
||||
dst = ptr->asBoolean();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool elementreference::get(int8_t& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool elementreference::get(int16_t& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool elementreference::get(int32_t& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool elementreference::get(int64_t& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool elementreference::get(uint8_t& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool elementreference::get(uint16_t& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool elementreference::get(uint32_t& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool elementreference::get(uint64_t& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool elementreference::get(float& dst) const {
|
||||
return get_to_num(ptr, dst);
|
||||
}
|
||||
inline bool elementreference::get(double& dst) const {
|
||||
return get_to_num(ptr, dst);
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const dv::value& value);
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "dv.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace dv {
|
||||
template <int n>
|
||||
inline dv::value to_value(glm::vec<n, float> vec) {
|
||||
auto list = dv::list();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
list.add(vec[i]);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
template <int n, int m>
|
||||
inline dv::value to_value(glm::mat<n, m, float> mat) {
|
||||
auto list = dv::list();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
for (size_t j = 0; j < m; j++) {
|
||||
list.add(mat[i][j]);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
template <int n>
|
||||
void get_vec(const dv::value& list, glm::vec<n, float>& vec) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
vec[i] = list[i].asNumber();
|
||||
}
|
||||
}
|
||||
|
||||
template <int n>
|
||||
void get_vec(const dv::value& map, const std::string& key, glm::vec<n, float>& vec) {
|
||||
if (!map.has(key)) {
|
||||
return;
|
||||
}
|
||||
auto& list = map[key];
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
vec[i] = list[i].asNumber();
|
||||
}
|
||||
}
|
||||
|
||||
template <int n, int m>
|
||||
void get_mat(
|
||||
const dv::value& list,
|
||||
glm::mat<n, m, float>& mat
|
||||
) {
|
||||
for (size_t y = 0; y < n; y++) {
|
||||
for (size_t x = 0; x < m; x++) {
|
||||
mat[y][x] = list[y * m + x].asNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <int n, int m>
|
||||
void get_mat(
|
||||
const dv::value& map,
|
||||
const std::string& key,
|
||||
glm::mat<n, m, float>& mat
|
||||
) {
|
||||
if (!map.has(key)) {
|
||||
return;
|
||||
}
|
||||
auto& list = map[key];
|
||||
for (size_t y = 0; y < n; y++) {
|
||||
for (size_t x = 0; x < m; x++) {
|
||||
mat[y][x] = list[y * m + x].asNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,345 +0,0 @@
|
||||
#include "dynamic.hpp"
|
||||
|
||||
#include "coders/json.hpp"
|
||||
|
||||
using namespace dynamic;
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const dynamic::Value& value) {
|
||||
stream << json::stringify(value, false, " ");
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const dynamic::Map& value) {
|
||||
stream << json::stringify(&value, false, " ");
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const dynamic::Map_sptr& value) {
|
||||
stream << json::stringify(value, false, " ");
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const dynamic::List& value) {
|
||||
stream << json::stringify(&value, false, " ");
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(
|
||||
std::ostream& stream, const dynamic::List_sptr& value
|
||||
) {
|
||||
stream << json::stringify(value, false, " ");
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::string List::str(size_t index) const {
|
||||
const auto& value = values[index];
|
||||
switch (static_cast<Type>(value.index())) {
|
||||
case Type::string:
|
||||
return std::get<std::string>(value);
|
||||
case Type::boolean:
|
||||
return std::get<bool>(value) ? "true" : "false";
|
||||
case Type::number:
|
||||
return std::to_string(std::get<double>(value));
|
||||
case Type::integer:
|
||||
return std::to_string(std::get<int64_t>(value));
|
||||
default:
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
}
|
||||
|
||||
number_t List::num(size_t index) const {
|
||||
const auto& value = values[index];
|
||||
switch (static_cast<Type>(value.index())) {
|
||||
case Type::number:
|
||||
return std::get<number_t>(value);
|
||||
case Type::integer:
|
||||
return std::get<integer_t>(value);
|
||||
case Type::string:
|
||||
return std::stoll(std::get<std::string>(value));
|
||||
case Type::boolean:
|
||||
return std::get<bool>(value);
|
||||
default:
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
}
|
||||
|
||||
integer_t List::integer(size_t index) const {
|
||||
const auto& value = values[index];
|
||||
switch (static_cast<Type>(value.index())) {
|
||||
case Type::number:
|
||||
return std::get<number_t>(value);
|
||||
case Type::integer:
|
||||
return std::get<integer_t>(value);
|
||||
case Type::string:
|
||||
return std::stoll(std::get<std::string>(value));
|
||||
case Type::boolean:
|
||||
return std::get<bool>(value);
|
||||
default:
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
}
|
||||
|
||||
const Map_sptr& List::map(size_t index) const {
|
||||
if (auto* val = std::get_if<Map_sptr>(&values[index])) {
|
||||
return *val;
|
||||
} else {
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
}
|
||||
|
||||
List* List::list(size_t index) const {
|
||||
if (auto* val = std::get_if<List_sptr>(&values[index])) {
|
||||
return val->get();
|
||||
} else {
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
}
|
||||
|
||||
bool List::flag(size_t index) const {
|
||||
const auto& value = values[index];
|
||||
switch (static_cast<Type>(value.index())) {
|
||||
case Type::integer:
|
||||
return std::get<integer_t>(value);
|
||||
case Type::boolean:
|
||||
return std::get<bool>(value);
|
||||
default:
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
}
|
||||
|
||||
Value* List::getValueWriteable(size_t index) {
|
||||
return &values.at(index);
|
||||
}
|
||||
|
||||
List& List::put(const Value& value) {
|
||||
values.emplace_back(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
List& List::putList() {
|
||||
auto arr = create_list();
|
||||
put(arr);
|
||||
return *arr;
|
||||
}
|
||||
|
||||
Map& List::putMap() {
|
||||
auto map = create_map();
|
||||
put(map);
|
||||
return *map;
|
||||
}
|
||||
|
||||
ByteBuffer& List::putBytes(size_t size) {
|
||||
auto bytes = create_bytes(size);
|
||||
put(bytes);
|
||||
return *bytes;
|
||||
}
|
||||
|
||||
void List::remove(size_t index) {
|
||||
values.erase(values.begin() + index);
|
||||
}
|
||||
|
||||
void Map::str(const std::string& key, std::string& dst) const {
|
||||
dst = get(key, dst);
|
||||
}
|
||||
|
||||
std::string Map::get(const std::string& key, const std::string& def) const {
|
||||
auto found = values.find(key);
|
||||
if (found == values.end()) return def;
|
||||
auto& value = found->second;
|
||||
switch (static_cast<Type>(value.index())) {
|
||||
case Type::string:
|
||||
return std::get<std::string>(value);
|
||||
case Type::boolean:
|
||||
return std::get<bool>(value) ? "true" : "false";
|
||||
case Type::number:
|
||||
return std::to_string(std::get<number_t>(value));
|
||||
case Type::integer:
|
||||
return std::to_string(std::get<integer_t>(value));
|
||||
default:
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
}
|
||||
|
||||
number_t Map::get(const std::string& key, double def) const {
|
||||
auto found = values.find(key);
|
||||
if (found == values.end()) return def;
|
||||
auto& value = found->second;
|
||||
switch (static_cast<Type>(value.index())) {
|
||||
case Type::number:
|
||||
return std::get<number_t>(value);
|
||||
case Type::integer:
|
||||
return std::get<integer_t>(value);
|
||||
case Type::string:
|
||||
return std::stoull(std::get<std::string>(value));
|
||||
case Type::boolean:
|
||||
return std::get<bool>(value);
|
||||
default:
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
}
|
||||
|
||||
integer_t Map::get(const std::string& key, integer_t def) const {
|
||||
auto found = values.find(key);
|
||||
if (found == values.end()) return def;
|
||||
auto& value = found->second;
|
||||
switch (static_cast<Type>(value.index())) {
|
||||
case Type::number:
|
||||
return std::get<number_t>(value);
|
||||
case Type::integer:
|
||||
return std::get<integer_t>(value);
|
||||
case Type::string:
|
||||
return std::stoull(std::get<std::string>(value));
|
||||
case Type::boolean:
|
||||
return std::get<bool>(value);
|
||||
default:
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
}
|
||||
|
||||
bool Map::get(const std::string& key, bool def) const {
|
||||
auto found = values.find(key);
|
||||
if (found == values.end()) return def;
|
||||
auto& value = found->second;
|
||||
switch (static_cast<Type>(value.index())) {
|
||||
case Type::integer:
|
||||
return std::get<integer_t>(value);
|
||||
case Type::boolean:
|
||||
return std::get<bool>(value);
|
||||
default:
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
}
|
||||
|
||||
void Map::num(const std::string& key, double& dst) const {
|
||||
dst = get(key, dst);
|
||||
}
|
||||
|
||||
void Map::num(const std::string& key, float& dst) const {
|
||||
dst = get(key, static_cast<number_t>(dst));
|
||||
}
|
||||
|
||||
void Map::num(const std::string& key, ubyte& dst) const {
|
||||
dst = get(key, static_cast<integer_t>(dst));
|
||||
}
|
||||
|
||||
void Map::num(const std::string& key, int& dst) const {
|
||||
dst = get(key, static_cast<integer_t>(dst));
|
||||
}
|
||||
|
||||
void Map::num(const std::string& key, int64_t& dst) const {
|
||||
dst = get(key, dst);
|
||||
}
|
||||
|
||||
void Map::num(const std::string& key, uint64_t& dst) const {
|
||||
dst = get(key, static_cast<integer_t>(dst));
|
||||
}
|
||||
|
||||
void Map::num(const std::string& key, uint& dst) const {
|
||||
dst = get(key, static_cast<integer_t>(dst));
|
||||
}
|
||||
|
||||
Map_sptr Map::map(const std::string& key) const {
|
||||
auto found = values.find(key);
|
||||
if (found != values.end()) {
|
||||
if (auto* val = std::get_if<Map_sptr>(&found->second)) {
|
||||
return *val;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
List_sptr Map::list(const std::string& key) const {
|
||||
auto found = values.find(key);
|
||||
if (found != values.end()) return std::get<List_sptr>(found->second);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ByteBuffer_sptr Map::bytes(const std::string& key) const {
|
||||
auto found = values.find(key);
|
||||
if (found != values.end()) return std::get<ByteBuffer_sptr>(found->second);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Map::flag(const std::string& key, bool& dst) const {
|
||||
dst = get(key, dst);
|
||||
}
|
||||
|
||||
Map& Map::put(const std::string& key, const Value& value) {
|
||||
values[key] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Map::remove(const std::string& key) {
|
||||
values.erase(key);
|
||||
}
|
||||
|
||||
List& Map::putList(const std::string& key) {
|
||||
auto arr = create_list();
|
||||
put(key, arr);
|
||||
return *arr;
|
||||
}
|
||||
|
||||
Map& Map::putMap(const std::string& key) {
|
||||
auto obj = create_map();
|
||||
put(key, obj);
|
||||
return *obj;
|
||||
}
|
||||
|
||||
ByteBuffer& Map::putBytes(const std::string& key, size_t size) {
|
||||
auto bytes = create_bytes(size);
|
||||
put(key, bytes);
|
||||
return *bytes;
|
||||
}
|
||||
|
||||
bool Map::has(const std::string& key) const {
|
||||
return values.find(key) != values.end();
|
||||
}
|
||||
|
||||
size_t Map::size() const {
|
||||
return values.size();
|
||||
}
|
||||
|
||||
static const std::string TYPE_NAMES[] {
|
||||
"none",
|
||||
"map",
|
||||
"list",
|
||||
"string",
|
||||
"number",
|
||||
"bool",
|
||||
"integer",
|
||||
};
|
||||
|
||||
const std::string& dynamic::type_name(const Value& value) {
|
||||
return TYPE_NAMES[value.index()];
|
||||
}
|
||||
|
||||
List_sptr dynamic::create_list(std::initializer_list<Value> values) {
|
||||
return std::make_shared<List>(values);
|
||||
}
|
||||
|
||||
Map_sptr dynamic::create_map(
|
||||
std::initializer_list<std::pair<const std::string, Value>> entries
|
||||
) {
|
||||
return std::make_shared<Map>(entries);
|
||||
}
|
||||
|
||||
ByteBuffer_sptr dynamic::create_bytes(size_t size) {
|
||||
return std::make_shared<ByteBuffer>(size);
|
||||
}
|
||||
|
||||
number_t dynamic::get_number(const Value& value) {
|
||||
if (auto num = std::get_if<number_t>(&value)) {
|
||||
return *num;
|
||||
} else if (auto num = std::get_if<integer_t>(&value)) {
|
||||
return *num;
|
||||
}
|
||||
throw std::runtime_error("cannot cast " + type_name(value) + " to number");
|
||||
}
|
||||
|
||||
integer_t dynamic::get_integer(const Value& value) {
|
||||
if (auto num = std::get_if<integer_t>(&value)) {
|
||||
return *num;
|
||||
}
|
||||
throw std::runtime_error("cannot cast " + type_name(value) + " to integer");
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "dynamic_fwd.hpp"
|
||||
|
||||
namespace dynamic {
|
||||
enum class Type {
|
||||
none = 0,
|
||||
map,
|
||||
list,
|
||||
bytes,
|
||||
string,
|
||||
number,
|
||||
boolean,
|
||||
integer
|
||||
};
|
||||
|
||||
const std::string& type_name(const Value& value);
|
||||
List_sptr create_list(std::initializer_list<Value> values = {});
|
||||
Map_sptr create_map(
|
||||
std::initializer_list<std::pair<const std::string, Value>> entries = {}
|
||||
);
|
||||
ByteBuffer_sptr create_bytes(size_t size);
|
||||
|
||||
number_t get_number(const Value& value);
|
||||
integer_t get_integer(const Value& value);
|
||||
|
||||
inline bool is_numeric(const Value& value) {
|
||||
return std::holds_alternative<number_t>(value) ||
|
||||
std::holds_alternative<integer_t>(value);
|
||||
}
|
||||
|
||||
inline number_t as_number(const Value& value) {
|
||||
if (auto num = std::get_if<number_t>(&value)) {
|
||||
return *num;
|
||||
} else if (auto num = std::get_if<integer_t>(&value)) {
|
||||
return *num;
|
||||
}
|
||||
return NAN;
|
||||
}
|
||||
|
||||
class List {
|
||||
public:
|
||||
std::vector<Value> values;
|
||||
|
||||
List() = default;
|
||||
List(std::vector<Value> values) : values(std::move(values)) {
|
||||
}
|
||||
|
||||
std::string str(size_t index) const;
|
||||
number_t num(size_t index) const;
|
||||
integer_t integer(size_t index) const;
|
||||
const Map_sptr& map(size_t index) const;
|
||||
List* list(size_t index) const;
|
||||
bool flag(size_t index) const;
|
||||
|
||||
inline size_t size() const {
|
||||
return values.size();
|
||||
}
|
||||
|
||||
inline Value& get(size_t i) {
|
||||
return values.at(i);
|
||||
}
|
||||
|
||||
List& put(std::unique_ptr<Map> value) {
|
||||
return put(Map_sptr(std::move(value)));
|
||||
}
|
||||
List& put(std::unique_ptr<List> value) {
|
||||
return put(List_sptr(std::move(value)));
|
||||
}
|
||||
List& put(std::unique_ptr<ByteBuffer> value) {
|
||||
return put(ByteBuffer_sptr(std::move(value)));
|
||||
}
|
||||
List& put(const Value& value);
|
||||
|
||||
Value* getValueWriteable(size_t index);
|
||||
|
||||
List& putList();
|
||||
Map& putMap();
|
||||
ByteBuffer& putBytes(size_t size);
|
||||
|
||||
void remove(size_t index);
|
||||
};
|
||||
|
||||
class Map {
|
||||
public:
|
||||
std::unordered_map<std::string, Value> values;
|
||||
|
||||
Map() = default;
|
||||
Map(std::unordered_map<std::string, Value> values)
|
||||
: values(std::move(values)) {};
|
||||
|
||||
template <typename T>
|
||||
T get(const std::string& key) const {
|
||||
if (!has(key)) {
|
||||
throw std::runtime_error("missing key '" + key + "'");
|
||||
}
|
||||
return get(key, T());
|
||||
}
|
||||
|
||||
std::string get(const std::string& key, const std::string& def) const;
|
||||
number_t get(const std::string& key, double def) const;
|
||||
integer_t get(const std::string& key, integer_t def) const;
|
||||
bool get(const std::string& key, bool def) const;
|
||||
|
||||
int get(const std::string& key, int def) const {
|
||||
return get(key, static_cast<integer_t>(def));
|
||||
}
|
||||
uint get(const std::string& key, uint def) const {
|
||||
return get(key, static_cast<integer_t>(def));
|
||||
}
|
||||
uint64_t get(const std::string& key, uint64_t def) const {
|
||||
return get(key, static_cast<integer_t>(def));
|
||||
}
|
||||
|
||||
void str(const std::string& key, std::string& dst) const;
|
||||
void num(const std::string& key, int& dst) const;
|
||||
void num(const std::string& key, float& dst) const;
|
||||
void num(const std::string& key, uint& dst) const;
|
||||
void num(const std::string& key, int64_t& dst) const;
|
||||
void num(const std::string& key, uint64_t& dst) const;
|
||||
void num(const std::string& key, ubyte& dst) const;
|
||||
void num(const std::string& key, double& dst) const;
|
||||
Map_sptr map(const std::string& key) const;
|
||||
List_sptr list(const std::string& key) const;
|
||||
ByteBuffer_sptr bytes(const std::string& key) const;
|
||||
void flag(const std::string& key, bool& dst) const;
|
||||
|
||||
Map& put(std::string key, std::unique_ptr<Map> value) {
|
||||
return put(key, Map_sptr(value.release()));
|
||||
}
|
||||
Map& put(std::string key, std::unique_ptr<List> value) {
|
||||
return put(key, List_sptr(value.release()));
|
||||
}
|
||||
Map& put(std::string key, int value) {
|
||||
return put(key, Value(static_cast<integer_t>(value)));
|
||||
}
|
||||
Map& put(std::string key, unsigned int value) {
|
||||
return put(key, Value(static_cast<integer_t>(value)));
|
||||
}
|
||||
Map& put(std::string key, int64_t value) {
|
||||
return put(key, Value(static_cast<integer_t>(value)));
|
||||
}
|
||||
Map& put(std::string key, uint64_t value) {
|
||||
return put(key, Value(static_cast<integer_t>(value)));
|
||||
}
|
||||
Map& put(std::string key, float value) {
|
||||
return put(key, Value(static_cast<number_t>(value)));
|
||||
}
|
||||
Map& put(std::string key, double value) {
|
||||
return put(key, Value(static_cast<number_t>(value)));
|
||||
}
|
||||
Map& put(std::string key, bool value) {
|
||||
return put(key, Value(static_cast<bool>(value)));
|
||||
}
|
||||
Map& put(const std::string& key, const ByteBuffer* bytes) {
|
||||
return put(key, std::make_unique<ByteBuffer>(
|
||||
bytes->data(), bytes->size()));
|
||||
}
|
||||
Map& put(std::string key, const ubyte* bytes, size_t size) {
|
||||
return put(key, std::make_unique<ByteBuffer>(bytes, size));
|
||||
}
|
||||
Map& put(std::string key, const char* value) {
|
||||
return put(key, Value(value));
|
||||
}
|
||||
Map& put(const std::string& key, const Value& value);
|
||||
|
||||
void remove(const std::string& key);
|
||||
|
||||
List& putList(const std::string& key);
|
||||
Map& putMap(const std::string& key);
|
||||
ByteBuffer& putBytes(const std::string& key, size_t size);
|
||||
|
||||
bool has(const std::string& key) const;
|
||||
size_t size() const;
|
||||
};
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const dynamic::Value& value);
|
||||
std::ostream& operator<<(std::ostream& stream, const dynamic::Map& value);
|
||||
std::ostream& operator<<(std::ostream& stream, const dynamic::Map_sptr& value);
|
||||
std::ostream& operator<<(std::ostream& stream, const dynamic::List& value);
|
||||
std::ostream& operator<<(std::ostream& stream, const dynamic::List_sptr& value);
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "util/Buffer.hpp"
|
||||
|
||||
namespace dynamic {
|
||||
class Map;
|
||||
class List;
|
||||
|
||||
using ByteBuffer = util::Buffer<ubyte>;
|
||||
using Map_sptr = std::shared_ptr<Map>;
|
||||
using List_sptr = std::shared_ptr<List>;
|
||||
using ByteBuffer_sptr = std::shared_ptr<ByteBuffer>;
|
||||
|
||||
struct none {};
|
||||
|
||||
inline constexpr none NONE = {};
|
||||
|
||||
using Value = std::variant<
|
||||
none,
|
||||
Map_sptr,
|
||||
List_sptr,
|
||||
ByteBuffer_sptr,
|
||||
std::string,
|
||||
number_t,
|
||||
bool,
|
||||
integer_t>;
|
||||
|
||||
using to_string_func = std::function<std::string(const Value&)>;
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "dynamic.hpp"
|
||||
|
||||
namespace dynamic {
|
||||
template <int n>
|
||||
inline dynamic::List_sptr to_value(glm::vec<n, float> vec) {
|
||||
auto list = dynamic::create_list();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
list->put(vec[i]);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
template <int n, int m>
|
||||
inline dynamic::List_sptr to_value(glm::mat<n, m, float> mat) {
|
||||
auto list = dynamic::create_list();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
for (size_t j = 0; j < m; j++) {
|
||||
list->put(mat[i][j]);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
template <int n>
|
||||
void get_vec(
|
||||
const dynamic::Map_sptr& root,
|
||||
const std::string& name,
|
||||
glm::vec<n, float>& vec
|
||||
) {
|
||||
if (const auto& list = root->list(name)) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
vec[i] = list->num(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <int n>
|
||||
void get_vec(
|
||||
const dynamic::List_sptr& root, size_t index, glm::vec<n, float>& vec
|
||||
) {
|
||||
if (const auto& list = root->list(index)) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
vec[i] = list->num(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <int n, int m>
|
||||
void get_mat(
|
||||
const dynamic::Map_sptr& root,
|
||||
const std::string& name,
|
||||
glm::mat<n, m, float>& mat
|
||||
) {
|
||||
if (const auto& list = root->list(name)) {
|
||||
for (size_t y = 0; y < n; y++) {
|
||||
for (size_t x = 0; x < m; x++) {
|
||||
mat[y][x] = list->num(y * m + x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <int n, int m>
|
||||
void get_mat(
|
||||
const dynamic::List_sptr& root, size_t index, glm::mat<n, m, float>& mat
|
||||
) {
|
||||
if (const auto& list = root->list(index)) {
|
||||
for (size_t y = 0; y < n; y++) {
|
||||
for (size_t x = 0; x < m; x++) {
|
||||
mat[y][x] = list->num(y * m + x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user