Blender  V3.3
idprop_serialize.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation. */
3 
4 #include <optional>
5 
6 #include "DNA_ID.h"
7 
8 #include "BKE_idprop.hh"
9 
10 #include "BLI_listbase.h"
11 
12 namespace blender::bke::idprop {
13 using namespace blender::io::serialize;
14 
15 /* Forward declarations */
16 class IDPropertySerializer;
17 struct DictionaryEntryParser;
18 static IDProperty *idprop_from_value(const DictionaryValue &value);
19 static const IDPropertySerializer &serializer_for(eIDPropertyType property_type);
20 static const IDPropertySerializer &serializer_for(StringRef idprop_typename);
21 
22 /* -------------------------------------------------------------------- */
26 /* Definitions */
27 static constexpr StringRef IDP_KEY_NAME("name");
28 static constexpr StringRef IDP_KEY_TYPE("type");
29 static constexpr StringRef IDP_KEY_SUBTYPE("subtype");
30 static constexpr StringRef IDP_KEY_VALUE("value");
31 
32 static constexpr StringRef IDP_PROPERTY_TYPENAME_STRING("IDP_STRING");
33 static constexpr StringRef IDP_PROPERTY_TYPENAME_INT("IDP_INT");
34 static constexpr StringRef IDP_PROPERTY_TYPENAME_FLOAT("IDP_FLOAT");
35 static constexpr StringRef IDP_PROPERTY_TYPENAME_DOUBLE("IDP_DOUBLE");
36 static constexpr StringRef IDP_PROPERTY_TYPENAME_ARRAY("IDP_ARRAY");
37 static constexpr StringRef IDP_PROPERTY_TYPENAME_GROUP("IDP_GROUP");
38 static constexpr StringRef IDP_PROPERTY_TYPENAME_UNKNOWN("IDP_UNKNOWN");
39 
46  public:
47  constexpr IDPropertySerializer() = default;
48 
53  virtual std::string type_name() const = 0;
54 
58  virtual std::optional<eIDPropertyType> property_type() const = 0;
59 
63  virtual std::shared_ptr<DictionaryValue> idprop_to_dictionary(
64  const struct IDProperty *id_property) const = 0;
65 
69  virtual std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
70  DictionaryEntryParser &entry_reader) const = 0;
71 
77  virtual bool supports_serializing() const
78  {
79  return true;
80  }
81 
82  protected:
88  std::shared_ptr<DictionaryValue> create_dictionary(const struct IDProperty *id_property) const
89  {
90  std::shared_ptr<DictionaryValue> result = std::make_shared<DictionaryValue>();
91  DictionaryValue::Items &attributes = result->elements();
92  attributes.append_as(std::pair(IDP_KEY_NAME, new StringValue(id_property->name)));
93  attributes.append_as(std::pair(IDP_KEY_TYPE, new StringValue(type_name())));
94  return result;
95  }
96 };
97 
103 
104  public:
105  explicit DictionaryEntryParser(const DictionaryValue &value) : lookup(value.create_lookup())
106  {
107  }
108 
109  std::optional<eIDPropertyType> get_type() const
110  {
111  return get_id_property_type(IDP_KEY_TYPE);
112  }
113 
114  std::optional<eIDPropertyType> get_subtype() const
115  {
116  return get_id_property_type(IDP_KEY_SUBTYPE);
117  }
118 
119  std::optional<std::string> get_name() const
120  {
121  return get_string(IDP_KEY_NAME);
122  }
123 
124  std::optional<std::string> get_string_value() const
125  {
126  return get_string(IDP_KEY_VALUE);
127  }
128 
129  std::optional<int32_t> get_int_value() const
130  {
131  return get_int(IDP_KEY_VALUE);
132  }
133 
134  std::optional<float> get_float_value() const
135  {
136  return get_float(IDP_KEY_VALUE);
137  }
138 
139  std::optional<double> get_double_value() const
140  {
141  return get_double(IDP_KEY_VALUE);
142  }
143 
145  {
146  return get_array(IDP_KEY_VALUE);
147  }
148 
149  std::optional<Vector<int32_t>> get_array_int_value() const
150  {
151  return get_array_primitive<int32_t, IntValue>(IDP_KEY_VALUE);
152  }
153 
154  std::optional<Vector<float>> get_array_float_value() const
155  {
156  return get_array_primitive<float, DoubleValue>(IDP_KEY_VALUE);
157  }
158 
159  std::optional<Vector<double>> get_array_double_value() const
160  {
161  return get_array_primitive<double, DoubleValue>(IDP_KEY_VALUE);
162  }
163 
164  private:
165  std::optional<std::string> get_string(StringRef key) const
166  {
167  const DictionaryValue::LookupValue *value_ptr = lookup.lookup_ptr(key);
168  if (value_ptr == nullptr) {
169  return std::nullopt;
170  }
171  const DictionaryValue::LookupValue &value = *value_ptr;
172 
173  if (value->type() != eValueType::String) {
174  return std::nullopt;
175  }
176 
177  return value->as_string_value()->value();
178  }
179 
180  const ArrayValue *get_array(StringRef key) const
181  {
182  const DictionaryValue::LookupValue *value_ptr = lookup.lookup_ptr(key);
183  if (value_ptr == nullptr) {
184  return nullptr;
185  }
186  const DictionaryValue::LookupValue &value = *value_ptr;
187 
188  if (value->type() != eValueType::Array) {
189  return nullptr;
190  }
191 
192  return value->as_array_value();
193  }
194 
195  std::optional<int32_t> get_int(StringRef key) const
196  {
197  const DictionaryValue::LookupValue *value_ptr = lookup.lookup_ptr(key);
198  if (value_ptr == nullptr) {
199  return std::nullopt;
200  }
201  const DictionaryValue::LookupValue &value = *value_ptr;
202 
203  if (value->type() != eValueType::Int) {
204  return std::nullopt;
205  }
206 
207  return value->as_int_value()->value();
208  }
209 
210  std::optional<double> get_double(StringRef key) const
211  {
212  const DictionaryValue::LookupValue *value_ptr = lookup.lookup_ptr(key);
213  if (value_ptr == nullptr) {
214  return std::nullopt;
215  }
216  const DictionaryValue::LookupValue &value = *value_ptr;
217 
218  if (value->type() != eValueType::Double) {
219  return std::nullopt;
220  }
221 
222  return value->as_double_value()->value();
223  }
224 
225  std::optional<float> get_float(StringRef key) const
226  {
227  return static_cast<std::optional<float>>(get_double(key));
228  }
229 
230  template<typename PrimitiveType, typename ValueType>
231  std::optional<Vector<PrimitiveType>> get_array_primitive(StringRef key) const
232  {
233  const DictionaryValue::LookupValue *value_ptr = lookup.lookup_ptr(key);
234  if (value_ptr == nullptr) {
235  return std::nullopt;
236  }
237  const DictionaryValue::LookupValue &value = *value_ptr;
238 
239  if (value->type() != eValueType::Array) {
240  return std::nullopt;
241  }
242 
243  Vector<PrimitiveType> result;
244  const ArrayValue::Items &elements = value->as_array_value()->elements();
245  for (const ArrayValue::Item &element : elements) {
246  const ValueType *value_type = static_cast<const ValueType *>(element.get());
247  PrimitiveType primitive_value = value_type->value();
248  result.append_as(primitive_value);
249  }
250 
251  return result;
252  }
253 
254  std::optional<eIDPropertyType> get_id_property_type(StringRef key) const
255  {
256  std::optional<std::string> string_value = get_string(key);
257  if (!string_value.has_value()) {
258  return std::nullopt;
259  }
260  const IDPropertySerializer &serializer = serializer_for(*string_value);
261  return serializer.property_type();
262  }
263 };
264 
267  public:
268  constexpr IDPStringSerializer() = default;
269 
270  std::string type_name() const override
271  {
273  }
274 
275  std::optional<eIDPropertyType> property_type() const override
276  {
277  return IDP_STRING;
278  }
279 
280  std::shared_ptr<DictionaryValue> idprop_to_dictionary(
281  const struct IDProperty *id_property) const override
282  {
283  std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
284  DictionaryValue::Items &attributes = result->elements();
285  attributes.append_as(std::pair(IDP_KEY_VALUE, new StringValue(IDP_String(id_property))));
286  return result;
287  }
288 
289  std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
290  DictionaryEntryParser &entry_reader) const override
291  {
292  BLI_assert(*(entry_reader.get_type()) == IDP_STRING);
293  std::optional<std::string> name = entry_reader.get_name();
294  if (!name.has_value()) {
295  return nullptr;
296  }
297  std::optional<std::string> string_value = entry_reader.get_string_value();
298  if (!string_value.has_value()) {
299  return nullptr;
300  }
301  return create(name->c_str(), string_value->c_str());
302  }
303 };
304 
307  public:
308  constexpr IDPIntSerializer() = default;
309 
310  std::string type_name() const override
311  {
313  }
314 
315  std::optional<eIDPropertyType> property_type() const override
316  {
317  return IDP_INT;
318  }
319 
320  std::shared_ptr<DictionaryValue> idprop_to_dictionary(
321  const struct IDProperty *id_property) const override
322  {
323  std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
324  DictionaryValue::Items &attributes = result->elements();
325  attributes.append_as(std::pair(IDP_KEY_VALUE, new IntValue(IDP_Int(id_property))));
326  return result;
327  }
328 
329  std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
330  DictionaryEntryParser &entry_reader) const override
331  {
332  BLI_assert(*(entry_reader.get_type()) == IDP_INT);
333  std::optional<std::string> name = entry_reader.get_name();
334  if (!name.has_value()) {
335  return nullptr;
336  }
337  std::optional<int32_t> extracted_value = entry_reader.get_int_value();
338  if (!extracted_value.has_value()) {
339  return nullptr;
340  }
341  return create(name->c_str(), *extracted_value);
342  }
343 };
344 
347  public:
348  constexpr IDPFloatSerializer() = default;
349 
350  std::string type_name() const override
351  {
353  }
354 
355  std::optional<eIDPropertyType> property_type() const override
356  {
357  return IDP_FLOAT;
358  }
359 
360  std::shared_ptr<DictionaryValue> idprop_to_dictionary(
361  const struct IDProperty *id_property) const override
362  {
363  std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
364  DictionaryValue::Items &attributes = result->elements();
365  attributes.append_as(std::pair(IDP_KEY_VALUE, new DoubleValue(IDP_Float(id_property))));
366  return result;
367  }
368 
369  std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
370  DictionaryEntryParser &entry_reader) const override
371  {
372  BLI_assert(*(entry_reader.get_type()) == IDP_FLOAT);
373  std::optional<std::string> name = entry_reader.get_name();
374  if (!name.has_value()) {
375  return nullptr;
376  }
377  std::optional<float> extracted_value = entry_reader.get_float_value();
378  if (!extracted_value.has_value()) {
379  return nullptr;
380  }
381  return create(name->c_str(), *extracted_value);
382  }
383 };
384 
387  public:
388  constexpr IDPDoubleSerializer() = default;
389 
390  std::string type_name() const override
391  {
393  }
394 
395  std::optional<eIDPropertyType> property_type() const override
396  {
397  return IDP_DOUBLE;
398  }
399 
400  std::shared_ptr<DictionaryValue> idprop_to_dictionary(
401  const struct IDProperty *id_property) const override
402  {
403  std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
404  DictionaryValue::Items &attributes = result->elements();
405  attributes.append_as(std::pair(IDP_KEY_VALUE, new DoubleValue(IDP_Double(id_property))));
406  return result;
407  }
408 
409  std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
410  DictionaryEntryParser &entry_reader) const override
411  {
412  BLI_assert(*(entry_reader.get_type()) == IDP_DOUBLE);
413  std::optional<std::string> name = entry_reader.get_name();
414  if (!name.has_value()) {
415  return nullptr;
416  }
417  std::optional<double> extracted_value = entry_reader.get_double_value();
418  if (!extracted_value.has_value()) {
419  return nullptr;
420  }
421  return create(name->c_str(), *extracted_value);
422  }
423 };
424 
427  public:
428  constexpr IDPArraySerializer() = default;
429 
430  std::string type_name() const override
431  {
433  }
434 
435  std::optional<eIDPropertyType> property_type() const override
436  {
437  return IDP_ARRAY;
438  }
439 
440  std::shared_ptr<DictionaryValue> idprop_to_dictionary(
441  const struct IDProperty *id_property) const override
442  {
443  std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
444  DictionaryValue::Items &attributes = result->elements();
445  const IDPropertySerializer &subtype_serializer = serializer_for(
446  static_cast<eIDPropertyType>(id_property->subtype));
447  attributes.append_as(
448  std::pair(IDP_KEY_SUBTYPE, new StringValue(subtype_serializer.type_name())));
449 
450  std::shared_ptr<ArrayValue> array = std::make_shared<ArrayValue>();
451  switch (static_cast<eIDPropertyType>(id_property->subtype)) {
452  case IDP_INT: {
453  int32_t *values = static_cast<int32_t *>(IDP_Array(id_property));
454  add_values<int32_t, IntValue>(array.get(), Span<int32_t>(values, id_property->len));
455  break;
456  }
457 
458  case IDP_FLOAT: {
459  float *values = static_cast<float *>(IDP_Array(id_property));
460  add_values<float, DoubleValue>(array.get(), Span<float>(values, id_property->len));
461  break;
462  }
463 
464  case IDP_DOUBLE: {
465  double *values = static_cast<double *>(IDP_Array(id_property));
466  add_values<double, DoubleValue>(array.get(), Span<double>(values, id_property->len));
467  break;
468  }
469 
470  case IDP_GROUP: {
471  IDProperty *values = static_cast<IDProperty *>(IDP_Array(id_property));
472  add_values(array.get(), Span<IDProperty>(values, id_property->len));
473  break;
474  }
475 
476  default: {
477  /* IDP_ARRAY only supports IDP_INT, IDP_FLOAT, IDP_DOUBLE and IDP_GROUP. */
479  break;
480  }
481  }
482  attributes.append_as(std::pair(IDP_KEY_VALUE, std::move(array)));
483 
484  return result;
485  }
486 
487  std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
488  DictionaryEntryParser &entry_reader) const override
489  {
490  BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
491  std::optional<eIDPropertyType> property_subtype = entry_reader.get_subtype();
492  if (!property_subtype.has_value()) {
493  return nullptr;
494  }
495 
496  switch (*property_subtype) {
497  case IDP_INT:
498  return idprop_array_int_from_value(entry_reader);
499 
500  case IDP_FLOAT:
501  return idprop_array_float_from_value(entry_reader);
502 
503  case IDP_DOUBLE:
504  return idprop_array_double_from_value(entry_reader);
505 
506  default:
507  break;
508  }
509  return nullptr;
510  }
511 
512  private:
514  template</* C-primitive type of the values to add. Possible types are `float`, `int32_t` or
515  * `double`. */
516  typename PrimitiveType,
517  /* Type of value that can store the PrimitiveType in the Array. */
518  typename ValueType>
519  void add_values(ArrayValue *array, Span<PrimitiveType> values) const
520  {
521  ArrayValue::Items &items = array->elements();
522  for (PrimitiveType value : values) {
523  items.append_as(std::make_shared<ValueType>(value));
524  }
525  }
526 
527  void add_values(ArrayValue *array, Span<IDProperty> values) const
528  {
529  ArrayValue::Items &items = array->elements();
530  for (const IDProperty &id_property : values) {
531  const IDPropertySerializer &value_serializer = serializer_for(
532  static_cast<eIDPropertyType>(id_property.type));
533  if (!value_serializer.supports_serializing()) {
534  continue;
535  }
536  std::shared_ptr<DictionaryValue> value = value_serializer.idprop_to_dictionary(&id_property);
537  items.append_as(value);
538  }
539  }
540 
541  std::unique_ptr<IDProperty, IDPropertyDeleter> idprop_array_int_from_value(
542  DictionaryEntryParser &entry_reader) const
543  {
544  BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
545  BLI_assert(*(entry_reader.get_subtype()) == IDP_INT);
546  std::optional<std::string> name = entry_reader.get_name();
547  if (!name.has_value()) {
548  return nullptr;
549  }
550  std::optional<Vector<int32_t>> extracted_value = entry_reader.get_array_int_value();
551  if (!extracted_value.has_value()) {
552  return nullptr;
553  }
554  return create(name->c_str(), *extracted_value);
555  }
556 
557  std::unique_ptr<IDProperty, IDPropertyDeleter> idprop_array_float_from_value(
558  DictionaryEntryParser &entry_reader) const
559  {
560  BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
561  BLI_assert(*(entry_reader.get_subtype()) == IDP_FLOAT);
562  std::optional<std::string> name = entry_reader.get_name();
563  if (!name.has_value()) {
564  return nullptr;
565  }
566  std::optional<Vector<float>> extracted_value = entry_reader.get_array_float_value();
567  if (!extracted_value.has_value()) {
568  return nullptr;
569  }
570  return create(name->c_str(), *extracted_value);
571  }
572 
573  std::unique_ptr<IDProperty, IDPropertyDeleter> idprop_array_double_from_value(
574  DictionaryEntryParser &entry_reader) const
575  {
576  BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
577  BLI_assert(*(entry_reader.get_subtype()) == IDP_DOUBLE);
578  std::optional<std::string> name = entry_reader.get_name();
579  if (!name.has_value()) {
580  return nullptr;
581  }
582  std::optional<Vector<double>> extracted_value = entry_reader.get_array_double_value();
583  if (!extracted_value.has_value()) {
584  return nullptr;
585  }
586  return create(name->c_str(), *extracted_value);
587  }
588 };
589 
592  public:
593  constexpr IDPGroupSerializer() = default;
594 
595  std::string type_name() const override
596  {
598  }
599 
600  std::optional<eIDPropertyType> property_type() const override
601  {
602  return IDP_GROUP;
603  }
604 
605  std::shared_ptr<DictionaryValue> idprop_to_dictionary(
606  const struct IDProperty *id_property) const override
607  {
608  std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
609  DictionaryValue::Items &attributes = result->elements();
610  std::shared_ptr<ArrayValue> array = std::make_shared<ArrayValue>();
611  ArrayValue::Items &elements = array->elements();
612 
613  LISTBASE_FOREACH (IDProperty *, sub_property, &id_property->data.group) {
614 
615  const IDPropertySerializer &sub_property_serializer = serializer_for(
616  static_cast<eIDPropertyType>(sub_property->type));
617  elements.append_as(sub_property_serializer.idprop_to_dictionary(sub_property));
618  }
619 
620  attributes.append_as(std::pair(IDP_KEY_VALUE, array));
621  return result;
622  }
623 
624  std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
625  DictionaryEntryParser &entry_reader) const override
626  {
627  BLI_assert(*(entry_reader.get_type()) == IDP_GROUP);
628  std::optional<std::string> name = entry_reader.get_name();
629  if (!name.has_value()) {
630  return nullptr;
631  }
632 
633  const ArrayValue *array = entry_reader.get_array_value();
634  if (array == nullptr) {
635  return nullptr;
636  }
637 
638  std::unique_ptr<IDProperty, IDPropertyDeleter> result = create_group(name->c_str());
639  for (const ArrayValue::Item &element : array->elements()) {
640  if (element->type() != eValueType::Dictionary) {
641  continue;
642  }
643  const DictionaryValue *subobject = element->as_dictionary_value();
644  IDProperty *subproperty = idprop_from_value(*subobject);
645  IDP_AddToGroup(result.get(), subproperty);
646  }
647 
648  return result;
649  }
650 };
651 
656  public:
657  constexpr IDPUnknownSerializer() = default;
658  std::string type_name() const override
659  {
661  }
662  std::optional<eIDPropertyType> property_type() const override
663  {
664  return std::nullopt;
665  }
666 
667  std::shared_ptr<DictionaryValue> idprop_to_dictionary(
668  const struct IDProperty *UNUSED(id_property)) const override
669  {
671  return nullptr;
672  }
673 
674  bool supports_serializing() const override
675  {
676  return false;
677  }
678 
679  std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
680  DictionaryEntryParser &UNUSED(entry_reader)) const override
681  {
682  return nullptr;
683  }
684 };
685 
686 /* Serializers are constructed statically to remove construction/destruction. */
694 
697 {
698  switch (property_type) {
699  case IDP_STRING:
700  return IDP_SERIALIZER_STRING;
701 
702  case IDP_INT:
703  return IDP_SERIALIZER_INT;
704 
705  case IDP_FLOAT:
706  return IDP_SERIALIZER_FLOAT;
707 
708  case IDP_DOUBLE:
709  return IDP_SERIALIZER_DOUBLE;
710 
711  case IDP_ARRAY:
712  return IDP_SERIALIZER_ARRAY;
713 
714  case IDP_GROUP:
715  return IDP_SERIALIZER_GROUP;
716 
717  default:
718  BLI_assert_msg(false, "Trying to convert an unsupported/unknown property type to a string");
719  return IDP_SERIALIZER_UNKNOWN;
720  }
721 }
722 
724 static const IDPropertySerializer &serializer_for(StringRef idprop_typename)
725 {
726  if (idprop_typename == IDP_PROPERTY_TYPENAME_STRING) {
727  return IDP_SERIALIZER_STRING;
728  }
729  if (idprop_typename == IDP_PROPERTY_TYPENAME_INT) {
730  return IDP_SERIALIZER_INT;
731  }
732  if (idprop_typename == IDP_PROPERTY_TYPENAME_FLOAT) {
733  return IDP_SERIALIZER_FLOAT;
734  }
735  if (idprop_typename == IDP_PROPERTY_TYPENAME_DOUBLE) {
736  return IDP_SERIALIZER_DOUBLE;
737  }
738  if (idprop_typename == IDP_PROPERTY_TYPENAME_ARRAY) {
739  return IDP_SERIALIZER_ARRAY;
740  }
741  if (idprop_typename == IDP_PROPERTY_TYPENAME_GROUP) {
742  return IDP_SERIALIZER_GROUP;
743  }
744  return IDP_SERIALIZER_UNKNOWN;
745 }
746 
747 /* \} */
748 
749 /* -------------------------------------------------------------------- */
752 std::unique_ptr<ArrayValue> convert_to_serialize_values(const struct IDProperty *properties)
753 {
754  BLI_assert(properties != nullptr);
755  std::unique_ptr<ArrayValue> result = std::make_unique<ArrayValue>();
756  ArrayValue::Items &elements = result->elements();
757  const struct IDProperty *current_property = properties;
758  while (current_property != nullptr) {
759  const IDPropertySerializer &serializer = serializer_for(
760  static_cast<eIDPropertyType>(current_property->type));
761  if (serializer.supports_serializing()) {
762  elements.append_as(serializer.idprop_to_dictionary(current_property));
763  }
764  current_property = current_property->next;
765  }
766 
767  return result;
768 }
769 
770 /* \} */
771 
772 /* -------------------------------------------------------------------- */
777 {
778  DictionaryEntryParser entry_reader(value);
779  std::optional<eIDPropertyType> property_type = entry_reader.get_type();
780  if (!property_type.has_value()) {
781  return nullptr;
782  }
783 
784  const IDPropertySerializer &serializer = serializer_for(*property_type);
785  return serializer.entry_to_idprop(entry_reader).release();
786 }
787 
789 {
790  IDProperty *result = nullptr;
791  IDProperty *previous_added = nullptr;
792 
793  const ArrayValue::Items &elements = value.elements();
794  for (const ArrayValue::Item &element : elements) {
795  if (element->type() != eValueType::Dictionary) {
796  continue;
797  }
798  const DictionaryValue *object_value = element->as_dictionary_value();
799  IDProperty *last_created = idprop_from_value(*object_value);
800  if (last_created == nullptr) {
801  continue;
802  }
803 
804  if (result == nullptr) {
805  result = last_created;
806  }
807 
808  if (previous_added) {
809  previous_added->next = last_created;
810  }
811  last_created->prev = previous_added;
812  previous_added = last_created;
813  }
814 
815  return result;
816 }
817 
819 {
820  if (value.type() != eValueType::Array) {
821  return nullptr;
822  }
823 
824  return idprop_from_value(*value.as_array_value());
825 }
826 
827 /* \} */
828 
829 } // namespace blender::bke::idprop
#define IDP_Float(prop)
Definition: BKE_idprop.h:269
#define IDP_Int(prop)
Definition: BKE_idprop.h:244
#define IDP_String(prop)
Definition: BKE_idprop.h:271
#define IDP_Double(prop)
Definition: BKE_idprop.h:270
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL()
Definition: idprop.c:631
#define IDP_Array(prop)
Definition: BKE_idprop.h:245
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define UNUSED(x)
ID and Library types, which are fundamental for sdna.
eIDPropertyType
Definition: DNA_ID.h:135
@ IDP_DOUBLE
Definition: DNA_ID.h:143
@ IDP_FLOAT
Definition: DNA_ID.h:138
@ IDP_STRING
Definition: DNA_ID.h:136
@ IDP_INT
Definition: DNA_ID.h:137
@ IDP_GROUP
Definition: DNA_ID.h:141
@ IDP_ARRAY
Definition: DNA_ID.h:140
ATTR_WARN_UNUSED_RESULT const void * element
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const struct IDProperty *id_property) const override
create dictionary containing the given id_property.
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const struct IDProperty *id_property) const override
create dictionary containing the given id_property.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const struct IDProperty *id_property) const override
create dictionary containing the given id_property.
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const struct IDProperty *id_property) const override
create dictionary containing the given id_property.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const struct IDProperty *id_property) const override
create dictionary containing the given id_property.
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const struct IDProperty *id_property) const override
create dictionary containing the given id_property.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
Dummy serializer for unknown and unsupported types.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &UNUSED(entry_reader)) const override
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
bool supports_serializing() const override
Can the serializer be used?
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const struct IDProperty *UNUSED(id_property)) const override
Base class for (de)serializing IDProperties.
virtual std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const =0
convert the entry to an id property.
std::shared_ptr< DictionaryValue > create_dictionary(const struct IDProperty *id_property) const
Create a new DictionaryValue instance.
virtual std::string type_name() const =0
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
virtual std::shared_ptr< DictionaryValue > idprop_to_dictionary(const struct IDProperty *id_property) const =0
create dictionary containing the given id_property.
virtual std::optional< eIDPropertyType > property_type() const =0
return the IDPropertyType for (de)serializing.
virtual bool supports_serializing() const
Can the serializer be used?
const Container & elements() const
std::shared_ptr< Value > LookupValue
const ArrayValue * as_array_value() const
Definition: serialize.cc:41
static float get_float(PointerRNA &ptr, const char *name)
static int get_int(PointerRNA &ptr, const char *name)
static string get_string(PointerRNA &ptr, const char *name)
PrimitiveType
Definition: kernel/types.h:549
GAttributeReader lookup(const void *owner, const AttributeIDRef &attribute_id)
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRefNull prop_name)
Allocate a new IDProperty of type IDP_GROUP.
static constexpr StringRef IDP_KEY_SUBTYPE("subtype")
static constexpr StringRef IDP_PROPERTY_TYPENAME_FLOAT("IDP_FLOAT")
static constexpr IDPUnknownSerializer IDP_SERIALIZER_UNKNOWN
static constexpr StringRef IDP_PROPERTY_TYPENAME_STRING("IDP_STRING")
static constexpr IDPStringSerializer IDP_SERIALIZER_STRING
static constexpr StringRef IDP_KEY_VALUE("value")
static const IDPropertySerializer & serializer_for(eIDPropertyType property_type)
get the serializer for the given property type.
static constexpr IDPArraySerializer IDP_SERIALIZER_ARRAY
std::unique_ptr< io::serialize::ArrayValue > convert_to_serialize_values(const IDProperty *properties)
Convert the given properties to Value objects for serialization.
static constexpr StringRef IDP_PROPERTY_TYPENAME_DOUBLE("IDP_DOUBLE")
static constexpr IDPGroupSerializer IDP_SERIALIZER_GROUP
static constexpr StringRef IDP_PROPERTY_TYPENAME_UNKNOWN("IDP_UNKNOWN")
static constexpr StringRef IDP_PROPERTY_TYPENAME_GROUP("IDP_GROUP")
static IDProperty * idprop_from_value(const DictionaryValue &value)
static constexpr StringRef IDP_KEY_TYPE("type")
static constexpr StringRef IDP_PROPERTY_TYPENAME_INT("IDP_INT")
static constexpr IDPDoubleSerializer IDP_SERIALIZER_DOUBLE
static constexpr IDPFloatSerializer IDP_SERIALIZER_FLOAT
static constexpr StringRef IDP_PROPERTY_TYPENAME_ARRAY("IDP_ARRAY")
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value)
Allocate a new IDProperty of type IDP_INT, set its name and value.
static constexpr StringRef IDP_KEY_NAME("name")
static constexpr IDPIntSerializer IDP_SERIALIZER_INT
IDProperty * convert_from_serialize_value(const blender::io::serialize::Value &value)
Convert the given value to an IDProperty.
PrimitiveValue< double, eValueType::Double > DoubleValue
PrimitiveValue< int64_t, eValueType::Int > IntValue
signed int int32_t
Definition: stdint.h:77
ListBase group
Definition: DNA_ID.h:101
int len
Definition: DNA_ID.h:121
struct IDProperty * next
Definition: DNA_ID.h:107
char name[64]
Definition: DNA_ID.h:111
IDPropertyData data
Definition: DNA_ID.h:117
struct IDProperty * prev
Definition: DNA_ID.h:107
char subtype
Definition: DNA_ID.h:108
char type
Definition: DNA_ID.h:108
Helper class for parsing DictionaryValues.
std::optional< eIDPropertyType > get_subtype() const
std::optional< double > get_double_value() const
DictionaryEntryParser(const DictionaryValue &value)
std::optional< eIDPropertyType > get_type() const
std::optional< std::string > get_name() const
std::optional< Vector< float > > get_array_float_value() const
std::optional< int32_t > get_int_value() const
std::optional< float > get_float_value() const
std::optional< Vector< double > > get_array_double_value() const
std::optional< Vector< int32_t > > get_array_int_value() const
std::optional< std::string > get_string_value() const