initial commit
This commit is contained in:
144
include/model_value.hpp
Normal file
144
include/model_value.hpp
Normal file
@@ -0,0 +1,144 @@
|
||||
#pragma once
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
class DaliValue {
|
||||
public:
|
||||
using Array = std::vector<DaliValue>;
|
||||
using Object = std::map<std::string, DaliValue>;
|
||||
|
||||
using Variant = std::variant<std::monostate, bool, int64_t, double, std::string, Array, Object>;
|
||||
|
||||
DaliValue() = default;
|
||||
DaliValue(std::nullptr_t) : value_(std::monostate{}) {}
|
||||
DaliValue(bool v) : value_(v) {}
|
||||
DaliValue(int v) : value_(static_cast<int64_t>(v)) {}
|
||||
DaliValue(int64_t v) : value_(v) {}
|
||||
DaliValue(double v) : value_(v) {}
|
||||
DaliValue(const char* v) : value_(std::string(v)) {}
|
||||
DaliValue(std::string v) : value_(std::move(v)) {}
|
||||
DaliValue(Array v) : value_(std::move(v)) {}
|
||||
DaliValue(Object v) : value_(std::move(v)) {}
|
||||
|
||||
bool isNull() const { return std::holds_alternative<std::monostate>(value_); }
|
||||
bool isBool() const { return std::holds_alternative<bool>(value_); }
|
||||
bool isInt() const { return std::holds_alternative<int64_t>(value_); }
|
||||
bool isDouble() const { return std::holds_alternative<double>(value_); }
|
||||
bool isString() const { return std::holds_alternative<std::string>(value_); }
|
||||
bool isArray() const { return std::holds_alternative<Array>(value_); }
|
||||
bool isObject() const { return std::holds_alternative<Object>(value_); }
|
||||
|
||||
std::optional<bool> asBool() const {
|
||||
if (isBool()) return std::get<bool>(value_);
|
||||
if (isInt()) return std::get<int64_t>(value_) != 0;
|
||||
if (isString()) {
|
||||
const auto& s = std::get<std::string>(value_);
|
||||
if (s == "true" || s == "TRUE" || s == "1") return true;
|
||||
if (s == "false" || s == "FALSE" || s == "0") return false;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<int> asInt() const {
|
||||
if (isInt()) return static_cast<int>(std::get<int64_t>(value_));
|
||||
if (isDouble()) return static_cast<int>(std::get<double>(value_));
|
||||
if (isString()) {
|
||||
const auto& s = std::get<std::string>(value_);
|
||||
if (s.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
char* end = nullptr;
|
||||
errno = 0;
|
||||
const long parsed = std::strtol(s.c_str(), &end, 10);
|
||||
if (errno != 0 || end == s.c_str() || *end != '\0') {
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<int>(parsed);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<double> asDouble() const {
|
||||
if (isDouble()) return std::get<double>(value_);
|
||||
if (isInt()) return static_cast<double>(std::get<int64_t>(value_));
|
||||
if (isString()) {
|
||||
const auto& s = std::get<std::string>(value_);
|
||||
if (s.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
char* end = nullptr;
|
||||
errno = 0;
|
||||
const double parsed = std::strtod(s.c_str(), &end);
|
||||
if (errno != 0 || end == s.c_str() || *end != '\0') {
|
||||
return std::nullopt;
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> asString() const {
|
||||
if (isString()) return std::get<std::string>(value_);
|
||||
if (isBool()) return std::get<bool>(value_) ? "true" : "false";
|
||||
if (isInt()) return std::to_string(std::get<int64_t>(value_));
|
||||
if (isDouble()) return std::to_string(std::get<double>(value_));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const Array* asArray() const {
|
||||
if (!isArray()) return nullptr;
|
||||
return &std::get<Array>(value_);
|
||||
}
|
||||
|
||||
const Object* asObject() const {
|
||||
if (!isObject()) return nullptr;
|
||||
return &std::get<Object>(value_);
|
||||
}
|
||||
|
||||
Array* asArray() {
|
||||
if (!isArray()) return nullptr;
|
||||
return &std::get<Array>(value_);
|
||||
}
|
||||
|
||||
Object* asObject() {
|
||||
if (!isObject()) return nullptr;
|
||||
return &std::get<Object>(value_);
|
||||
}
|
||||
|
||||
const Variant& variant() const { return value_; }
|
||||
Variant& variant() { return value_; }
|
||||
|
||||
private:
|
||||
Variant value_;
|
||||
};
|
||||
|
||||
inline const DaliValue* getObjectValue(const DaliValue::Object& obj, const std::string& key) {
|
||||
const auto it = obj.find(key);
|
||||
if (it == obj.end()) return nullptr;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
inline std::optional<int> getObjectInt(const DaliValue::Object& obj, const std::string& key) {
|
||||
const auto* v = getObjectValue(obj, key);
|
||||
if (!v) return std::nullopt;
|
||||
return v->asInt();
|
||||
}
|
||||
|
||||
inline std::optional<bool> getObjectBool(const DaliValue::Object& obj, const std::string& key) {
|
||||
const auto* v = getObjectValue(obj, key);
|
||||
if (!v) return std::nullopt;
|
||||
return v->asBool();
|
||||
}
|
||||
|
||||
inline std::optional<std::string> getObjectString(const DaliValue::Object& obj,
|
||||
const std::string& key) {
|
||||
const auto* v = getObjectValue(obj, key);
|
||||
if (!v) return std::nullopt;
|
||||
return v->asString();
|
||||
}
|
||||
Reference in New Issue
Block a user