17 enum class Type :
int {
27 using Array = ::std::vector<::cereal::DynamicValue>;
31 using Integer = int64;
35 using Number = double;
37 using String = ::std::string;
39 using Object = ::std::
40 unordered_map<String, ::cereal::DynamicValue, ::cereal::util::internal::StringViewHash, ::std::equal_to<void>>;
42 using Member = ::std::pair<::std::string, ::cereal::DynamicValue>;
44 using Variant = ::std::variant<::cereal::NullType, bool, int64, double, ::std::string, Array, Object>;
53 DynamicValue() =
default;
55 DynamicValue(::std::nullptr_t) noexcept : mValue(Null{}) {}
56 DynamicValue(Null) noexcept : mValue(Null{}) {}
57 DynamicValue(Bool value) noexcept : mValue(value) {}
59 template <::std::
integral T>
60 requires(!::std::same_as<::std::remove_cvref_t<T>, Bool>)
61 DynamicValue(T value) noexcept : mValue(
static_cast<Integer
>(value)) {}
63 template <::std::
floating_po
int T>
64 DynamicValue(T value) noexcept : mValue(
static_cast<Number
>(value)) {}
66 DynamicValue(
char const* value) : mValue(String{value ==
nullptr ?
"" : value}) {}
67 DynamicValue(::std::string_view value) : mValue(String{value}) {}
68 DynamicValue(String value) : mValue(::std::move(value)) {}
69 DynamicValue(Array value) : mValue(::std::move(value)) {}
70 DynamicValue(Object value) : mValue(::std::move(value)) {}
72 DynamicValue(DynamicValue
const&) =
default;
73 DynamicValue(DynamicValue&&) =
default;
74 DynamicValue& operator=(DynamicValue
const&) =
default;
75 DynamicValue& operator=(DynamicValue&&) =
default;
78 requires(!::std::same_as<::std::remove_cvref_t<T>, DynamicValue> && ::std::constructible_from<DynamicValue, T>)
79 DynamicValue&
operator=(T&& value) {
80 return *
this = DynamicValue(::std::forward<T>(value));
83 [[nodiscard]]
static DynamicValue array() {
return Array{}; }
85 [[nodiscard]]
static DynamicValue array(::std::initializer_list<DynamicValue> values) {
return Array{values}; }
87 [[nodiscard]]
static DynamicValue object() {
return Object{}; }
89 [[nodiscard]]
static DynamicValue object(::std::initializer_list<Member> members) {
91 result.reserve(members.size());
92 for (
auto const& [name, value] : members) {
93 result.insert_or_assign(name, value);
98 [[nodiscard]] Variant
const& value()
const&
noexcept {
return mValue; }
99 [[nodiscard]] Variant& value() &
noexcept {
return mValue; }
100 [[nodiscard]] Variant&& value() &&
noexcept { return ::std::move(mValue); }
103 [[nodiscard]]
bool is()
const noexcept {
104 return ::std::holds_alternative<T>(value());
108 [[nodiscard]] T
const& get()
const& {
109 return ::std::get<T>(value());
113 [[nodiscard]] T& get() & {
114 return ::std::get<T>(value());
118 [[nodiscard]] T&& get() && {
119 return ::std::get<T>(::std::move(*this).value());
123 [[nodiscard]] T
const* getIf()
const noexcept {
124 return ::std::get_if<T>(&value());
128 [[nodiscard]] T* getIf()
noexcept {
129 return ::std::get_if<T>(&value());
132 [[nodiscard]]
bool isNull()
const noexcept {
return is<Null>(); }
133 [[nodiscard]]
bool isBool()
const noexcept {
return is<Bool>(); }
134 [[nodiscard]]
bool isInteger()
const noexcept {
return is<Integer>(); }
135 [[nodiscard]]
bool isNumber()
const noexcept {
return is<Number>(); }
136 [[nodiscard]]
bool isString()
const noexcept {
return is<String>(); }
137 [[nodiscard]]
bool isArray()
const noexcept {
return is<Array>(); }
138 [[nodiscard]]
bool isObject()
const noexcept {
return is<Object>(); }
139 [[nodiscard]]
bool isNumeric()
const noexcept {
return isInteger() || isNumber(); }
140 [[nodiscard]]
bool isPrimitive()
const noexcept {
return !isArray() && !isObject(); }
142 [[nodiscard]] Type type()
const noexcept {
return static_cast<Type
>(value().index()); }
144 [[nodiscard]] Null
const& asNull()
const {
return get<Null>(); }
145 [[nodiscard]] Null& asNull() {
return get<Null>(); }
146 [[nodiscard]] Bool
const& asBool()
const {
return get<Bool>(); }
147 [[nodiscard]] Bool& asBool() {
return get<Bool>(); }
148 [[nodiscard]] Integer
const& asInteger()
const {
return get<Integer>(); }
149 [[nodiscard]] Integer& asInteger() {
return get<Integer>(); }
150 [[nodiscard]] Number
const& asNumber()
const {
return get<Number>(); }
151 [[nodiscard]] Number& asNumber() {
return get<Number>(); }
152 [[nodiscard]] String
const& asString()
const {
return get<String>(); }
153 [[nodiscard]] String& asString() {
return get<String>(); }
154 [[nodiscard]] Array
const& asArray()
const {
return get<Array>(); }
155 [[nodiscard]] Array& asArray() {
return get<Array>(); }
156 [[nodiscard]] Object
const& asObject()
const {
return get<Object>(); }
157 [[nodiscard]] Object& asObject() {
return get<Object>(); }
159 [[nodiscard]]
bool contains(::std::string_view member)
const {
163 return get<Object>().contains(member);
166 [[nodiscard]] ::std::size_t size()
const noexcept {
167 if (
auto const* values = ::std::get_if<Array>(&value())) {
168 return values->size();
170 if (
auto const* members = ::std::get_if<Object>(&value())) {
171 return members->size();
173 return isNull() ? 0 : 1;
176 [[nodiscard]]
bool empty()
const noexcept {
return size() == 0; }
178 [[nodiscard]]
bool hasMember(::std::string_view member)
const {
return contains(member); }
180 DynamicValue& operator[](::std::string_view member) {
184 auto& values = get<Object>();
185 if (
auto iter = values.find(member); iter != values.end()) {
188 return values.try_emplace(String{member}).first->second;
191 DynamicValue
const& operator[](::std::string_view member)
const {
192 auto const& values = get<Object>();
193 auto iter = values.find(member);
194 if (iter == values.end()) {
195 throw ::std::out_of_range(
"DynamicValue object key not found");
200 DynamicValue& operator[](::std::size_t index) {
return get<Array>().at(index); }
202 DynamicValue
const& operator[](::std::size_t index)
const {
return get<Array>().at(index); }
204 DynamicValue& at(::std::string_view member) {
return const_cast<DynamicValue&
>(::std::as_const(*this).at(member)); }
206 DynamicValue
const& at(::std::string_view member)
const {
return operator[](member); }
208 DynamicValue& at(::std::size_t index) {
return get<Array>().at(index); }
210 DynamicValue
const& at(::std::size_t index)
const {
return get<Array>().at(index); }
213 requires ::std::constructible_from<DynamicValue, T>
214 DynamicValue& set(::std::string_view member, T&& field) {
215 (*this)[member] = DynamicValue(::std::forward<T>(field));
219 DynamicValue& pushBack(DynamicValue element) {
223 get<Array>().emplace_back(::std::move(element));
227 DynamicValue& push_back(DynamicValue element) {
return pushBack(::std::move(element)); }
230 requires ::std::constructible_from<DynamicValue, T>
231 DynamicValue& emplaceBack(T&& element) {
232 return pushBack(DynamicValue(::std::forward<T>(element)));
236 requires ::std::constructible_from<DynamicValue, T>
237 DynamicValue& emplace_back(T&& element) {
238 return emplaceBack(::std::forward<T>(element));
241 bool erase(::std::string_view member) {
245 auto& values = get<Object>();
246 auto iter = values.find(member);
247 if (iter == values.end()) {
254 void erase(::std::size_t index) {
255 auto& values = get<Array>();
256 if (index >= values.size()) {
257 throw ::std::out_of_range(
"DynamicValue array index out of range");
259 values.erase(values.begin() +
static_cast<::std::ptrdiff_t
>(index));
263 if (
auto* values = getIf<Array>()) {
265 }
else if (
auto* members = getIf<Object>()) {
267 }
else if (
auto* text = getIf<String>()) {
274 void reserve(::std::size_t capacity) {
275 if (
auto* values = getIf<Array>()) {
276 values->reserve(capacity);
278 get<Object>().reserve(capacity);
282 MCAPI uint64 hash()
const;