1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
19 /** \file
20  * \ingroup bke
21  */
22 
23 #include "DNA_ID.h"
24 
25 #include "BLI_compiler_attrs.h"
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 struct BlendDataReader;
32 struct BlendExpander;
33 struct BlendLibReader;
34 struct BlendWriter;
35 struct ID;
36 struct IDProperty;
37 
38 typedef union IDPropertyTemplate {
39   int i;
40   float f;
41   double d;
42   struct {
43     const char *str;
44     int len;
45     char subtype;
46   } string;
47   struct ID *id;
48   struct {
49     int len;
50     char type;
51   } array;
52   struct {
53     int matvec_size;
54     const float *example;
55   } matrix_or_vector;
56 } IDPropertyTemplate;
57 
58 /* ----------- Property Array Type ---------- */
59 
60 IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
61 IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag) ATTR_WARN_UNUSED_RESULT
62     ATTR_NONNULL();
63 
64 /* shallow copies item */
65 void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL();
66 struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT
67     ATTR_NONNULL();
68 void IDP_AppendArray(struct IDProperty *prop, struct IDProperty *item);
69 void IDP_ResizeIDPArray(struct IDProperty *prop, int len);
70 
71 /* ----------- Numeric Array Type ----------- */
72 /*this function works for strings too!*/
73 void IDP_ResizeArray(struct IDProperty *prop, int newlen);
74 void IDP_FreeArray(struct IDProperty *prop);
75 
76 /* ---------- String Type ------------ */
77 IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) ATTR_WARN_UNUSED_RESULT
78     ATTR_NONNULL(2 /* 'name 'arg */); /* maxlen excludes '\0' */
79 void IDP_AssignString(struct IDProperty *prop, const char *st, int maxlen)
80     ATTR_NONNULL(); /* maxlen excludes '\0' */
81 void IDP_ConcatStringC(struct IDProperty *prop, const char *st) ATTR_NONNULL();
82 void IDP_ConcatString(struct IDProperty *str1, struct IDProperty *append) ATTR_NONNULL();
83 void IDP_FreeString(struct IDProperty *prop) ATTR_NONNULL();
84 
85 /*-------- ID Type -------*/
86 
87 typedef void (*IDPWalkFunc)(void *userData, IDProperty *idp);
88 
89 void IDP_AssignID(IDProperty *prop, ID *id, const int flag);
90 
91 /*-------- Group Functions -------*/
92 
93 /** Sync values from one group to another, only where they match */
94 void IDP_SyncGroupValues(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL();
95 void IDP_SyncGroupTypes(struct IDProperty *dest,
96                         const struct IDProperty *src,
97                         const bool do_arraylen) ATTR_NONNULL();
98 void IDP_ReplaceGroupInGroup(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL();
99 void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
100 void IDP_ReplaceInGroup_ex(struct IDProperty *group,
101                            struct IDProperty *prop,
102                            struct IDProperty *prop_exist);
103 void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite)
104     ATTR_NONNULL();
105 void IDP_MergeGroup_ex(IDProperty *dest,
106                        const IDProperty *src,
107                        const bool do_overwrite,
108                        const int flag) ATTR_NONNULL();
109 bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
110 bool IDP_InsertToGroup(struct IDProperty *group,
111                        struct IDProperty *previous,
112                        struct IDProperty *pnew) ATTR_NONNULL(1 /* group */, 3 /* pnew */);
113 void IDP_RemoveFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
114 void IDP_FreeFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
115 
116 IDProperty *IDP_GetPropertyFromGroup(const struct IDProperty *prop,
117                                      const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
118 IDProperty *IDP_GetPropertyTypeFromGroup(const struct IDProperty *prop,
119                                          const char *name,
120                                          const char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
121 
122 /*-------- Main Functions --------*/
123 struct IDProperty *IDP_GetProperties(struct ID *id,
124                                      const bool create_if_needed) ATTR_WARN_UNUSED_RESULT
125     ATTR_NONNULL();
126 struct IDProperty *IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT
127     ATTR_NONNULL();
128 struct IDProperty *IDP_CopyProperty_ex(const struct IDProperty *prop,
129                                        const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
130 void IDP_CopyPropertyContent(IDProperty *dst, IDProperty *src) ATTR_NONNULL();
131 
132 bool IDP_EqualsProperties_ex(IDProperty *prop1,
133                              IDProperty *prop2,
134                              const bool is_strict) ATTR_WARN_UNUSED_RESULT;
135 
136 bool IDP_EqualsProperties(struct IDProperty *prop1,
137                           struct IDProperty *prop2) ATTR_WARN_UNUSED_RESULT;
138 
139 struct IDProperty *IDP_New(const char type,
140                            const IDPropertyTemplate *val,
141                            const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
142 
143 void IDP_FreePropertyContent_ex(struct IDProperty *prop, const bool do_id_user);
144 void IDP_FreePropertyContent(struct IDProperty *prop);
145 void IDP_FreeProperty_ex(IDProperty *prop, const bool do_id_user);
146 void IDP_FreeProperty(struct IDProperty *prop);
147 
148 void IDP_ClearProperty(IDProperty *prop);
149 
150 void IDP_RelinkProperty(struct IDProperty *prop);
151 
152 void IDP_Reset(IDProperty *prop, const IDProperty *reference);
153 
154 #define IDP_Int(prop) ((prop)->data.val)
155 #define IDP_Array(prop) ((prop)->data.pointer)
156 /* C11 const correctness for casts */
157 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
158 #  define IDP_Float(prop) \
159     _Generic((prop), \
160   IDProperty *:             (*(float *)&(prop)->data.val), \
161   const IDProperty *: (*(const float *)&(prop)->data.val))
162 #  define IDP_Double(prop) \
163     _Generic((prop), \
164   IDProperty *:             (*(double *)&(prop)->data.val), \
165   const IDProperty *: (*(const double *)&(prop)->data.val))
166 #  define IDP_String(prop) \
167     _Generic((prop), \
168   IDProperty *:             ((char *) (prop)->data.pointer), \
169   const IDProperty *: ((const char *) (prop)->data.pointer))
170 #  define IDP_IDPArray(prop) \
171     _Generic((prop), \
172   IDProperty *:             ((IDProperty *) (prop)->data.pointer), \
173   const IDProperty *: ((const IDProperty *) (prop)->data.pointer))
174 #  define IDP_Id(prop) \
175     _Generic((prop), \
176   IDProperty *:             ((ID *) (prop)->data.pointer), \
177   const IDProperty *: ((const ID *) (prop)->data.pointer))
178 #else
179 #  define IDP_Float(prop) (*(float *)&(prop)->data.val)
180 #  define IDP_Double(prop) (*(double *)&(prop)->data.val)
181 #  define IDP_String(prop) ((char *)(prop)->data.pointer)
182 #  define IDP_IDPArray(prop) ((IDProperty *)(prop)->data.pointer)
183 #  define IDP_Id(prop) ((ID *)(prop)->data.pointer)
184 #endif
185 
186 /**
187  * Call a callback for each idproperty in the hierarchy under given root one (included).
188  *
189  */
190 typedef void (*IDPForeachPropertyCallback)(IDProperty *id_property, void *user_data);
191 
192 void IDP_foreach_property(struct IDProperty *id_property_root,
193                           const int type_filter,
194                           IDPForeachPropertyCallback callback,
195                           void *user_data);
196 
197 /* Format IDProperty as strings */
198 char *IDP_reprN(const struct IDProperty *prop, uint *r_len);
199 void IDP_repr_fn(const IDProperty *prop,
200                  void (*str_append_fn)(void *user_data, const char *str, uint str_len),
201                  void *user_data);
202 void IDP_print(const struct IDProperty *prop);
203 
204 void IDP_BlendWrite(struct BlendWriter *writer, const struct IDProperty *prop);
205 void IDP_BlendReadData_impl(struct BlendDataReader *reader,
206                             IDProperty **prop,
207                             const char *caller_func_id);
208 #define IDP_BlendDataRead(reader, prop) IDP_BlendReadData_impl(reader, prop, __func__)
209 void IDP_BlendReadLib(struct BlendLibReader *reader, IDProperty *prop);
210 void IDP_BlendReadExpand(struct BlendExpander *expander, IDProperty *prop);
211 
212 #ifdef __cplusplus
213 }
214 #endif
215