initial commit

This commit is contained in:
Tony
2026-03-26 12:04:08 +08:00
commit 7e8ac7f566
31 changed files with 4304 additions and 0 deletions

144
include/model_value.hpp Normal file
View 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();
}