Blender V4.3
serialize.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_fileops.hh"
6#include "BLI_serialize.hh"
7
8#include "json.hpp"
9
10namespace blender::io::serialize {
11
13{
14 if (type_ != eValueType::String) {
15 return nullptr;
16 }
17 return static_cast<const StringValue *>(this);
18}
19
21{
22 if (type_ != eValueType::Int) {
23 return nullptr;
24 }
25 return static_cast<const IntValue *>(this);
26}
27
29{
30 if (type_ != eValueType::Double) {
31 return nullptr;
32 }
33 return static_cast<const DoubleValue *>(this);
34}
35
37{
38 if (type_ != eValueType::Boolean) {
39 return nullptr;
40 }
41 return static_cast<const BooleanValue *>(this);
42}
43
45{
46 if (type_ != eValueType::Enum) {
47 return nullptr;
48 }
49 return static_cast<const EnumValue *>(this);
50}
51
53{
54 if (type_ != eValueType::Array) {
55 return nullptr;
56 }
57 return static_cast<const ArrayValue *>(this);
58}
59
61{
62 if (type_ != eValueType::Dictionary) {
63 return nullptr;
64 }
65 return static_cast<const DictionaryValue *>(this);
66}
67
68static void convert_to_json(nlohmann::ordered_json &j, const Value &value);
69static void convert_to_json(nlohmann::ordered_json &j, const ArrayValue &value)
70{
71 /* Create a json array to store the elements. If this isn't done and items is empty it would
72 * return use a null value, in stead of an empty array. */
73 j = "[]"_json;
74 for (const std::shared_ptr<Value> &item_value : value.elements()) {
75 nlohmann::ordered_json json_item;
76 convert_to_json(json_item, *item_value);
77 j.push_back(json_item);
78 }
79}
80
81static void convert_to_json(nlohmann::ordered_json &j, const DictionaryValue &value)
82{
83 /* Create a json object to store the attributes. If this isn't done and attributes is empty it
84 * would return use a null value, in stead of an empty object. */
85 j = "{}"_json;
86 for (const DictionaryValue::Item &attribute : value.elements()) {
87 nlohmann::ordered_json json_item;
88 convert_to_json(json_item, *attribute.second);
89 j[attribute.first] = json_item;
90 }
91}
92
93static void convert_to_json(nlohmann::ordered_json &j, const Value &value)
94{
95 switch (value.type()) {
96 case eValueType::String: {
97 j = value.as_string_value()->value();
98 break;
99 }
100
101 case eValueType::Int: {
102 j = value.as_int_value()->value();
103 break;
104 }
105
106 case eValueType::Array: {
107 const ArrayValue &array = *value.as_array_value();
109 break;
110 }
111
113 const DictionaryValue &object = *value.as_dictionary_value();
114 convert_to_json(j, object);
115 break;
116 }
117
118 case eValueType::Null: {
119 j = nullptr;
120 break;
121 }
122
123 case eValueType::Boolean: {
124 j = value.as_boolean_value()->value();
125 break;
126 }
127
128 case eValueType::Double: {
129 j = value.as_double_value()->value();
130 break;
131 }
132
133 case eValueType::Enum: {
134 j = value.as_enum_value()->value();
135 break;
136 }
137 }
138}
139
140static std::unique_ptr<Value> convert_from_json(const nlohmann::ordered_json &j);
141static std::unique_ptr<ArrayValue> convert_from_json_to_array(const nlohmann::ordered_json &j)
142{
143 std::unique_ptr<ArrayValue> array = std::make_unique<ArrayValue>();
144 for (auto element : j.items()) {
146 }
147 return array;
148}
149
150static std::unique_ptr<DictionaryValue> convert_from_json_to_object(
151 const nlohmann::ordered_json &j)
152{
153 std::unique_ptr<DictionaryValue> object = std::make_unique<DictionaryValue>();
154 for (auto element : j.items()) {
155 object->append(element.key(), convert_from_json(element.value()));
156 }
157 return object;
158}
159
160static std::unique_ptr<Value> convert_from_json(const nlohmann::ordered_json &j)
161{
162 switch (j.type()) {
163 case nlohmann::json::value_t::array: {
165 }
166
167 case nlohmann::json::value_t::object: {
169 }
170
171 case nlohmann::json::value_t::string: {
172 std::string value = j;
173 return std::make_unique<StringValue>(value);
174 }
175
176 case nlohmann::json::value_t::null: {
177 return std::make_unique<NullValue>();
178 }
179
180 case nlohmann::json::value_t::boolean: {
181 return std::make_unique<BooleanValue>(j);
182 }
183 case nlohmann::json::value_t::number_integer:
184 case nlohmann::json::value_t::number_unsigned: {
185 return std::make_unique<IntValue>(j);
186 }
187
188 case nlohmann::json::value_t::number_float: {
189 return std::make_unique<DoubleValue>(j);
190 }
191
192 case nlohmann::json::value_t::binary:
193 case nlohmann::json::value_t::discarded:
194 /*
195 * Binary data isn't supported.
196 * Discarded is an internal type of nlohmann.
197 *
198 * Assert in case we need to parse them.
199 */
201 return std::make_unique<NullValue>();
202 }
203
205 return std::make_unique<NullValue>();
206}
207
208void ArrayValue::append(std::shared_ptr<Value> value)
209{
210 values_.append(std::move(value));
211}
212
213void ArrayValue::append_bool(const bool value)
214{
215 this->append(std::make_shared<BooleanValue>(value));
216}
217
218void ArrayValue::append_int(const int value)
219{
220 this->append(std::make_shared<IntValue>(value));
221}
222
223void ArrayValue::append_double(const double value)
224{
225 this->append(std::make_shared<DoubleValue>(value));
226}
227
228void ArrayValue::append_str(std::string value)
229{
230 this->append(std::make_shared<StringValue>(std::move(value)));
231}
232
234{
235 this->append(std::make_shared<NullValue>());
236}
237
238std::shared_ptr<DictionaryValue> ArrayValue::append_dict()
239{
240 auto value = std::make_shared<DictionaryValue>();
241 this->append(value);
242 return value;
243}
244
245std::shared_ptr<ArrayValue> ArrayValue::append_array()
246{
247 auto value = std::make_shared<ArrayValue>();
248 this->append(value);
249 return value;
250}
251
253{
255 for (const Item &item : values_) {
256 result.add_as(item.first, item.second);
257 }
258 return result;
259}
260
261const std::shared_ptr<Value> *DictionaryValue::lookup(const StringRef key) const
262{
263 for (const auto &item : values_) {
264 if (item.first == key) {
265 return &item.second;
266 }
267 }
268 return nullptr;
269}
270
271std::optional<StringRefNull> DictionaryValue::lookup_str(const StringRef key) const
272{
273 if (const std::shared_ptr<Value> *value = this->lookup(key)) {
274 if (const StringValue *str_value = (*value)->as_string_value()) {
275 return StringRefNull(str_value->value());
276 }
277 }
278 return std::nullopt;
279}
280
281std::optional<int64_t> DictionaryValue::lookup_int(const StringRef key) const
282{
283 if (const std::shared_ptr<Value> *value = this->lookup(key)) {
284 if (const IntValue *int_value = (*value)->as_int_value()) {
285 return int_value->value();
286 }
287 }
288 return std::nullopt;
289}
290
291std::optional<double> DictionaryValue::lookup_double(const StringRef key) const
292{
293 if (const std::shared_ptr<Value> *value = this->lookup(key)) {
294 if (const DoubleValue *double_value = (*value)->as_double_value()) {
295 return double_value->value();
296 }
297 }
298 return std::nullopt;
299}
300
302{
303 if (const std::shared_ptr<Value> *value = this->lookup(key)) {
304 return (*value)->as_dictionary_value();
305 }
306 return nullptr;
307}
308
310{
311 if (const std::shared_ptr<Value> *value = this->lookup(key)) {
312 return (*value)->as_array_value();
313 }
314 return nullptr;
315}
316
317void DictionaryValue::append(std::string key, std::shared_ptr<Value> value)
318{
319 values_.append({std::move(key), std::move(value)});
320}
321
322void DictionaryValue::append_int(std::string key, const int64_t value)
323{
324 this->append(std::move(key), std::make_shared<IntValue>(value));
325}
326
327void DictionaryValue::append_double(std::string key, const double value)
328{
329 this->append(std::move(key), std::make_shared<DoubleValue>(value));
330}
331
332void DictionaryValue::append_str(std::string key, std::string value)
333{
334 this->append(std::move(key), std::make_shared<StringValue>(std::move(value)));
335}
336
337std::shared_ptr<DictionaryValue> DictionaryValue::append_dict(std::string key)
338{
339 auto value = std::make_shared<DictionaryValue>();
340 this->append(std::move(key), value);
341 return value;
342}
343
344std::shared_ptr<ArrayValue> DictionaryValue::append_array(std::string key)
345{
346 auto value = std::make_shared<ArrayValue>();
347 this->append(std::move(key), value);
348 return value;
349}
350
351void JsonFormatter::serialize(std::ostream &os, const Value &value)
352{
353 nlohmann::ordered_json j;
354 convert_to_json(j, value);
355 if (indentation_len) {
356 os << j.dump(indentation_len);
357 }
358 else {
359 os << j.dump();
360 }
361}
362
363std::unique_ptr<Value> JsonFormatter::deserialize(std::istream &is)
364{
365 nlohmann::ordered_json j;
366 try {
367 is >> j;
368 return convert_from_json(j);
369 }
370 catch (...) {
371 return nullptr;
372 }
373}
374
375void write_json_file(const StringRef path, const Value &value)
376{
377 JsonFormatter formatter;
378 fstream stream(path, std::ios::out);
379 formatter.serialize(stream, value);
380}
381
382std::shared_ptr<Value> read_json_file(const StringRef path)
383{
384 JsonFormatter formatter;
385 fstream stream(path, std::ios::in);
386 return formatter.deserialize(stream);
387}
388
389} // namespace blender::io::serialize
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
File and directory operations.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
ATTR_WARN_UNUSED_RESULT const void * element
void append(const array< T > &from)
void append(std::shared_ptr< Value > value)
Definition serialize.cc:208
Span< std::shared_ptr< Value > > elements() const
std::shared_ptr< ArrayValue > append_array()
Definition serialize.cc:245
void append_str(std::string value)
Definition serialize.cc:228
std::shared_ptr< DictionaryValue > append_dict()
Definition serialize.cc:238
void append(std::string key, std::shared_ptr< Value > value)
Definition serialize.cc:317
const std::shared_ptr< Value > * lookup(const StringRef key) const
Definition serialize.cc:261
void append_str(std::string key, std::string value)
Definition serialize.cc:332
std::shared_ptr< DictionaryValue > append_dict(std::string key)
Definition serialize.cc:337
std::pair< std::string, std::shared_ptr< Value > > Item
const DictionaryValue * lookup_dict(const StringRef key) const
Definition serialize.cc:301
void append_double(std::string key, double value)
Definition serialize.cc:327
void append_int(std::string key, int64_t value)
Definition serialize.cc:322
const ArrayValue * lookup_array(const StringRef key) const
Definition serialize.cc:309
Map< std::string, std::shared_ptr< Value > > Lookup
std::optional< int64_t > lookup_int(const StringRef key) const
Definition serialize.cc:281
std::shared_ptr< ArrayValue > append_array(std::string key)
Definition serialize.cc:344
std::optional< StringRefNull > lookup_str(const StringRef key) const
Definition serialize.cc:271
std::optional< double > lookup_double(const StringRef key) const
Definition serialize.cc:291
std::unique_ptr< Value > deserialize(std::istream &is) override
Definition serialize.cc:363
void serialize(std::ostream &os, const Value &value) override
Definition serialize.cc:351
const std::string & value() const
const EnumValue * as_enum_value() const
Definition serialize.cc:44
const BooleanValue * as_boolean_value() const
Definition serialize.cc:36
const ArrayValue * as_array_value() const
Definition serialize.cc:52
const StringValue * as_string_value() const
Definition serialize.cc:12
const IntValue * as_int_value() const
Definition serialize.cc:20
const DoubleValue * as_double_value() const
Definition serialize.cc:28
const DictionaryValue * as_dictionary_value() const
Definition serialize.cc:60
static std::unique_ptr< DictionaryValue > convert_from_json_to_object(const nlohmann::ordered_json &j)
Definition serialize.cc:150
void write_json_file(StringRef path, const Value &value)
Definition serialize.cc:375
PrimitiveValue< int64_t, eValueType::Int > IntValue
PrimitiveValue< bool, eValueType::Boolean > BooleanValue
PrimitiveValue< int, eValueType::Enum > EnumValue
static std::unique_ptr< Value > convert_from_json(const nlohmann::ordered_json &j)
Definition serialize.cc:160
PrimitiveValue< double, eValueType::Double > DoubleValue
static void convert_to_json(nlohmann::ordered_json &j, const Value &value)
Definition serialize.cc:93
static std::unique_ptr< ArrayValue > convert_from_json_to_array(const nlohmann::ordered_json &j)
Definition serialize.cc:141
std::shared_ptr< Value > read_json_file(StringRef path)
Definition serialize.cc:382
__int64 int64_t
Definition stdint.h:89