diff --git a/source/blender/blenlib/BLI_serialize.hh b/source/blender/blenlib/BLI_serialize.hh index 3ebf157107a..afb95907378 100644 --- a/source/blender/blenlib/BLI_serialize.hh +++ b/source/blender/blenlib/BLI_serialize.hh @@ -87,12 +87,7 @@ template class PrimitiveValue; using IntValue = PrimitiveValue; using DoubleValue = PrimitiveValue; using BooleanValue = PrimitiveValue; - -template -class ContainerValue; -/* ArrayValue stores its items as shared pointer as it shares data with a lookup table that can - * be created by calling `create_lookup`. */ -using ArrayValue = ContainerValue>, eValueType::Array>; +class ArrayValue; /** * Class containing a (de)serializable value. @@ -214,7 +209,7 @@ template< eValueType V, /** Type of the data inside the container. */ - typename ContainerItem> + typename ContainerItem = typename Container::value_type> class ContainerValue : public Value { public: using Items = Container; @@ -237,6 +232,18 @@ class ContainerValue : public Value { } }; +class ArrayValue : public ContainerValue>, eValueType::Array> { + public: + void append(std::shared_ptr value); + void append_bool(bool value); + void append_int(int value); + void append_double(double value); + void append_str(std::string value); + void append_null(); + std::shared_ptr append_dict(); + std::shared_ptr append_array(); +}; + /** * Internal storage type for DictionaryValue. * @@ -260,14 +267,21 @@ class DictionaryValue * * The lookup is owned by the caller. */ - const Lookup create_lookup() const - { - Lookup result; - for (const Item &item : elements()) { - result.add_as(item.first, item.second); - } - return result; - } + const Lookup create_lookup() const; + + const std::shared_ptr *lookup(const StringRef key) const; + std::optional lookup_str(const StringRef key) const; + std::optional lookup_int(const StringRef key) const; + std::optional lookup_double(const StringRef key) const; + const DictionaryValue *lookup_dict(const StringRef key) const; + const ArrayValue *lookup_array(const StringRef key) const; + + void append(std::string key, std::shared_ptr value); + void append_int(std::string key, int64_t value); + void append_double(std::string key, double value); + void append_str(std::string key, std::string value); + std::shared_ptr append_dict(std::string key); + std::shared_ptr append_array(std::string key); }; /** @@ -300,4 +314,7 @@ class JsonFormatter : public Formatter { std::unique_ptr deserialize(std::istream &is) override; }; +void write_json_file(StringRef path, const Value &value); +std::shared_ptr read_json_file(StringRef path); + } // namespace blender::io::serialize diff --git a/source/blender/blenlib/intern/serialize.cc b/source/blender/blenlib/intern/serialize.cc index d795e67a54e..3279dc09682 100644 --- a/source/blender/blenlib/intern/serialize.cc +++ b/source/blender/blenlib/intern/serialize.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_fileops.hh" #include "BLI_serialize.hh" #include "json.hpp" @@ -197,6 +198,149 @@ static std::unique_ptr convert_from_json(const nlohmann::ordered_json &j) return std::make_unique(); } +void ArrayValue::append(std::shared_ptr value) +{ + this->elements().append(std::move(value)); +} + +void ArrayValue::append_bool(const bool value) +{ + this->append(std::make_shared(value)); +} + +void ArrayValue::append_int(const int value) +{ + this->append(std::make_shared(value)); +} + +void ArrayValue::append_double(const double value) +{ + this->append(std::make_shared(value)); +} + +void ArrayValue::append_str(std::string value) +{ + this->append(std::make_shared(std::move(value))); +} + +void ArrayValue::append_null() +{ + this->append(std::make_shared()); +} + +std::shared_ptr ArrayValue::append_dict() +{ + auto value = std::make_shared(); + this->append(value); + return value; +} + +std::shared_ptr ArrayValue::append_array() +{ + auto value = std::make_shared(); + this->append(value); + return value; +} + +const DictionaryValue::Lookup DictionaryValue::create_lookup() const +{ + Lookup result; + for (const Item &item : elements()) { + result.add_as(item.first, item.second); + } + return result; +} + +const std::shared_ptr *DictionaryValue::lookup(const StringRef key) const +{ + for (const auto &item : this->elements()) { + if (item.first == key) { + return &item.second; + } + } + return nullptr; +} + +std::optional DictionaryValue::lookup_str(const StringRef key) const +{ + if (const std::shared_ptr *value = this->lookup(key)) { + if (const StringValue *str_value = (*value)->as_string_value()) { + return StringRefNull(str_value->value()); + } + } + return std::nullopt; +} + +std::optional DictionaryValue::lookup_int(const StringRef key) const +{ + if (const std::shared_ptr *value = this->lookup(key)) { + if (const IntValue *int_value = (*value)->as_int_value()) { + return int_value->value(); + } + } + return std::nullopt; +} + +std::optional DictionaryValue::lookup_double(const StringRef key) const +{ + if (const std::shared_ptr *value = this->lookup(key)) { + if (const DoubleValue *double_value = (*value)->as_double_value()) { + return double_value->value(); + } + } + return std::nullopt; +} + +const DictionaryValue *DictionaryValue::lookup_dict(const StringRef key) const +{ + if (const std::shared_ptr *value = this->lookup(key)) { + return (*value)->as_dictionary_value(); + } + return nullptr; +} + +const ArrayValue *DictionaryValue::lookup_array(const StringRef key) const +{ + if (const std::shared_ptr *value = this->lookup(key)) { + return (*value)->as_array_value(); + } + return nullptr; +} + +void DictionaryValue::append(std::string key, std::shared_ptr value) +{ + this->elements().append({std::move(key), std::move(value)}); +} + +void DictionaryValue::append_int(std::string key, const int64_t value) +{ + this->append(std::move(key), std::make_shared(value)); +} + +void DictionaryValue::append_double(std::string key, const double value) +{ + this->append(std::move(key), std::make_shared(value)); +} + +void DictionaryValue::append_str(std::string key, const std::string value) +{ + this->append(std::move(key), std::make_shared(value)); +} + +std::shared_ptr DictionaryValue::append_dict(std::string key) +{ + auto value = std::make_shared(); + this->append(std::move(key), value); + return value; +} + +std::shared_ptr DictionaryValue::append_array(std::string key) +{ + auto value = std::make_shared(); + this->append(std::move(key), value); + return value; +} + void JsonFormatter::serialize(std::ostream &os, const Value &value) { nlohmann::ordered_json j; @@ -216,4 +360,18 @@ std::unique_ptr JsonFormatter::deserialize(std::istream &is) return convert_from_json(j); } +void write_json_file(const StringRef path, const Value &value) +{ + JsonFormatter formatter; + fstream stream(path, std::ios::out); + formatter.serialize(stream, value); +} + +std::shared_ptr read_json_file(const StringRef path) +{ + JsonFormatter formatter; + fstream stream(path, std::ios::in); + return formatter.deserialize(stream); +} + } // namespace blender::io::serialize diff --git a/source/blender/blenlib/tests/BLI_serialize_test.cc b/source/blender/blenlib/tests/BLI_serialize_test.cc index 7d0ca057df8..cfc6220bc8c 100644 --- a/source/blender/blenlib/tests/BLI_serialize_test.cc +++ b/source/blender/blenlib/tests/BLI_serialize_test.cc @@ -78,12 +78,11 @@ TEST(serialize, array_to_json) JsonFormatter json; std::stringstream out; ArrayValue value_array; - ArrayValue::Items &array = value_array.elements(); - array.append_as(new IntValue(42)); - array.append_as(new StringValue("Hello JSON")); - array.append_as(new NullValue); - array.append_as(new BooleanValue(false)); - array.append_as(new BooleanValue(true)); + value_array.append_int(42); + value_array.append_str("Hello JSON"); + value_array.append_null(); + value_array.append_bool(false); + value_array.append_bool(true); json.serialize(out, value_array); EXPECT_EQ(out.str(), "[42,\"Hello JSON\",null,false,true]"); @@ -94,8 +93,7 @@ TEST(serialize, object_to_json) JsonFormatter json; std::stringstream out; DictionaryValue value_object; - DictionaryValue::Items &attributes = value_object.elements(); - attributes.append_as(std::pair(std::string("best_number"), new IntValue(42))); + value_object.append_int("best_number", 42); json.serialize(out, value_object); EXPECT_EQ(out.str(), "{\"best_number\":42}"); diff --git a/source/blender/editors/asset/intern/asset_indexer.cc b/source/blender/editors/asset/intern/asset_indexer.cc index 992d8d053d8..04554382716 100644 --- a/source/blender/editors/asset/intern/asset_indexer.cc +++ b/source/blender/editors/asset/intern/asset_indexer.cc @@ -657,8 +657,7 @@ struct AssetIndex { AssetIndex(const FileIndexerEntries &indexer_entries) { std::unique_ptr root = std::make_unique(); - DictionaryValue::Items &root_attributes = root->elements(); - root_attributes.append_as(std::pair(ATTRIBUTE_VERSION, new IntValue(CURRENT_VERSION))); + root->append_int(ATTRIBUTE_VERSION, CURRENT_VERSION); init_value_from_file_indexer_entries(*root, indexer_entries); contents = std::move(root);