#pragma once #include #include #include #include #include #include #include class DaliValue { public: using Array = std::vector; using Object = std::map; using Variant = std::variant; DaliValue() = default; DaliValue(std::nullptr_t) : value_(std::monostate{}) {} DaliValue(bool v) : value_(v) {} DaliValue(int v) : value_(static_cast(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(value_); } bool isBool() const { return std::holds_alternative(value_); } bool isInt() const { return std::holds_alternative(value_); } bool isDouble() const { return std::holds_alternative(value_); } bool isString() const { return std::holds_alternative(value_); } bool isArray() const { return std::holds_alternative(value_); } bool isObject() const { return std::holds_alternative(value_); } std::optional asBool() const { if (isBool()) return std::get(value_); if (isInt()) return std::get(value_) != 0; if (isString()) { const auto& s = std::get(value_); if (s == "true" || s == "TRUE" || s == "1") return true; if (s == "false" || s == "FALSE" || s == "0") return false; } return std::nullopt; } std::optional asInt() const { if (isInt()) return static_cast(std::get(value_)); if (isDouble()) return static_cast(std::get(value_)); if (isString()) { const auto& s = std::get(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(parsed); } return std::nullopt; } std::optional asDouble() const { if (isDouble()) return std::get(value_); if (isInt()) return static_cast(std::get(value_)); if (isString()) { const auto& s = std::get(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 asString() const { if (isString()) return std::get(value_); if (isBool()) return std::get(value_) ? "true" : "false"; if (isInt()) return std::to_string(std::get(value_)); if (isDouble()) return std::to_string(std::get(value_)); return std::nullopt; } const Array* asArray() const { if (!isArray()) return nullptr; return &std::get(value_); } const Object* asObject() const { if (!isObject()) return nullptr; return &std::get(value_); } Array* asArray() { if (!isArray()) return nullptr; return &std::get(value_); } Object* asObject() { if (!isObject()) return nullptr; return &std::get(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 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 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 getObjectString(const DaliValue::Object& obj, const std::string& key) { const auto* v = getObjectValue(obj, key); if (!v) return std::nullopt; return v->asString(); }