Merge branch 'main' into blocks-metadata
This commit is contained in:
+19
-22
@@ -348,41 +348,38 @@ std::string_view StructLayout::getChars(
|
||||
return std::string_view(ptr, strnlen(ptr, field.elements));
|
||||
}
|
||||
|
||||
std::unique_ptr<dynamic::Map> StructLayout::serialize() const {
|
||||
auto map = std::make_unique<dynamic::Map>();
|
||||
dv::value StructLayout::serialize() const {
|
||||
auto map = dv::object();
|
||||
for (const auto& [name, index] : indices) {
|
||||
auto& fieldmap = map->putMap(name);
|
||||
auto& fieldmap = map.object(name);
|
||||
const auto& field = fields[index];
|
||||
fieldmap.put("type", to_string(field.type));
|
||||
fieldmap["type"] = to_string(field.type);
|
||||
if (field.elements != 1) {
|
||||
fieldmap.put("length", field.elements);
|
||||
fieldmap["length"] = field.elements;
|
||||
}
|
||||
if (field.convertStrategy != FieldConvertStrategy::RESET) {
|
||||
fieldmap.put("convert-strategy", to_string(field.convertStrategy));
|
||||
fieldmap["convert-strategy"] = to_string(field.convertStrategy);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
void StructLayout::deserialize(dynamic::Map* src) {
|
||||
void StructLayout::deserialize(const dv::value& src) {
|
||||
std::vector<Field> fields;
|
||||
for (auto& [name, value] : src->values) {
|
||||
if (auto fieldmapptr = std::get_if<dynamic::Map_sptr>(&value)) {
|
||||
const auto& fieldmap = *fieldmapptr;
|
||||
for (const auto& [name, fieldmap] : src.asObject()) {
|
||||
const auto& typeName = fieldmap["type"].asString();
|
||||
FieldType type = FieldType_from_string(typeName);
|
||||
|
||||
int elements = 1;
|
||||
fieldmap.at("length").get(elements);
|
||||
|
||||
auto typeName = fieldmap->get<std::string>("type");
|
||||
FieldType type = FieldType_from_string(typeName);
|
||||
|
||||
int elements = fieldmap->get("length", 1);
|
||||
|
||||
auto convertStrategy = FieldConvertStrategy::RESET;
|
||||
if (fieldmap->has("convert-strategy")) {
|
||||
convertStrategy = FieldConvertStrategy_from_string(
|
||||
fieldmap->get<std::string>("convert-strategy")
|
||||
);
|
||||
}
|
||||
fields.push_back(Field {type, name, elements, convertStrategy});
|
||||
auto convertStrategy = FieldConvertStrategy::RESET;
|
||||
if (fieldmap.has("convert-strategy")) {
|
||||
convertStrategy = FieldConvertStrategy_from_string(
|
||||
fieldmap["convert-strategy"].asString()
|
||||
);
|
||||
}
|
||||
fields.push_back(Field {type, name, elements, convertStrategy});
|
||||
}
|
||||
*this = create(fields);
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace data {
|
||||
[[nodiscard]]
|
||||
static StructLayout create(const std::vector<Field>& fields);
|
||||
|
||||
std::unique_ptr<dynamic::Map> serialize() const override;
|
||||
void deserialize(dynamic::Map* src) override;
|
||||
dv::value serialize() const override;
|
||||
void deserialize(const dv::value& src) override;
|
||||
};
|
||||
}
|
||||
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
#include "dv.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "util/Buffer.hpp"
|
||||
|
||||
namespace dv {
|
||||
value& value::operator[](const key_t& key) {
|
||||
check_type(type, value_type::object);
|
||||
return (*val.object)[key];
|
||||
}
|
||||
const value& value::operator[](const key_t& key) const {
|
||||
check_type(type, value_type::object);
|
||||
return (*val.object)[key];
|
||||
}
|
||||
|
||||
value& value::operator=(const objects::Bytes& bytes) {
|
||||
return setBytes(std::make_shared<objects::Bytes>(bytes));
|
||||
}
|
||||
|
||||
value& value::operator[](size_t index) {
|
||||
check_type(type, value_type::list);
|
||||
return (*val.list)[index];
|
||||
}
|
||||
const value& value::operator[](size_t index) const {
|
||||
check_type(type, value_type::list);
|
||||
return (*val.list)[index];
|
||||
}
|
||||
|
||||
void value::add(value v) {
|
||||
check_type(type, value_type::list);
|
||||
return val.list->push_back(std::move(v));
|
||||
}
|
||||
|
||||
value& value::object(const key_t& key) {
|
||||
reference ref = this->operator[](key);
|
||||
ref = dv::object();
|
||||
return ref;
|
||||
}
|
||||
|
||||
value& value::list(const key_t& key) {
|
||||
reference ref = this->operator[](key);
|
||||
ref = dv::list();
|
||||
return ref;
|
||||
}
|
||||
|
||||
value& value::object() {
|
||||
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() {
|
||||
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() {
|
||||
check_type(type, value_type::list);
|
||||
return val.list->begin();
|
||||
}
|
||||
|
||||
list_t::iterator value::end() {
|
||||
check_type(type, value_type::list);
|
||||
return val.list->end();
|
||||
}
|
||||
|
||||
list_t::const_iterator value::begin() const {
|
||||
check_type(type, value_type::list);
|
||||
const auto& constlist = *val.list;
|
||||
return constlist.begin();
|
||||
}
|
||||
|
||||
list_t::const_iterator value::end() const {
|
||||
check_type(type, value_type::list);
|
||||
const auto& constlist = *val.list;
|
||||
return constlist.end();
|
||||
}
|
||||
|
||||
const std::string& value::asString() const {
|
||||
check_type(type, value_type::string);
|
||||
return *val.string;
|
||||
}
|
||||
|
||||
integer_t value::asInteger() const {
|
||||
if (type == value_type::integer) {
|
||||
return val.integer;
|
||||
} else if (type == value_type::number) {
|
||||
return static_cast<integer_t>(val.number);
|
||||
}
|
||||
throw_type_error(type, value_type::integer);
|
||||
return 0; // unreachable
|
||||
}
|
||||
|
||||
number_t value::asNumber() const {
|
||||
if (type == value_type::number) {
|
||||
return val.number;
|
||||
} else if (type == value_type::integer) {
|
||||
return static_cast<number_t>(val.integer);
|
||||
}
|
||||
throw_type_error(type, value_type::integer);
|
||||
return 0; // unreachable
|
||||
}
|
||||
|
||||
boolean_t value::asBoolean() const {
|
||||
check_type(type, value_type::boolean);
|
||||
return val.boolean;
|
||||
}
|
||||
|
||||
objects::Bytes& value::asBytes() {
|
||||
check_type(type, value_type::bytes);
|
||||
return *val.bytes;
|
||||
}
|
||||
|
||||
const objects::Bytes& value::asBytes() const {
|
||||
check_type(type, value_type::bytes);
|
||||
return *val.bytes;
|
||||
}
|
||||
|
||||
const objects::Object& value::asObject() const {
|
||||
check_type(type, value_type::object);
|
||||
return *val.object;
|
||||
}
|
||||
|
||||
size_t value::size() const noexcept {
|
||||
switch (type) {
|
||||
case value_type::list:
|
||||
return val.list->size();
|
||||
case value_type::object:
|
||||
return val.object->size();
|
||||
case value_type::string:
|
||||
return val.string->size();
|
||||
default:
|
||||
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);
|
||||
}
|
||||
+597
@@ -0,0 +1,597 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace util {
|
||||
template<class T> class Buffer;
|
||||
}
|
||||
|
||||
namespace dv {
|
||||
using integer_t = int64_t;
|
||||
using number_t = double;
|
||||
using boolean_t = bool;
|
||||
using byte_t = unsigned char;
|
||||
using key_t = std::string;
|
||||
|
||||
enum class value_type : uint8_t {
|
||||
none = 0,
|
||||
number,
|
||||
boolean,
|
||||
integer,
|
||||
object,
|
||||
list,
|
||||
bytes,
|
||||
string
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
using list_t = std::vector<value>;
|
||||
using map_t = std::unordered_map<key_t, value>;
|
||||
using pair = std::pair<const key_t, value>;
|
||||
|
||||
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 optionalvalue {
|
||||
value* ptr;
|
||||
|
||||
optionalvalue(value* ptr) noexcept : ptr(ptr) {}
|
||||
|
||||
inline operator bool() const noexcept {
|
||||
return ptr != nullptr;
|
||||
}
|
||||
|
||||
inline value& operator*() noexcept {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline const value& operator*() const noexcept {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
bool get(std::string& dst) const;
|
||||
bool get(bool& dst) const;
|
||||
bool get(char& dst) const;
|
||||
bool get(short& dst) const;
|
||||
bool get(int& dst) const;
|
||||
bool get(long& dst) const;
|
||||
bool get(long long& dst) const;
|
||||
bool get(unsigned char& dst) const;
|
||||
bool get(unsigned short& dst) const;
|
||||
bool get(unsigned int& dst) const;
|
||||
bool get(unsigned long& dst) const;
|
||||
bool get(unsigned long long& 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 {
|
||||
integer_t integer;
|
||||
number_t number;
|
||||
boolean_t boolean;
|
||||
std::unique_ptr<std::string> string;
|
||||
std::shared_ptr<objects::Object> object;
|
||||
std::shared_ptr<objects::List> list;
|
||||
std::shared_ptr<objects::Bytes> bytes;
|
||||
value_u() noexcept {}
|
||||
~value_u() noexcept {}
|
||||
} val;
|
||||
|
||||
inline value& setBoolean(boolean_t v) noexcept {
|
||||
this->~value();
|
||||
type = value_type::boolean;
|
||||
val.boolean = v;
|
||||
return *this;
|
||||
}
|
||||
inline value& setInteger(integer_t v) noexcept {
|
||||
this->~value();
|
||||
type = value_type::integer;
|
||||
val.integer = v;
|
||||
return *this;
|
||||
}
|
||||
inline value& setNumber(number_t v) noexcept {
|
||||
this->~value();
|
||||
type = value_type::number;
|
||||
val.number = v;
|
||||
return *this;
|
||||
}
|
||||
inline value& setNone() noexcept {
|
||||
this->~value();
|
||||
type = value_type::none;
|
||||
return *this;
|
||||
}
|
||||
inline value& setString(std::string v) noexcept {
|
||||
this->~value();
|
||||
new(&val.string)std::unique_ptr<std::string>(
|
||||
std::make_unique<std::string>(std::move(v)));
|
||||
type = value_type::string;
|
||||
return *this;
|
||||
}
|
||||
inline value& setString(std::unique_ptr<std::string> v) noexcept {
|
||||
this->~value();
|
||||
new(&val.string)std::unique_ptr<std::string>(std::move(v));
|
||||
type = value_type::string;
|
||||
return *this;
|
||||
}
|
||||
inline value& setList(std::shared_ptr<objects::List> ptr) noexcept {
|
||||
this->~value();
|
||||
new(&val.list)std::shared_ptr<objects::List>(std::move(ptr));
|
||||
type = value_type::list;
|
||||
return *this;
|
||||
}
|
||||
inline value& setObject(std::shared_ptr<objects::Object> ptr) noexcept {
|
||||
this->~value();
|
||||
new(&val.object)std::shared_ptr<objects::Object>(std::move(ptr));
|
||||
type = value_type::object;
|
||||
return *this;
|
||||
}
|
||||
inline value& setBytes(std::shared_ptr<objects::Bytes> ptr) noexcept {
|
||||
this->~value();
|
||||
new(&val.bytes)std::shared_ptr<objects::Bytes>(std::move(ptr));
|
||||
type = value_type::bytes;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
value() noexcept : type(value_type::none) {}
|
||||
|
||||
/// @brief Constructor for fundamental types
|
||||
template<typename T>
|
||||
value(T v, std::enable_if_t<std::is_fundamental<T>::value, int> = 0) noexcept {
|
||||
this->operator=(v);
|
||||
}
|
||||
value(std::string v) noexcept {
|
||||
this->operator=(std::move(v));
|
||||
}
|
||||
value(std::shared_ptr<objects::Object> v) noexcept {
|
||||
this->operator=(std::move(v));
|
||||
}
|
||||
value(std::shared_ptr<objects::List> v) noexcept {
|
||||
this->operator=(std::move(v));
|
||||
}
|
||||
value(std::shared_ptr<objects::Bytes> v) noexcept {
|
||||
this->operator=(std::move(v));
|
||||
}
|
||||
|
||||
value(const value& v) noexcept : type(value_type::none) {
|
||||
this->operator=(v);
|
||||
}
|
||||
|
||||
value(value&& v) noexcept {
|
||||
this->operator=(std::move(v));
|
||||
}
|
||||
|
||||
~value() noexcept {
|
||||
switch (type) {
|
||||
case value_type::object:
|
||||
val.object.reset();
|
||||
break;
|
||||
case value_type::list:
|
||||
val.list.reset();
|
||||
break;
|
||||
case value_type::bytes:
|
||||
val.bytes.reset();
|
||||
break;
|
||||
case value_type::string:
|
||||
val.string.reset();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline value& operator=(std::nullptr_t) {
|
||||
return setNone();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::enable_if_t<std::is_integral<T>() && !std::is_same<T, bool>(), value&>
|
||||
operator=(T v) {
|
||||
return setInteger(v);
|
||||
}
|
||||
|
||||
inline value& operator=(float v) {
|
||||
return setNumber(v);
|
||||
}
|
||||
inline value& operator=(double v) {
|
||||
return setNumber(v);
|
||||
}
|
||||
inline value& operator=(bool v) {
|
||||
return setBoolean(v);
|
||||
}
|
||||
inline value& operator=(std::string_view v) {
|
||||
return setString(std::string(v));
|
||||
}
|
||||
inline value& operator=(std::string v) {
|
||||
return setString(std::move(v));
|
||||
}
|
||||
inline value& operator=(const char* v) {
|
||||
return setString(v);
|
||||
}
|
||||
inline value& operator=(std::shared_ptr<objects::List> ptr) {
|
||||
return setList(std::move(ptr));
|
||||
}
|
||||
inline value& operator=(std::shared_ptr<objects::Object> ptr) {
|
||||
return setObject(std::move(ptr));
|
||||
}
|
||||
inline value& operator=(std::shared_ptr<objects::Bytes> ptr) {
|
||||
return setBytes(std::move(ptr));
|
||||
}
|
||||
value& operator=(const objects::Bytes& bytes);
|
||||
|
||||
inline value& operator=(const value& v) {
|
||||
switch (v.type) {
|
||||
case value_type::object:
|
||||
setObject(v.val.object);
|
||||
break;
|
||||
case value_type::list:
|
||||
setList(v.val.list);
|
||||
break;
|
||||
case value_type::bytes:
|
||||
setBytes(v.val.bytes);
|
||||
break;
|
||||
case value_type::string:
|
||||
setString(*v.val.string);
|
||||
break;
|
||||
case value_type::boolean:
|
||||
setBoolean(v.val.boolean);
|
||||
break;
|
||||
case value_type::integer:
|
||||
setInteger(v.val.integer);
|
||||
break;
|
||||
case value_type::number:
|
||||
setNumber(v.val.number);
|
||||
break;
|
||||
case value_type::none:
|
||||
setNone();
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline value& operator=(value&& v) noexcept {
|
||||
if (type < value_type::object) {
|
||||
type = v.type;
|
||||
switch (v.type) {
|
||||
case value_type::none:
|
||||
break;
|
||||
case value_type::integer:
|
||||
val.integer = v.val.integer;
|
||||
break;
|
||||
case value_type::number:
|
||||
val.number = v.val.number;
|
||||
break;
|
||||
case value_type::boolean:
|
||||
val.boolean = v.val.boolean;
|
||||
break;
|
||||
case value_type::string:
|
||||
new(&val.string)std::unique_ptr<std::string>(
|
||||
std::move(v.val.string));
|
||||
break;
|
||||
case value_type::object:
|
||||
new(&val.object)std::shared_ptr<objects::Object>(
|
||||
std::move(v.val.object));
|
||||
break;
|
||||
case value_type::list:
|
||||
new(&val.list)std::shared_ptr<objects::List>(
|
||||
std::move(v.val.list));
|
||||
break;
|
||||
case value_type::bytes:
|
||||
new(&val.list)std::shared_ptr<objects::Bytes>(
|
||||
std::move(v.val.bytes));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (v.type) {
|
||||
case value_type::object:
|
||||
setObject(std::move(v.val.object));
|
||||
break;
|
||||
case value_type::list:
|
||||
setList(std::move(v.val.list));
|
||||
break;
|
||||
case value_type::bytes:
|
||||
setBytes(std::move(v.val.bytes));
|
||||
break;
|
||||
case value_type::string:
|
||||
setString(std::move(v.val.string));
|
||||
break;
|
||||
case value_type::boolean:
|
||||
setBoolean(v.val.boolean);
|
||||
break;
|
||||
case value_type::integer:
|
||||
setInteger(v.val.integer);
|
||||
break;
|
||||
case value_type::number:
|
||||
setNumber(v.val.number);
|
||||
break;
|
||||
case value_type::none:
|
||||
setNone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void add(value v);
|
||||
|
||||
template<class T>
|
||||
inline void add(T v) {
|
||||
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;
|
||||
|
||||
value& operator[](size_t index);
|
||||
|
||||
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);
|
||||
|
||||
value& object();
|
||||
|
||||
value& list();
|
||||
|
||||
list_t::iterator begin();
|
||||
list_t::iterator end();
|
||||
|
||||
list_t::const_iterator begin() const;
|
||||
list_t::const_iterator end() const;
|
||||
|
||||
const std::string& asString() const;
|
||||
|
||||
integer_t asInteger() const;
|
||||
|
||||
number_t asNumber() const;
|
||||
|
||||
boolean_t asBoolean() const;
|
||||
|
||||
objects::Bytes& asBytes();
|
||||
|
||||
const objects::Bytes& asBytes() const;
|
||||
|
||||
const objects::Object& asObject() const;
|
||||
|
||||
inline value_type getType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
std::string asString(std::string def) const {
|
||||
if (type != value_type::string) {
|
||||
return def;
|
||||
}
|
||||
return *val.string;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
optionalvalue 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 optionalvalue(nullptr);
|
||||
}
|
||||
return optionalvalue(&found->second);
|
||||
}
|
||||
|
||||
optionalvalue at(size_t index) {
|
||||
check_type(type, value_type::list);
|
||||
return optionalvalue(&val.list->at(index));
|
||||
}
|
||||
|
||||
const optionalvalue at(size_t index) const {
|
||||
check_type(type, value_type::list);
|
||||
return optionalvalue(&val.list->at(index));
|
||||
}
|
||||
|
||||
bool has(const key_t& k) const;
|
||||
|
||||
size_t size() const noexcept;
|
||||
|
||||
size_t length() const noexcept {
|
||||
return size();
|
||||
}
|
||||
inline bool empty() const noexcept {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
inline bool isString() const noexcept {
|
||||
return type == value_type::string;
|
||||
}
|
||||
inline bool isObject() const noexcept {
|
||||
return type == value_type::object;
|
||||
}
|
||||
inline bool isList() const noexcept {
|
||||
return type == value_type::list;
|
||||
}
|
||||
inline bool isInteger() const noexcept {
|
||||
return type == value_type::integer;
|
||||
}
|
||||
inline bool isNumber() const noexcept {
|
||||
return type == value_type::number;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool is_numeric(const value& val) {
|
||||
return val.isInteger() && val.isNumber();
|
||||
}
|
||||
}
|
||||
|
||||
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>();
|
||||
}
|
||||
|
||||
inline value list() {
|
||||
return std::make_shared<objects::List>();
|
||||
}
|
||||
|
||||
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 optionalvalue::get(std::string& dst) const {
|
||||
if (ptr) {
|
||||
dst = ptr->asString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool optionalvalue::get(bool& dst) const {
|
||||
if (ptr) {
|
||||
dst = ptr->asBoolean();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool optionalvalue::get(char& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::get(short& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::get(int& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::get(long& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::get(long long& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::get(unsigned char& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::get(unsigned short& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::get(unsigned int& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::get(unsigned long& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::get(unsigned long long& dst) const {
|
||||
return get_to_int(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::get(float& dst) const {
|
||||
return get_to_num(ptr, dst);
|
||||
}
|
||||
inline bool optionalvalue::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