Merge branch 'main' into heightmaps

This commit is contained in:
MihailRis
2024-09-19 15:16:14 +03:00
74 changed files with 1885 additions and 1782 deletions
+161
View File
@@ -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
View File
@@ -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);
+78
View File
@@ -0,0 +1,78 @@
#pragma once
#include "dv.hpp"
#include <glm/glm.hpp>
namespace dv {
template <int n, typename T>
inline dv::value to_value(glm::vec<n, T> vec) {
auto list = dv::list();
for (size_t i = 0; i < n; i++) {
list.add(vec[i]);
}
return list;
}
template <int n, int m, typename T>
inline dv::value to_value(glm::mat<n, m, T> 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, typename T>
void get_vec(const dv::value& map, const std::string& key, glm::vec<n, T>& vec) {
if (!map.has(key)) {
return;
}
auto& list = map[key];
for (size_t i = 0; i < n; i++) {
if constexpr (std::is_floating_point<T>()) {
vec[i] = list[i].asNumber();
} else {
vec[i] = list[i].asInteger();
}
}
}
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();
}
}
}
}
-345
View File
@@ -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");
}
-190
View File
@@ -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);
-35
View File
@@ -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&)>;
}
-113
View File
@@ -1,113 +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>
inline dynamic::List_sptr to_value(glm::vec<n, int> vec) {
auto list = dynamic::create_list();
for (size_t i = 0; i < n; i++) {
list->put(static_cast<integer_t>(vec[i]));
}
return list;
}
template <int n, int m, typename T>
inline dynamic::List_sptr to_value(glm::mat<n, m, T> 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);
}
}
}
/// TODO: remove raw pointer overloads
template <int n>
void get_vec(
const dynamic::Map* root,
const std::string& name,
glm::vec<n, int>& vec
) {
if (const auto& list = root->list(name)) {
for (size_t i = 0; i < n; i++) {
vec[i] = list->integer(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>
void get_vec(
const dynamic::List_sptr& root, size_t index, glm::vec<n, int>& vec
) {
if (const auto& list = root->list(index)) {
for (size_t i = 0; i < n; i++) {
vec[i] = list->integer(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);
}
}
}
}
}