1 /* WEED is free software; you can redistribute it and/or
2 modify it under the terms of the GNU Lesser General Public
3 License as published by the Free Software Foundation; either
4 version 3 of the License, or (at your option) any later version.
5
6 Weed is distributed in the hope that it will be useful,
7 but WITHOUT ANY WARRANTY; without even the implied warranty of
8 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 Lesser General Public License for more details.
10
11 You should have received a copy of the GNU Lesser General Public
12 License along with this source code; if not, write to the Free Software
13 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
14
15 Weed is developed by:
16 Gabriel "Salsaman" Finch - http://lives-video.com
17
18 partly based on LiViDO, which is developed by:
19
20 Niels Elburg - http://veejay.sf.net
21 Denis "Jaromil" Rojo - http://freej.dyne.org
22 Tom Schouten - http://zwizwa.fartit.com
23 Andraz Tori - http://cvs.cinelerra.org
24
25 reviewed with suggestions and contributions from:
26 Silvano "Kysucix" Galliani - http://freej.dyne.org
27 Kentaro Fukuchi - http://megaui.net/fukuchi
28 Jun Iio - http://www.malib.net
29 Carlo Prelz - http://www2.fluido.as:8080/
30 */
31
32 /* (C) G. Finch, 2005 - 2020 */
33
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37
38 #define __LIBWEED__
39 #define __WEED__HOST__
40
41 #ifndef NEED_LOCAL_WEED
42 #include <weed/weed.h>
43 #include <weed/weed-effects.h>
44 #include <weed/weed-utils.h>
45 #else
46 #include "weed.h"
47 #include "weed-effects.h"
48 #include "weed-utils.h"
49 #endif
50
51 /////////////////////////////////////////////////////////////////
52
53 #define weed_get_value(plant, key, value) weed_leaf_get(plant, key, 0, value)
54 #define weed_check_leaf(plant, key) weed_get_value(plant, key, NULL)
55
56 static weed_malloc_f _malloc_func = malloc;
57 static weed_calloc_f _calloc_func = calloc;
58 static weed_memcpy_f _memcpy_func = memcpy;
59 static weed_memcmp_f _memcmp_func = memcmp;
60 static weed_free_f _free_func = free;
61
62
weed_utils_set_custom_memfuncs(weed_malloc_f malloc_func,weed_calloc_f calloc_func,weed_memcpy_f memcpy_func,weed_memcmp_f memcmp_func,weed_free_f free_func)63 void weed_utils_set_custom_memfuncs(weed_malloc_f malloc_func, weed_calloc_f calloc_func, weed_memcpy_f memcpy_func,
64 weed_memcmp_f memcmp_func, weed_free_f free_func) {
65 if (malloc_func) _malloc_func = malloc_func;
66 if (calloc_func) _calloc_func = calloc_func;
67 if (memcpy_func) _memcpy_func = memcpy_func;
68 if (memcmp_func) _memcmp_func = memcmp_func;
69 if (free_func) _free_func = free_func;
70 }
71
72
weed_plant_has_leaf(weed_plant_t * plant,const char * key)73 int weed_plant_has_leaf(weed_plant_t *plant, const char *key) {
74 // check for existence of a leaf, must have a value and not just a seed_type
75 if (weed_check_leaf(plant, key) == WEED_SUCCESS) return WEED_TRUE;
76 return WEED_FALSE;
77 }
78
79
weed_leaf_exists(weed_plant_t * plant,const char * key)80 int weed_leaf_exists(weed_plant_t *plant, const char *key) {
81 // check for existence of a leaf, may have only a seed_type but no value set
82 if (weed_leaf_seed_type(plant, key) == WEED_SEED_INVALID) return WEED_FALSE;
83 return WEED_TRUE;
84 }
85
86
87 /////////////////////////////////////////////////////////////////
88 // leaf setters
89
weed_set_int_value(weed_plant_t * plant,const char * key,int32_t value)90 weed_error_t weed_set_int_value(weed_plant_t *plant, const char *key, int32_t value) {
91 return weed_leaf_set(plant, key, WEED_SEED_INT, 1, (weed_voidptr_t)&value);
92 }
93
94
weed_set_double_value(weed_plant_t * plant,const char * key,double value)95 weed_error_t weed_set_double_value(weed_plant_t *plant, const char *key, double value) {
96 return weed_leaf_set(plant, key, WEED_SEED_DOUBLE, 1, (weed_voidptr_t)&value);
97 }
98
99
weed_set_boolean_value(weed_plant_t * plant,const char * key,int32_t value)100 weed_error_t weed_set_boolean_value(weed_plant_t *plant, const char *key, int32_t value) {
101 return weed_leaf_set(plant, key, WEED_SEED_BOOLEAN, 1, (weed_voidptr_t)&value);
102 }
103
104
weed_set_int64_value(weed_plant_t * plant,const char * key,int64_t value)105 weed_error_t weed_set_int64_value(weed_plant_t *plant, const char *key, int64_t value) {
106 return weed_leaf_set(plant, key, WEED_SEED_INT64, 1, (weed_voidptr_t)&value);
107 }
108
109
weed_set_string_value(weed_plant_t * plant,const char * key,const char * value)110 weed_error_t weed_set_string_value(weed_plant_t *plant, const char *key, const char *value) {
111 return weed_leaf_set(plant, key, WEED_SEED_STRING, 1, (weed_voidptr_t)&value);
112 }
113
114
weed_set_funcptr_value(weed_plant_t * plant,const char * key,weed_voidptr_t value)115 weed_error_t weed_set_funcptr_value(weed_plant_t *plant, const char *key, weed_voidptr_t value) {
116 return weed_leaf_set(plant, key, WEED_SEED_FUNCPTR, 1, (weed_voidptr_t)&value);
117 }
118
119
weed_set_voidptr_value(weed_plant_t * plant,const char * key,weed_voidptr_t value)120 weed_error_t weed_set_voidptr_value(weed_plant_t *plant, const char *key, weed_voidptr_t value) {
121 return weed_leaf_set(plant, key, WEED_SEED_VOIDPTR, 1, (weed_voidptr_t)&value);
122 }
123
124
weed_set_plantptr_value(weed_plant_t * plant,const char * key,weed_plant_t * value)125 weed_error_t weed_set_plantptr_value(weed_plant_t *plant, const char *key, weed_plant_t *value) {
126 return weed_leaf_set(plant, key, WEED_SEED_PLANTPTR, 1, (weed_voidptr_t)&value);
127 }
128
129
weed_set_custom_value(weed_plant_t * plant,const char * key,uint32_t seed_type,weed_voidptr_t value)130 weed_error_t weed_set_custom_value(weed_plant_t *plant, const char *key, uint32_t seed_type, weed_voidptr_t value) {
131 return weed_leaf_set(plant, key, seed_type, 1, (weed_voidptr_t)&value);
132 }
133
134
135 //////////////////////////////////////////////////////////////////////////////////////////////////
136
weed_leaf_check(weed_plant_t * plant,const char * key,uint32_t seed_type)137 static inline weed_error_t weed_leaf_check(weed_plant_t *plant, const char *key, uint32_t seed_type) {
138 weed_error_t err;
139 if ((err = weed_check_leaf(plant, key)) != WEED_SUCCESS) return err;
140 if (weed_leaf_seed_type(plant, key) != seed_type) return WEED_ERROR_WRONG_SEED_TYPE;
141 return WEED_SUCCESS;
142 }
143
144
weed_value_get(weed_plant_t * plant,const char * key,uint32_t seed_type,weed_voidptr_t retval)145 static inline weed_error_t weed_value_get(weed_plant_t *plant, const char *key, uint32_t seed_type, weed_voidptr_t retval) {
146 weed_error_t err;
147 if ((err = weed_leaf_check(plant, key, seed_type)) != WEED_SUCCESS) return err;
148 return weed_get_value(plant, key, retval);
149 }
150
151
152 ////////////////////////////////////////////////////////////
153
weed_get_int_value(weed_plant_t * plant,const char * key,weed_error_t * error)154 int32_t weed_get_int_value(weed_plant_t *plant, const char *key, weed_error_t *error) {
155 int32_t retval = 0;
156 weed_error_t err = weed_value_get(plant, key, WEED_SEED_INT, &retval);
157 if (error) *error = err;
158 return retval;
159 }
160
161
weed_get_double_value(weed_plant_t * plant,const char * key,weed_error_t * error)162 double weed_get_double_value(weed_plant_t *plant, const char *key, weed_error_t *error) {
163 double retval = 0.;
164 weed_error_t err = weed_value_get(plant, key, WEED_SEED_DOUBLE, &retval);
165 if (error) *error = err;
166 return retval;
167 }
168
169
weed_get_boolean_value(weed_plant_t * plant,const char * key,weed_error_t * error)170 int32_t weed_get_boolean_value(weed_plant_t *plant, const char *key, weed_error_t *error) {
171 int32_t retval = WEED_FALSE;
172 weed_error_t err = weed_value_get(plant, key, WEED_SEED_BOOLEAN, &retval);
173 if (error) *error = err;
174 return retval;
175 }
176
177
weed_get_int64_value(weed_plant_t * plant,const char * key,weed_error_t * error)178 int64_t weed_get_int64_value(weed_plant_t *plant, const char *key, weed_error_t *error) {
179 int64_t retval = 0;
180 weed_error_t err = weed_value_get(plant, key, WEED_SEED_INT64, &retval);
181 if (error) *error = err;
182 return retval;
183 }
184
185
weed_get_string_value(weed_plant_t * plant,const char * key,weed_error_t * error)186 char *weed_get_string_value(weed_plant_t *plant, const char *key, weed_error_t *error) {
187 char *retval = NULL;
188 weed_error_t err = weed_check_leaf(plant, key);
189 if (err != WEED_SUCCESS) {
190 if (error) *error = err;
191 return NULL;
192 }
193 if (weed_leaf_seed_type(plant, key) != WEED_SEED_STRING) {
194 if (error) *error = WEED_ERROR_WRONG_SEED_TYPE;
195 return NULL;
196 }
197 if ((retval = (char *)(*_malloc_func)(weed_leaf_element_size(plant, key, 0) + 1)) == NULL) {
198 if (error) *error = WEED_ERROR_MEMORY_ALLOCATION;
199 return NULL;
200 }
201 if ((err = weed_value_get(plant, key, WEED_SEED_STRING, &retval)) != WEED_SUCCESS) {
202 if (retval) {
203 (*_free_func)(retval);
204 retval = NULL;
205 }
206 }
207 if (error) *error = err;
208 return retval;
209 }
210
211
weed_get_voidptr_value(weed_plant_t * plant,const char * key,weed_error_t * error)212 weed_voidptr_t weed_get_voidptr_value(weed_plant_t *plant, const char *key, weed_error_t *error) {
213 weed_voidptr_t retval = NULL;
214 weed_error_t err = weed_value_get(plant, key, WEED_SEED_VOIDPTR, &retval);
215 if (error) *error = err;
216 return retval;
217 }
218
219
weed_get_funcptr_value(weed_plant_t * plant,const char * key,weed_error_t * error)220 weed_funcptr_t weed_get_funcptr_value(weed_plant_t *plant, const char *key, weed_error_t *error) {
221 weed_funcptr_t retval = NULL;
222 weed_error_t err = weed_value_get(plant, key, WEED_SEED_FUNCPTR, &retval);
223 if (error) *error = err;
224 return retval;
225 }
226
227
weed_get_plantptr_value(weed_plant_t * plant,const char * key,weed_error_t * error)228 weed_plant_t *weed_get_plantptr_value(weed_plant_t *plant, const char *key, weed_error_t *error) {
229 weed_plant_t *retval = NULL;
230 weed_error_t err = weed_value_get(plant, key, WEED_SEED_PLANTPTR, &retval);
231 if (error) *error = err;
232 return retval;
233 }
234
235
weed_get_custom_value(weed_plant_t * plant,const char * key,uint32_t seed_type,weed_error_t * error)236 weed_voidptr_t weed_get_custom_value(weed_plant_t *plant, const char *key, uint32_t seed_type, weed_error_t *error) {
237 weed_voidptr_t retval = NULL;
238 weed_error_t err = weed_value_get(plant, key, seed_type, &retval);
239 if (error) *error = err;
240 return retval;
241 }
242
243
244 ////////////////////////////////////////////////////////////
245
weed_get_values(weed_plant_t * plant,const char * key,size_t dsize,char ** retval,int * elems)246 static inline weed_error_t weed_get_values(weed_plant_t *plant, const char *key, size_t dsize, char **retval, int *elems) {
247 weed_error_t err;
248 weed_size_t num_elems = weed_leaf_num_elements(plant, key);
249
250 if (num_elems * dsize > 0) {
251 if ((*retval = (char *)(*_calloc_func)(num_elems, dsize)) == NULL) {
252 return WEED_ERROR_MEMORY_ALLOCATION;
253 }
254 }
255
256 for (int i = 0; i < num_elems; i++) {
257 if ((err = weed_leaf_get(plant, key, i, (weed_voidptr_t) & (*retval)[i * dsize])) != WEED_SUCCESS) {
258 (*_free_func)(*retval);
259 *retval = NULL;
260 return err;
261 }
262 }
263 if (elems) *elems = (int)num_elems;
264 return WEED_SUCCESS;
265 }
266
267
weed_get_arrayx(weed_plant_t * plant,const char * key,uint32_t seed_type,weed_size_t typelen,weed_error_t * error,int * elems)268 static inline weed_voidptr_t weed_get_arrayx(weed_plant_t *plant, const char *key,
269 uint32_t seed_type, weed_size_t typelen, weed_error_t *error, int *elems) {
270 char *retvals = NULL;
271 weed_error_t err = weed_leaf_check(plant, key, seed_type);
272 if (err != WEED_SUCCESS) {
273 if (elems) *elems = 0;
274 if (error) *error = err;
275 return NULL;
276 }
277 err = weed_get_values(plant, key, typelen, &retvals, elems);
278 if (error) *error = err;
279 return retvals;
280 }
281
282
weed_get_int_array_counted(weed_plant_t * plant,const char * key,int * count)283 int32_t *weed_get_int_array_counted(weed_plant_t *plant, const char *key, int *count) {
284 return (int32_t *)(weed_get_arrayx(plant, key, WEED_SEED_INT, 4, NULL, count));
285 }
weed_get_int_array(weed_plant_t * plant,const char * key,weed_error_t * error)286 int32_t *weed_get_int_array(weed_plant_t *plant, const char *key, weed_error_t *error) {
287 return (int32_t *)(weed_get_arrayx(plant, key, WEED_SEED_INT, 4, error, NULL));
288 }
289
weed_get_double_array_counted(weed_plant_t * plant,const char * key,int * count)290 double *weed_get_double_array_counted(weed_plant_t *plant, const char *key, int *count) {
291 return (double *)(weed_get_arrayx(plant, key, WEED_SEED_DOUBLE, 8, NULL, count));
292 }
weed_get_double_array(weed_plant_t * plant,const char * key,weed_error_t * error)293 double *weed_get_double_array(weed_plant_t *plant, const char *key, weed_error_t *error) {
294 return (double *)(weed_get_arrayx(plant, key, WEED_SEED_DOUBLE, 8, error, NULL));
295 }
296
weed_get_boolean_array_counted(weed_plant_t * plant,const char * key,int * count)297 int32_t *weed_get_boolean_array_counted(weed_plant_t *plant, const char *key, int *count) {
298 return (int32_t *)(weed_get_arrayx(plant, key, WEED_SEED_BOOLEAN, 4, NULL, count));
299 }
weed_get_boolean_array(weed_plant_t * plant,const char * key,weed_error_t * error)300 int32_t *weed_get_boolean_array(weed_plant_t *plant, const char *key, weed_error_t *error) {
301 return (int32_t *)(weed_get_arrayx(plant, key, WEED_SEED_BOOLEAN, 4, error, NULL));
302 }
303
weed_get_int64_array_counted(weed_plant_t * plant,const char * key,int * count)304 int64_t *weed_get_int64_array_counted(weed_plant_t *plant, const char *key, int *count) {
305 return (int64_t *)(weed_get_arrayx(plant, key, WEED_SEED_INT64, 8, NULL, count));
306 }
weed_get_int64_array(weed_plant_t * plant,const char * key,weed_error_t * error)307 int64_t *weed_get_int64_array(weed_plant_t *plant, const char *key, weed_error_t *error) {
308 return (int64_t *)(weed_get_arrayx(plant, key, WEED_SEED_INT64, 8, error, NULL));
309 }
310
311
__weed_get_string_array__(weed_plant_t * plant,const char * key,weed_error_t * error,int * count)312 char **__weed_get_string_array__(weed_plant_t *plant, const char *key, weed_error_t *error, int *count) {
313 weed_size_t num_elems;
314 char **retvals = NULL;
315
316 weed_error_t err = weed_leaf_check(plant, key, WEED_SEED_STRING);
317
318 if (err != WEED_SUCCESS) {
319 if (error) *error = err;
320 return NULL;
321 }
322
323 if ((num_elems = weed_leaf_num_elements(plant, key)) == 0) return NULL;
324
325 if ((retvals = (char **)(*_malloc_func)(num_elems * sizeof(char *))) == NULL) {
326 if (error) *error = WEED_ERROR_MEMORY_ALLOCATION;
327 return NULL;
328 }
329
330 for (int i = 0; i < num_elems; i++) {
331 if ((retvals[i] = (char *)(*_malloc_func)(weed_leaf_element_size(plant, key, i) + 1)) == NULL) {
332 for (--i; i >= 0; i--)(*_free_func)(retvals[i]);
333 if (error) *error = WEED_ERROR_MEMORY_ALLOCATION;
334 (*_free_func)(retvals);
335 return NULL;
336 }
337 if ((err = weed_leaf_get(plant, key, i, &retvals[i])) != WEED_SUCCESS) {
338 for (--i; i >= 0; i--)(*_free_func)(retvals[i]);
339 if (error) *error = err;
340 (*_free_func)(retvals);
341 return NULL;
342 }
343 }
344 if (error) *error = WEED_SUCCESS;
345 if (count) *count = num_elems;
346 return retvals;
347 }
348
349
weed_get_string_array_counted(weed_plant_t * plant,const char * key,int * count)350 char **weed_get_string_array_counted(weed_plant_t *plant, const char *key, int *count) {
351 return __weed_get_string_array__(plant, key, NULL, count);
352 }
weed_get_string_array(weed_plant_t * plant,const char * key,weed_error_t * error)353 char **weed_get_string_array(weed_plant_t *plant, const char *key, weed_error_t *error) {
354 return __weed_get_string_array__(plant, key, error, NULL);
355 }
356
weed_get_funcptr_array_counted(weed_plant_t * plant,const char * key,int * count)357 weed_funcptr_t *weed_get_funcptr_array_counted(weed_plant_t *plant, const char *key, int *count) {
358 return (weed_funcptr_t *)(weed_get_arrayx(plant, key, WEED_SEED_FUNCPTR, WEED_FUNCPTR_SIZE, NULL, count));
359 }
weed_get_funcptr_array(weed_plant_t * plant,const char * key,weed_error_t * error)360 weed_funcptr_t *weed_get_funcptr_array(weed_plant_t *plant, const char *key, weed_error_t *error) {
361 return (weed_funcptr_t *)(weed_get_arrayx(plant, key, WEED_SEED_FUNCPTR, WEED_FUNCPTR_SIZE, error, NULL));
362 }
363
weed_get_voidptr_array_counted(weed_plant_t * plant,const char * key,int * count)364 weed_voidptr_t *weed_get_voidptr_array_counted(weed_plant_t *plant, const char *key, int *count) {
365 return (weed_voidptr_t *)(weed_get_arrayx(plant, key, WEED_SEED_VOIDPTR, WEED_VOIDPTR_SIZE, NULL, count));
366 }
weed_get_voidptr_array(weed_plant_t * plant,const char * key,weed_error_t * error)367 weed_voidptr_t *weed_get_voidptr_array(weed_plant_t *plant, const char *key, weed_error_t *error) {
368 return (weed_voidptr_t *)(weed_get_arrayx(plant, key, WEED_SEED_VOIDPTR, WEED_VOIDPTR_SIZE, error, NULL));
369 }
370
weed_get_plantptr_array_counted(weed_plant_t * plant,const char * key,int * count)371 weed_plant_t **weed_get_plantptr_array_counted(weed_plant_t *plant, const char *key, int *count) {
372 return (weed_plant_t **)(weed_get_arrayx(plant, key, WEED_SEED_PLANTPTR, WEED_VOIDPTR_SIZE, NULL, count));
373 }
weed_get_plantptr_array(weed_plant_t * plant,const char * key,weed_error_t * error)374 weed_plant_t **weed_get_plantptr_array(weed_plant_t *plant, const char *key, weed_error_t *error) {
375 return (weed_plant_t **)(weed_get_arrayx(plant, key, WEED_SEED_PLANTPTR, WEED_VOIDPTR_SIZE, error, NULL));
376 }
377
weed_get_custom_array_counted(weed_plant_t * plant,const char * key,uint32_t seed_type,int * count)378 weed_voidptr_t *weed_get_custom_array_counted(weed_plant_t *plant, const char *key, uint32_t seed_type, int *count) {
379 return (weed_voidptr_t *)(weed_get_arrayx(plant, key, seed_type, WEED_VOIDPTR_SIZE, NULL, count));
380 }
weed_get_custom_array(weed_plant_t * plant,const char * key,uint32_t seed_type,weed_error_t * error)381 weed_voidptr_t *weed_get_custom_array(weed_plant_t *plant, const char *key, uint32_t seed_type, weed_error_t *error) {
382 return (weed_voidptr_t *)(weed_get_arrayx(plant, key, seed_type, WEED_VOIDPTR_SIZE, error, NULL));
383 }
384
385 /////////////////////////////////////////////////////
386
weed_set_int_array(weed_plant_t * plant,const char * key,weed_size_t num_elems,int32_t * values)387 weed_error_t weed_set_int_array(weed_plant_t *plant, const char *key, weed_size_t num_elems, int32_t *values) {
388 return weed_leaf_set(plant, key, WEED_SEED_INT, num_elems, (weed_voidptr_t)values);
389 }
390
weed_set_double_array(weed_plant_t * plant,const char * key,weed_size_t num_elems,double * values)391 weed_error_t weed_set_double_array(weed_plant_t *plant, const char *key, weed_size_t num_elems, double *values) {
392 return weed_leaf_set(plant, key, WEED_SEED_DOUBLE, num_elems, (weed_voidptr_t)values);
393 }
394
weed_set_boolean_array(weed_plant_t * plant,const char * key,weed_size_t num_elems,int32_t * values)395 weed_error_t weed_set_boolean_array(weed_plant_t *plant, const char *key, weed_size_t num_elems, int32_t *values) {
396 return weed_leaf_set(plant, key, WEED_SEED_BOOLEAN, num_elems, (weed_voidptr_t)values);
397 }
398
weed_set_int64_array(weed_plant_t * plant,const char * key,weed_size_t num_elems,int64_t * values)399 weed_error_t weed_set_int64_array(weed_plant_t *plant, const char *key, weed_size_t num_elems, int64_t *values) {
400 return weed_leaf_set(plant, key, WEED_SEED_INT64, num_elems, (weed_voidptr_t)values);
401 }
402
weed_set_string_array(weed_plant_t * plant,const char * key,weed_size_t num_elems,char ** values)403 weed_error_t weed_set_string_array(weed_plant_t *plant, const char *key, weed_size_t num_elems, char **values) {
404 return weed_leaf_set(plant, key, WEED_SEED_STRING, num_elems, (weed_voidptr_t)values);
405 }
406
weed_set_funcptr_array(weed_plant_t * plant,const char * key,weed_size_t num_elems,weed_funcptr_t * values)407 weed_error_t weed_set_funcptr_array(weed_plant_t *plant, const char *key, weed_size_t num_elems, weed_funcptr_t *values) {
408 return weed_leaf_set(plant, key, WEED_SEED_FUNCPTR, num_elems, (weed_voidptr_t)values);
409 }
410
weed_set_voidptr_array(weed_plant_t * plant,const char * key,weed_size_t num_elems,weed_voidptr_t * values)411 weed_error_t weed_set_voidptr_array(weed_plant_t *plant, const char *key, weed_size_t num_elems, weed_voidptr_t *values) {
412 return weed_leaf_set(plant, key, WEED_SEED_VOIDPTR, num_elems, (weed_voidptr_t)values);
413 }
414
weed_set_plantptr_array(weed_plant_t * plant,const char * key,weed_size_t num_elems,weed_plant_t ** values)415 weed_error_t weed_set_plantptr_array(weed_plant_t *plant, const char *key, weed_size_t num_elems, weed_plant_t **values) {
416 return weed_leaf_set(plant, key, WEED_SEED_PLANTPTR, num_elems, (weed_voidptr_t)values);
417 }
418
weed_set_custom_array(weed_plant_t * plant,const char * key,uint32_t seed_type,weed_size_t num_elems,weed_voidptr_t * values)419 weed_error_t weed_set_custom_array(weed_plant_t *plant, const char *key, uint32_t seed_type, weed_size_t num_elems,
420 weed_voidptr_t *values) {
421 return weed_leaf_set(plant, key, seed_type, num_elems, (weed_voidptr_t)values);
422 }
423
424 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
425
weed_get_plant_type(weed_plant_t * plant)426 int32_t weed_get_plant_type(weed_plant_t *plant) {
427 if (!plant) return WEED_PLANT_UNKNOWN;
428 return weed_get_int_value(plant, WEED_LEAF_TYPE, NULL);
429 }
430
431
weed_leaf_copy_nth(weed_plant_t * dst,const char * keyt,weed_plant_t * src,const char * keyf,int n)432 weed_error_t weed_leaf_copy_nth(weed_plant_t *dst, const char *keyt, weed_plant_t *src, const char *keyf, int n) {
433 // copy a leaf from src to dest
434 // pointers are copied by reference only
435 // strings are duplicated
436
437 // if src or dst are NULL, nothing is copied and WEED_SUCCESS is returned
438
439 // may return the standard errors:
440 // WEED_SUCCESS, WEED_ERROR_MEMORY_ALLOCATION, WEED_ERROR_IMMUTABLE, WEED_ERROR_WRONG_SEED_TYPE
441 weed_error_t err;
442 uint32_t seed_type;
443 int num, count;
444
445 if (!dst || !src) return WEED_SUCCESS;
446
447 if ((err = weed_check_leaf(src, keyf)) == WEED_ERROR_NOSUCH_LEAF) return WEED_ERROR_NOSUCH_LEAF;
448
449 seed_type = weed_leaf_seed_type(src, keyf);
450
451 if (err == WEED_ERROR_NOSUCH_ELEMENT) {
452 err = weed_leaf_set(dst, keyt, seed_type, 0, NULL);
453 } else {
454 switch (seed_type) {
455 case WEED_SEED_INT: {
456 int32_t *datai = weed_get_arrayx(src, keyf, WEED_SEED_INT, 4, &err, &num);
457 if (err == WEED_SUCCESS) {
458 if (n >= 0) {
459 if (n >= num) err = WEED_ERROR_NOSUCH_ELEMENT;
460 else {
461 int32_t *datai2 = weed_get_arrayx(dst, keyt, WEED_SEED_INT, 4, &err, &count);
462 if (err == WEED_SUCCESS) {
463 if (n >= count) err = WEED_ERROR_NOSUCH_ELEMENT;
464 else {
465 datai2[n] = datai[n];
466 (*_free_func)(datai);
467 datai = datai2;
468 num = count;
469 // *INDENT-OFF*
470 }}}}
471 // *INDENT-ON*
472 if (err == WEED_SUCCESS)
473 err = weed_set_int_array(dst, keyt, num, datai);
474 }
475 if (datai)(*_free_func)(datai);
476 }
477 break;
478 case WEED_SEED_INT64: {
479 int64_t *datai64 = weed_get_arrayx(src, keyf, WEED_SEED_INT64, 8, &err, &num);
480 if (err == WEED_SUCCESS) {
481 if (n >= 0) {
482 if (n >= num) err = WEED_ERROR_NOSUCH_ELEMENT;
483 else {
484 int64_t *datai642 = weed_get_arrayx(dst, keyt, WEED_SEED_INT64, 8, &err, &count);
485 if (err == WEED_SUCCESS) {
486 if (n >= count) err = WEED_ERROR_NOSUCH_ELEMENT;
487 else {
488 datai642[n] = datai64[n];
489 (*_free_func)(datai64);
490 datai64 = datai642;
491 num = count;
492 // *INDENT-OFF*
493 }}}}
494 // *INDENT-ON*
495 if (err == WEED_SUCCESS)
496 err = weed_set_int64_array(dst, keyt, num, datai64);
497 }
498 if (datai64)(*_free_func)(datai64);
499 }
500 break;
501 case WEED_SEED_BOOLEAN: {
502 int32_t *datai = weed_get_arrayx(src, keyf, WEED_SEED_BOOLEAN, 4, &err, &num);
503 if (err == WEED_SUCCESS) {
504 if (n >= 0) {
505 if (n >= num) err = WEED_ERROR_NOSUCH_ELEMENT;
506 else {
507 int32_t *datai2 = weed_get_arrayx(dst, keyt, WEED_SEED_BOOLEAN, 4, &err, &count);
508 if (err == WEED_SUCCESS) {
509 if (n >= count) err = WEED_ERROR_NOSUCH_ELEMENT;
510 else {
511 datai2[n] = datai[n];
512 (*_free_func)(datai);
513 datai = datai2;
514 num = count;
515 // *INDENT-OFF*
516 }}}}
517 // *INDENT-ON*
518 if (err == WEED_SUCCESS)
519 err = weed_set_boolean_array(dst, keyt, num, datai);
520 }
521 if (datai)(*_free_func)(datai);
522 }
523 break;
524 case WEED_SEED_DOUBLE: {
525 double *datad = weed_get_arrayx(src, keyf, WEED_SEED_DOUBLE, 8, &err, &num);
526 if (err == WEED_SUCCESS) {
527 if (n >= 0) {
528 if (n >= num) err = WEED_ERROR_NOSUCH_ELEMENT;
529 else {
530 double *datad2 = weed_get_arrayx(dst, keyt, WEED_SEED_DOUBLE, 8, &err, &count);
531 if (err == WEED_SUCCESS) {
532 if (n >= count) err = WEED_ERROR_NOSUCH_ELEMENT;
533 else {
534 datad2[n] = datad[n];
535 (*_free_func)(datad);
536 datad = datad2;
537 num = count;
538 // *INDENT-OFF*
539 }}}}
540 // *INDENT-ON*
541 if (err == WEED_SUCCESS)
542 err = weed_set_double_array(dst, keyt, num, datad);
543 }
544 if (datad)(*_free_func)(datad);
545 }
546 break;
547 case WEED_SEED_FUNCPTR: {
548 weed_funcptr_t *dataf = weed_get_arrayx(src, keyf, WEED_SEED_FUNCPTR, WEED_FUNCPTR_SIZE, &err, &num);
549 if (err == WEED_SUCCESS) {
550 if (n >= 0) {
551 if (n >= num) err = WEED_ERROR_NOSUCH_ELEMENT;
552 else {
553 weed_funcptr_t *dataf2 = NULL;
554 dataf2 = weed_get_arrayx(dst, keyt, WEED_SEED_FUNCPTR, WEED_FUNCPTR_SIZE, &err, &count);
555 if (err == WEED_SUCCESS) {
556 if (n >= count) err = WEED_ERROR_NOSUCH_ELEMENT;
557 else {
558 dataf2[n] = dataf[n];
559 (*_free_func)(dataf);
560 dataf = dataf2;
561 num = count;
562 // *INDENT-OFF*
563 }}}}
564 // *INDENT-ON*
565 if (err == WEED_SUCCESS)
566 err = weed_set_funcptr_array(dst, keyt, num, dataf);
567 }
568 if (dataf)(*_free_func)(dataf);
569 }
570 break;
571 case WEED_SEED_VOIDPTR: {
572 weed_voidptr_t *datav = weed_get_arrayx(src, keyf, WEED_SEED_VOIDPTR, WEED_VOIDPTR_SIZE, &err, &num);
573 if (err == WEED_SUCCESS) {
574 if (n >= 0) {
575 if (n >= num) err = WEED_ERROR_NOSUCH_ELEMENT;
576 else {
577 weed_voidptr_t *datav2 = weed_get_arrayx(dst, keyt, WEED_SEED_VOIDPTR, WEED_VOIDPTR_SIZE, &err, &count);
578 if (err == WEED_SUCCESS) {
579 if (n >= count) err = WEED_ERROR_NOSUCH_ELEMENT;
580 else {
581 datav2[n] = datav[n];
582 (*_free_func)(datav);
583 datav = datav2;
584 num = count;
585 // *INDENT-OFF*
586 }}}}
587 // *INDENT-ON*
588 if (err == WEED_SUCCESS)
589 err = weed_set_voidptr_array(dst, keyt, num, datav);
590 }
591 if (datav)(*_free_func)(datav);
592 }
593 break;
594 case WEED_SEED_PLANTPTR: {
595 weed_plant_t **datap = weed_get_arrayx(src, keyf, WEED_SEED_PLANTPTR, WEED_VOIDPTR_SIZE, &err, &num);
596 if (err == WEED_SUCCESS) {
597 if (n >= 0) {
598 if (n >= num) err = WEED_ERROR_NOSUCH_ELEMENT;
599 else {
600 weed_plant_t **datap2 = weed_get_arrayx(dst, keyt, WEED_SEED_PLANTPTR, WEED_VOIDPTR_SIZE, &err, &count);
601 if (err == WEED_SUCCESS) {
602 if (n >= count) err = WEED_ERROR_NOSUCH_ELEMENT;
603 else {
604 datap2[n] = datap[n];
605 (*_free_func)(datap);
606 datap = datap2;
607 num = count;
608 // *INDENT-OFF*
609 }}}}
610 // *INDENT-ON*
611 if (err == WEED_SUCCESS)
612 err = weed_set_plantptr_array(dst, keyt, num, datap);
613 }
614 if (datap)(*_free_func)(datap);
615 }
616 break;
617 case WEED_SEED_STRING: {
618 char **datac = __weed_get_string_array__(src, keyf, &err, &num);
619 if (err == WEED_SUCCESS) {
620 if (n >= 0) {
621 if (n >= num) err = WEED_ERROR_NOSUCH_ELEMENT;
622 else {
623 char **datac2 = __weed_get_string_array__(dst, keyt, &err, &count);
624 if (err == WEED_SUCCESS) {
625 if (n >= count) err = WEED_ERROR_NOSUCH_ELEMENT;
626 else {
627 (*_free_func)(datac2[n]);
628 datac2[n] = datac[n];
629 for (int i = 0; i < num; i++) if (i != n)(*_free_func)(datac[n]);
630 (*_free_func)(datac);
631 datac = datac2;
632 num = count;
633 // *INDENT-OFF*
634 }}}}
635 // *INDENT-ON*
636 if (err == WEED_SUCCESS)
637 err = weed_set_string_array(dst, keyt, num, datac);
638 }
639 for (int i = 0; i < num; i++)(*_free_func)(datac[i]);
640 (*_free_func)(datac);
641 }
642 break;
643 }
644 }
645 return err;
646 }
647
weed_leaf_copy(weed_plant_t * dst,const char * keyt,weed_plant_t * src,const char * keyf)648 weed_error_t weed_leaf_copy(weed_plant_t *dst, const char *keyt, weed_plant_t *src, const char *keyf) {
649 return weed_leaf_copy_nth(dst, keyt, src, keyf, -1);
650 }
651
weed_leaf_dup(weed_plant_t * dst,weed_plant_t * src,const char * key)652 weed_error_t weed_leaf_dup(weed_plant_t *dst, weed_plant_t *src, const char *key) {
653 return weed_leaf_copy_nth(dst, key, src, key, -1);
654 }
655
weed_leaf_dup_nth(weed_plant_t * dst,weed_plant_t * src,const char * key,int n)656 weed_error_t weed_leaf_dup_nth(weed_plant_t *dst, weed_plant_t *src, const char *key, int n) {
657 return weed_leaf_copy_nth(dst, key, src, key, n);
658 }
659
weed_leaf_elements_equate(weed_plant_t * p0,const char * k0,weed_plant_t * p1,const char * k1,int elem)660 int weed_leaf_elements_equate(weed_plant_t *p0, const char *k0, weed_plant_t *p1, const char *k1, int elem) {
661 int c0, c1;
662 int32_t st;
663 weed_error_t err;
664 int ret = WEED_FALSE, i;
665 if (!p0 || !p1) return WEED_FALSE;
666 st = weed_leaf_seed_type(p0, k0);
667 if (st == WEED_SEED_INVALID || st != weed_leaf_seed_type(p1, k1)) return WEED_FALSE;
668 if (st != WEED_SEED_STRING) {
669 weed_size_t sz = weed_leaf_element_size(p0, k0, 0);
670 char *m0 = weed_get_arrayx(p0, k0, st, sz, &err, &c0);
671 if (err == WEED_SUCCESS) {
672 char *m1 = weed_get_arrayx(p1, k1, st, sz, &err, &c1);
673 if (err == WEED_SUCCESS) {
674 if (elem < 0) {
675 if (c0 == c1 && !(*_memcmp_func)(m0, m1, c0 * sz)) ret = WEED_TRUE;
676 } else if (c0 > elem && c1 > elem && !(*_memcmp_func)(m0 + elem * sz, m1 + elem * sz, sz)) ret = WEED_TRUE;
677 }
678 if (m1)(*_free_func)(m1);
679 }
680 if (m0)(*_free_func)(m0);
681 } else {
682 char **s0 = __weed_get_string_array__(p0, k0, &err, &c0);
683 if (err == WEED_SUCCESS) {
684 char **s1 = __weed_get_string_array__(p1, k1, &err, &c1);
685 if (err == WEED_SUCCESS) {
686 if (elem < 0) {
687 if (c0 == c1) {
688 for (i = 0; i < c0; i++) if (strcmp(s0[i], s1[i])) break;
689 if (i == c0) ret = WEED_TRUE;
690 }
691 } else if (c0 > elem && c1 > elem && !strcmp(s0[elem], s1[elem])) ret = WEED_TRUE;
692 }
693 if (s1) {
694 for (i = 0; i < c1; i++)(*_free_func)(s1[i]);
695 (*_free_func)(s1);
696 }
697 }
698 if (s0) {
699 for (i = 0; i < c0; i++)(*_free_func)(s0[i]);
700 (*_free_func)(s0);
701 }
702 }
703 return ret;
704 }
705
706
weed_plant_copy(weed_plant_t * src)707 weed_plant_t *weed_plant_copy(weed_plant_t *src) {
708 weed_plant_t *plant;
709 weed_error_t err;
710 char **proplist;
711 char *prop;
712 int i = 0;
713
714 if (!src) return NULL;
715
716 plant = weed_plant_new(weed_get_int_value(src, WEED_LEAF_TYPE, &err));
717 if (!plant) return NULL;
718
719 proplist = weed_plant_list_leaves(src, NULL);
720 for (prop = proplist[0]; (prop = proplist[i]) != NULL && err == WEED_SUCCESS; i++) {
721 if (err == WEED_SUCCESS) {
722 if (strcmp(prop, WEED_LEAF_TYPE)) {
723 err = weed_leaf_copy(plant, prop, src, prop);
724 if (err == WEED_ERROR_IMMUTABLE || err == WEED_ERROR_WRONG_SEED_TYPE) err = WEED_SUCCESS; // ignore these errors
725 }
726 }(*_free_func)(prop);
727 }(*_free_func)(proplist);
728
729 if (err == WEED_ERROR_MEMORY_ALLOCATION) {
730 //if (plant!=NULL) weed_plant_free(plant); // well, we should free the plant, but the plugins don't have this function...
731 return NULL;
732 }
733
734 return plant;
735 }
736
737 //////////////////////////////////////////////////////////////////////////////////////////////////////////
738
739 #define weed_seed_is_ptr(seed_type) (seed_type >= 64 ? WEED_TRUE : WEED_FALSE)
740
741 #define weed_seed_get_size(seed_type, size) (weed_seed_is_ptr(seed_type) ? WEED_VOIDPTR_SIZE : \
742 (seed_type == WEED_SEED_BOOLEAN || seed_type == WEED_SEED_INT) ? 4 : \
743 seed_type == WEED_SEED_DOUBLE ? 8 : \
744 seed_type == WEED_SEED_INT64 ? 8 : \
745 seed_type == WEED_SEED_STRING ? size : 0)
746
747
weed_find_leaf(weed_plant_t * leaf,const char * key)748 static inline weed_leaf_t *weed_find_leaf(weed_plant_t *leaf, const char *key) {
749 for (; leaf; leaf = leaf->next) {
750 if (!strcmp((char *)leaf->key, (char *)key)) return leaf;
751 }
752 return NULL;
753 }
754
755
_weed_default_get(weed_plant_t * plant,const char * key,void * value)756 static weed_error_t _weed_default_get(weed_plant_t *plant, const char *key, void *value) {
757 // we pass a pointer to this function back to the plugin so that it can bootstrap its real functions
758
759 // here we must assume that the plugin does not yet have its (static) memory functions, so we can only
760 // use the standard ones
761
762 weed_leaf_t *leaf = weed_find_leaf(plant, key);
763 if (!leaf) return WEED_ERROR_NOSUCH_LEAF;
764 if (!leaf->num_elements) return WEED_ERROR_NOSUCH_ELEMENT;
765 if (!value) return WEED_SUCCESS; // value can be NULL to check if leaf exists
766
767 if (leaf->seed_type == WEED_SEED_FUNCPTR) {
768 if (leaf->data[0]->value.funcptr == NULL) {
769 // because this is a special function, we return an error if the value is NULL, even though the value exists
770 *((weed_funcptr_t **)value) = NULL;
771 return WEED_ERROR_NOSUCH_ELEMENT;
772 }
773 (*_memcpy_func)(value, &(((weed_data_t *)(leaf->data[0]))->value.funcptr), WEED_FUNCPTR_SIZE);
774 return WEED_SUCCESS;
775 }
776 if (weed_seed_is_ptr(leaf->seed_type)) {
777 if (leaf->data[0]->value.voidptr == NULL) *((void **)value) = NULL;
778 else (*_memcpy_func)(value, &(((weed_data_t *)(leaf->data[0]))->value.voidptr), WEED_VOIDPTR_SIZE);
779 return WEED_SUCCESS;
780 } else {
781 if (leaf->seed_type == WEED_SEED_STRING) {
782 weed_size_t size = leaf->data[0]->size;
783 char **valuecharptrptr = (char **)value;
784 if (size > 0)(*_memcpy_func)(*valuecharptrptr, leaf->data[0]->value.voidptr, size);
785 (*valuecharptrptr)[size] = 0;
786 } else (*_memcpy_func)(value, leaf->data[0]->value.voidptr,
787 weed_seed_get_size(leaf->seed_type, leaf->data[0]->size));
788 }
789 return WEED_SUCCESS;
790 }
791
792
793 static weed_host_info_callback_f host_info_callback = NULL;
794 static void *host_info_callback_data = NULL;
795
weed_set_host_info_callback(weed_host_info_callback_f cb,void * user_data)796 void weed_set_host_info_callback(weed_host_info_callback_f cb, void *user_data) {
797 host_info_callback = cb;
798 host_info_callback_data = user_data;
799 }
800
801
check_weed_abi_compat(int32_t higher,int32_t lower)802 int check_weed_abi_compat(int32_t higher, int32_t lower) {
803 if (lower == higher) return WEED_TRUE; // equal versions are always compatible
804 if (lower > higher) {
805 int32_t tmp = lower;
806 lower = higher;
807 higher = tmp;
808 }
809 if (higher > WEED_ABI_VERSION) return WEED_FALSE; // we cant possibly know about future versions
810 if (lower < 200 && higher >= 200) return WEED_FALSE; // ABI 200 made breaking changes
811 if (higher < 100) return WEED_FALSE;
812 return WEED_TRUE;
813 }
814
815
check_filter_api_compat(int32_t higher,int32_t lower)816 int check_filter_api_compat(int32_t higher, int32_t lower) {
817 if (lower == higher) return WEED_TRUE; // equal versions are always compatible
818 if (lower > higher) {
819 int32_t tmp = lower;
820 lower = higher;
821 higher = tmp;
822 }
823 if (higher > WEED_FILTER_API_VERSION) return WEED_FALSE; // we cant possibly know about future versions
824 if (higher < 100) return WEED_FALSE;
825 return WEED_TRUE;
826 }
827
828
check_version_compat(int host_weed_api_version,int plugin_weed_api_min_version,int plugin_weed_api_max_version,int host_filter_api_version,int plugin_filter_api_min_version,int plugin_filter_api_max_version)829 static int check_version_compat(int host_weed_api_version,
830 int plugin_weed_api_min_version,
831 int plugin_weed_api_max_version,
832 int host_filter_api_version,
833 int plugin_filter_api_min_version,
834 int plugin_filter_api_max_version) {
835 if (plugin_weed_api_min_version > host_weed_api_version || plugin_filter_api_min_version > host_filter_api_version)
836 return WEED_FALSE;
837
838 if (host_weed_api_version > plugin_weed_api_max_version) {
839 if (check_weed_abi_compat(host_weed_api_version, plugin_weed_api_max_version) == 0) return 0;
840 }
841
842 if (host_filter_api_version > plugin_filter_api_max_version) {
843 return check_filter_api_compat(host_filter_api_version, plugin_filter_api_max_version);
844 }
845 return WEED_TRUE;
846 }
847
848
weed_bootstrap(weed_default_getter_f * value,int32_t plugin_min_weed_abi_version,int32_t plugin_max_weed_abi_version,int32_t plugin_min_filter_api_version,int32_t plugin_max_filter_api_version)849 weed_plant_t *weed_bootstrap(weed_default_getter_f * value,
850 int32_t plugin_min_weed_abi_version,
851 int32_t plugin_max_weed_abi_version,
852 int32_t plugin_min_filter_api_version,
853 int32_t plugin_max_filter_api_version) {
854 // function is called from weed_setup() in the plugin, using the fn ptr passed by the host
855
856 // here is where we define the functions for the plugin to use
857 // the host is free to implement its own version and then pass a pointer to that function in weed_setup() for the plugin
858
859 static weed_leaf_get_f wlg;
860 static weed_plant_new_f wpn;
861 static weed_plant_list_leaves_f wpll;
862 static weed_leaf_num_elements_f wlne;
863 static weed_leaf_element_size_f wles;
864 static weed_leaf_seed_type_f wlst;
865 static weed_leaf_get_flags_f wlgf;
866 static weed_leaf_set_f wls;
867 static weed_malloc_f weedmalloc;
868 #if WEED_ABI_CHECK_VERSION(200)
869 static weed_realloc_f weedrealloc;
870 static weed_calloc_f weedcalloc;
871 static weed_memmove_f weedmemmove;
872 #endif
873 static weed_free_f weedfree;
874 static weed_memcpy_f weedmemcpy;
875 static weed_memset_f weedmemset;
876 static weed_plant_free_f wpf;
877 static weed_leaf_delete_f wld;
878
879 int host_set_host_info = WEED_FALSE;
880
881 #if WEED_ABI_CHECK_VERSION(200)
882 int32_t host_weed_abi_version = weed_get_abi_version();
883 #else
884 /* versions here are just default values, we will set them again later, after possibly calling the host_info_callback function */
885 int32_t host_weed_abi_version = WEED_ABI_VERSION;
886 #endif
887 int32_t host_filter_api_version = WEED_FILTER_API_VERSION;
888
889 int32_t plugin_weed_abi_version = plugin_min_weed_abi_version;
890 int32_t plugin_filter_api_version = plugin_min_filter_api_version;
891
892 weed_plant_t *host_info = NULL;
893 weed_plant_t *plugin_info = NULL;
894
895 weed_error_t err;
896
897 if (host_weed_abi_version > WEED_ABI_VERSION) return NULL;
898
899 *value = _weed_default_get; // value is a pointer to fn. ptr
900 if (*value == NULL) return NULL;
901
902 if (plugin_min_weed_abi_version > plugin_max_weed_abi_version) {
903 // plugin author may be confused
904 int32_t tmp = plugin_min_weed_abi_version;
905 plugin_min_weed_abi_version = plugin_max_weed_abi_version;
906 plugin_max_weed_abi_version = tmp;
907 }
908 if (plugin_min_filter_api_version > plugin_max_filter_api_version) {
909 int32_t tmp = plugin_min_weed_abi_version;
910 plugin_min_weed_abi_version = plugin_max_weed_abi_version;
911 plugin_max_weed_abi_version = tmp;
912 }
913
914 // set pointers to the functions the plugin will use
915
916 wpn = weed_plant_new;
917 wpll = weed_plant_list_leaves;
918 wlne = weed_leaf_num_elements;
919 wles = weed_leaf_element_size;
920 wlst = weed_leaf_seed_type;
921 wlgf = weed_leaf_get_flags;
922 wls = weed_leaf_set;
923 wlg = weed_leaf_get;
924
925 // added for plugins in Filter API 200
926 wpf = weed_plant_free;
927 wld = weed_leaf_delete;
928
929 weedmalloc = malloc;
930 weedfree = free;
931 weedmemcpy = memcpy;
932 weedmemset = memset;
933
934 #if WEED_ABI_CHECK_VERSION(200)
935 // added for plugins in Weed ABI 200
936 weedrealloc = realloc;
937 weedmemmove = memmove;
938 weedcalloc = calloc;
939 #endif
940
941 host_info = weed_plant_new(WEED_PLANT_HOST_INFO);
942 if (!host_info) return NULL;
943
944 if (weed_set_int_value(host_info, WEED_LEAF_WEED_ABI_VERSION, host_weed_abi_version) != WEED_SUCCESS) {
945 if (host_info) weed_plant_free(host_info);
946 return NULL;
947 }
948 if (weed_set_int_value(host_info, WEED_LEAF_FILTER_API_VERSION, host_filter_api_version) != WEED_SUCCESS) {
949 if (host_info) weed_plant_free(host_info);
950 return NULL;
951 }
952
953 if (weedmalloc) {
954 if (weed_set_funcptr_value(host_info, WEED_LEAF_MALLOC_FUNC, (weed_funcptr_t)weedmalloc) != WEED_SUCCESS) {
955 if (host_info) weed_plant_free(host_info);
956 return NULL;
957 }
958 }
959 if (weedfree) {
960 if (weed_set_funcptr_value(host_info, WEED_LEAF_FREE_FUNC, (weed_funcptr_t)weedfree) != WEED_SUCCESS) {
961 if (host_info) weed_plant_free(host_info);
962 return NULL;
963 }
964 }
965 if (weedmemset) {
966 if (weed_set_funcptr_value(host_info, WEED_LEAF_MEMSET_FUNC, (weed_funcptr_t)weedmemset) != WEED_SUCCESS) {
967 if (host_info) weed_plant_free(host_info);
968 return NULL;
969 }
970 }
971 if (weedmemcpy) {
972 if (weed_set_funcptr_value(host_info, WEED_LEAF_MEMCPY_FUNC, (weed_funcptr_t)weedmemcpy) != WEED_SUCCESS) {
973 if (host_info) weed_plant_free(host_info);
974 return NULL;
975 }
976 }
977
978 #if WEED_ABI_CHECK_VERSION(200)
979 if (plugin_max_weed_abi_version >= 200) {
980 if (weedmemmove) {
981 if (weed_set_funcptr_value(host_info, WEED_LEAF_MEMMOVE_FUNC, (weed_funcptr_t)weedmemmove) != WEED_SUCCESS) {
982 if (host_info) weed_plant_free(host_info);
983 return NULL;
984 }
985 }
986 if (weedrealloc) {
987 if (weed_set_funcptr_value(host_info, WEED_LEAF_REALLOC_FUNC, (weed_funcptr_t)weedrealloc) != WEED_SUCCESS) {
988 if (host_info) weed_plant_free(host_info);
989 return NULL;
990 }
991 }
992 if (weedcalloc) {
993 if (weed_set_funcptr_value(host_info, WEED_LEAF_CALLOC_FUNC, (weed_funcptr_t)weedcalloc) != WEED_SUCCESS) {
994 if (host_info) weed_plant_free(host_info);
995 return NULL;
996 }
997 }
998 }
999
1000 #endif
1001
1002 if (wpn) {
1003 if (weed_set_funcptr_value(host_info, WEED_PLANT_NEW_FUNC, (weed_funcptr_t)wpn) != WEED_SUCCESS) {
1004 if (host_info) weed_plant_free(host_info);
1005 return NULL;
1006 }
1007 }
1008 if (wlg) {
1009 if (weed_set_funcptr_value(host_info, WEED_LEAF_GET_FUNC, (weed_funcptr_t)wlg) != WEED_SUCCESS) {
1010 if (host_info) weed_plant_free(host_info);
1011 return NULL;
1012 }
1013 }
1014 if (wls) {
1015 if (weed_set_funcptr_value(host_info, WEED_LEAF_SET_FUNC, (weed_funcptr_t)wls) != WEED_SUCCESS) {
1016 if (host_info) weed_plant_free(host_info);
1017 return NULL;
1018 }
1019 }
1020 if (wlst) {
1021 if (weed_set_funcptr_value(host_info, WEED_LEAF_SEED_TYPE_FUNC, (weed_funcptr_t)wlst) != WEED_SUCCESS) {
1022 if (host_info) weed_plant_free(host_info);
1023 return NULL;
1024 }
1025 }
1026 if (wlne) {
1027 if (weed_set_funcptr_value(host_info, WEED_LEAF_NUM_ELEMENTS_FUNC, (weed_funcptr_t)wlne) != WEED_SUCCESS) {
1028 if (host_info) weed_plant_free(host_info);
1029 return NULL;
1030 }
1031 }
1032 if (wles) {
1033 if (weed_set_funcptr_value(host_info, WEED_LEAF_ELEMENT_SIZE_FUNC, (weed_funcptr_t)wles) != WEED_SUCCESS) {
1034 if (host_info) weed_plant_free(host_info);
1035 return NULL;
1036 }
1037 }
1038 if (wpll) {
1039 if (weed_set_funcptr_value(host_info, WEED_PLANT_LIST_LEAVES_FUNC, (weed_funcptr_t)wpll) != WEED_SUCCESS) {
1040 if (host_info) weed_plant_free(host_info);
1041 return NULL;
1042 }
1043 }
1044 if (wlgf) {
1045 if (weed_set_funcptr_value(host_info, WEED_LEAF_GET_FLAGS_FUNC, (weed_funcptr_t)wlgf) != WEED_SUCCESS) {
1046 if (host_info) weed_plant_free(host_info);
1047 return NULL;
1048 }
1049 }
1050 if (plugin_max_filter_api_version >= 200) {
1051 if (wpf) {
1052 if (weed_set_funcptr_value(host_info, WEED_PLANT_FREE_FUNC, (weed_funcptr_t)wpf) != WEED_SUCCESS) {
1053 if (host_info) weed_plant_free(host_info);
1054 return NULL;
1055 }
1056 }
1057 if (wld) {
1058 if (weed_set_funcptr_value(host_info, WEED_LEAF_DELETE_FUNC, (weed_funcptr_t)wld) != WEED_SUCCESS) {
1059 if (host_info) weed_plant_free(host_info);
1060 return NULL;
1061 }
1062 }
1063 }
1064
1065 plugin_info = weed_plant_new(WEED_PLANT_PLUGIN_INFO);
1066 if (!plugin_info) {
1067 if (host_info) weed_plant_free(host_info);
1068 return NULL;
1069 }
1070
1071 if (weed_set_plantptr_value(host_info, WEED_LEAF_PLUGIN_INFO, plugin_info) != WEED_SUCCESS) {
1072 if (plugin_info) weed_plant_free(plugin_info);
1073 if (host_info) weed_plant_free(host_info);
1074 return NULL;
1075 }
1076
1077 if (weed_set_int_value(plugin_info, WEED_LEAF_MIN_WEED_ABI_VERSION, plugin_min_weed_abi_version) != WEED_SUCCESS) {
1078 if (plugin_info) weed_plant_free(plugin_info);
1079 if (host_info) weed_plant_free(host_info);
1080 return NULL;
1081 }
1082 if (weed_set_int_value(plugin_info, WEED_LEAF_MAX_WEED_ABI_VERSION, plugin_max_weed_abi_version) != WEED_SUCCESS) {
1083 if (plugin_info) weed_plant_free(plugin_info);
1084 if (host_info) weed_plant_free(host_info);
1085 return NULL;
1086 }
1087 if (weed_set_int_value(plugin_info, WEED_LEAF_MIN_FILTER_API_VERSION, plugin_min_filter_api_version) != WEED_SUCCESS) {
1088 if (plugin_info) weed_plant_free(plugin_info);
1089 if (host_info) weed_plant_free(host_info);
1090 return NULL;
1091 }
1092 if (weed_set_int_value(plugin_info, WEED_LEAF_MAX_FILTER_API_VERSION, plugin_max_filter_api_version) != WEED_SUCCESS) {
1093 if (plugin_info) weed_plant_free(plugin_info);
1094 if (host_info) weed_plant_free(host_info);
1095 return NULL;
1096 }
1097
1098 if (host_info_callback) {
1099 // if host set a callback function, we call it so it can examine and adjust the host_info plant
1100 // including setting memory functions and checking the weed and filter api values if it wishes
1101 // host can also substitute its own host_info
1102 // the host is also free to adjust or replace plant_info
1103
1104 weed_plant_t *host_host_info = host_info_callback(host_info, host_info_callback_data);
1105 if (!host_host_info) {
1106 if (plugin_info) weed_plant_free(plugin_info);
1107 return NULL;
1108 }
1109
1110 if (host_host_info != host_info) {
1111 if (host_info) weed_plant_free(host_info);
1112 host_info = host_host_info;
1113 host_set_host_info = WEED_TRUE;
1114 }
1115
1116 if (weed_plant_has_leaf(host_info, WEED_LEAF_WEED_ABI_VERSION)) {
1117 host_weed_abi_version = weed_get_int_value(host_host_info, WEED_LEAF_WEED_ABI_VERSION, &err);
1118 if (err != WEED_SUCCESS) {
1119 if (plugin_info) weed_plant_free(plugin_info);
1120 if (host_set_host_info == WEED_FALSE) if (host_info) weed_plant_free(host_info);
1121 return NULL;
1122 }
1123 }
1124 if (weed_plant_has_leaf(host_info, WEED_LEAF_FILTER_API_VERSION)) {
1125 host_filter_api_version = weed_get_int_value(host_host_info, WEED_LEAF_FILTER_API_VERSION, &err);
1126 if (err != WEED_SUCCESS) {
1127 if (plugin_info) weed_plant_free(plugin_info);
1128 if (host_set_host_info == WEED_FALSE) if (host_info) weed_plant_free(host_info);
1129 return NULL;
1130 }
1131 }
1132 }
1133
1134 if (!check_version_compat(host_weed_abi_version, plugin_min_weed_abi_version, plugin_max_weed_abi_version,
1135 host_filter_api_version, plugin_min_filter_api_version, plugin_max_filter_api_version)) {
1136 if (plugin_info) weed_plant_free(plugin_info);
1137 if (host_set_host_info == WEED_FALSE) if (host_info) weed_plant_free(host_info);
1138 return NULL;
1139 }
1140
1141 plugin_weed_abi_version = host_weed_abi_version;
1142 plugin_filter_api_version = host_filter_api_version;
1143
1144 if (host_set_host_info) {
1145 if (weed_plant_has_leaf(host_info, WEED_LEAF_PLUGIN_INFO)) {
1146 weed_plant_t *host_plugin_info = weed_get_plantptr_value(host_info, WEED_LEAF_PLUGIN_INFO, &err);
1147 if (err != WEED_SUCCESS) {
1148 if (plugin_info) weed_plant_free(plugin_info);
1149 return NULL;
1150 }
1151
1152 if (host_plugin_info != plugin_info) {
1153 if (plugin_info) weed_plant_free(plugin_info);
1154 plugin_info = NULL;
1155 }
1156 }
1157
1158 // host replaced the host_info with one of its own, check that all of the functions are present
1159 if (!weed_plant_has_leaf(host_info, WEED_LEAF_MALLOC_FUNC)) {
1160 if (weedmalloc == NULL) {
1161 if (plugin_info) weed_plant_free(plugin_info);
1162 return NULL;
1163 }
1164 if (weed_set_funcptr_value(host_info, WEED_LEAF_MALLOC_FUNC, (weed_funcptr_t)weedmalloc) != WEED_SUCCESS) {
1165 if (plugin_info) weed_plant_free(plugin_info);
1166 return NULL;
1167 }
1168 }
1169 if (!weed_plant_has_leaf(host_info, WEED_LEAF_FREE_FUNC)) {
1170 if (weedfree == NULL) {
1171 if (plugin_info) weed_plant_free(plugin_info);
1172 return NULL;
1173 }
1174 if (weed_set_funcptr_value(host_info, WEED_LEAF_FREE_FUNC, (weed_funcptr_t)weedfree) != WEED_SUCCESS) {
1175 if (plugin_info) weed_plant_free(plugin_info);
1176 return NULL;
1177 }
1178 }
1179 if (!weed_plant_has_leaf(host_info, WEED_LEAF_MEMSET_FUNC)) {
1180 if (weedmemset == NULL) {
1181 if (plugin_info) weed_plant_free(plugin_info);
1182 return NULL;
1183 }
1184 if (weed_set_funcptr_value(host_info, WEED_LEAF_MEMSET_FUNC, (weed_funcptr_t)weedmemset) != WEED_SUCCESS) {
1185 if (plugin_info) weed_plant_free(plugin_info);
1186 return NULL;
1187 }
1188 }
1189 if (!weed_plant_has_leaf(host_info, WEED_LEAF_MEMCPY_FUNC)) {
1190 if (weedmemcpy == NULL) {
1191 if (plugin_info) weed_plant_free(plugin_info);
1192 return NULL;
1193 }
1194 if (weed_set_funcptr_value(host_info, WEED_LEAF_MEMCPY_FUNC, (weed_funcptr_t)weedmemcpy) != WEED_SUCCESS) {
1195 if (plugin_info) weed_plant_free(plugin_info);
1196 return NULL;
1197 }
1198 }
1199
1200 #if WEED_ABI_CHECK_VERSION(200)
1201 if (plugin_weed_abi_version >= 200) {
1202 if (!weed_plant_has_leaf(host_info, WEED_LEAF_MEMMOVE_FUNC)) {
1203 if (weedmemmove == NULL) {
1204 if (plugin_info) weed_plant_free(plugin_info);
1205 return NULL;
1206 }
1207 if (weed_set_funcptr_value(host_info, WEED_LEAF_MEMMOVE_FUNC, (weed_funcptr_t)weedmemmove) != WEED_SUCCESS) {
1208 if (plugin_info) weed_plant_free(plugin_info);
1209 return NULL;
1210 }
1211 }
1212 if (!weed_plant_has_leaf(host_info, WEED_LEAF_REALLOC_FUNC)) {
1213 if (weedrealloc == NULL) {
1214 if (plugin_info) weed_plant_free(plugin_info);
1215 return NULL;
1216 }
1217 if (weed_set_funcptr_value(host_info, WEED_LEAF_REALLOC_FUNC, (weed_funcptr_t)weedrealloc) != WEED_SUCCESS) {
1218 if (plugin_info) weed_plant_free(plugin_info);
1219 return NULL;
1220 }
1221 }
1222 if (!weed_plant_has_leaf(host_info, WEED_LEAF_CALLOC_FUNC)) {
1223 if (weedcalloc == NULL) {
1224 if (plugin_info) weed_plant_free(plugin_info);
1225 return NULL;
1226 }
1227 if (weed_set_funcptr_value(host_info, WEED_LEAF_CALLOC_FUNC, (weed_funcptr_t)weedcalloc) != WEED_SUCCESS) {
1228 if (plugin_info) weed_plant_free(plugin_info);
1229 return NULL;
1230 }
1231 }
1232 }
1233
1234 #endif
1235
1236 if (!weed_plant_has_leaf(host_info, WEED_PLANT_NEW_FUNC)) {
1237 if (wpn == NULL) {
1238 if (plugin_info) weed_plant_free(plugin_info);
1239 return NULL;
1240 }
1241 if (weed_set_funcptr_value(host_info, WEED_PLANT_NEW_FUNC, (weed_funcptr_t)wpn) != WEED_SUCCESS) {
1242 if (plugin_info) weed_plant_free(plugin_info);
1243 return NULL;
1244 }
1245 }
1246 if (!weed_plant_has_leaf(host_info, WEED_LEAF_GET_FUNC)) {
1247 if (wlg == NULL) {
1248 if (plugin_info) weed_plant_free(plugin_info);
1249 return NULL;
1250 }
1251 if (weed_set_funcptr_value(host_info, WEED_LEAF_GET_FUNC, (weed_funcptr_t)wlg) != WEED_SUCCESS) {
1252 if (plugin_info) weed_plant_free(plugin_info);
1253 return NULL;
1254 }
1255 }
1256 if (!weed_plant_has_leaf(host_info, WEED_LEAF_SET_FUNC)) {
1257 if (wls == NULL) {
1258 if (plugin_info) weed_plant_free(plugin_info);
1259 return NULL;
1260 }
1261 if (weed_set_funcptr_value(host_info, WEED_LEAF_SET_FUNC, (weed_funcptr_t)wls) != WEED_SUCCESS) {
1262 if (plugin_info) weed_plant_free(plugin_info);
1263 return NULL;
1264 }
1265 }
1266 if (!weed_plant_has_leaf(host_info, WEED_LEAF_SEED_TYPE_FUNC)) {
1267 if (wlst == NULL) {
1268 if (plugin_info) weed_plant_free(plugin_info);
1269 return NULL;
1270 }
1271 if (weed_set_funcptr_value(host_info, WEED_LEAF_SEED_TYPE_FUNC, (weed_funcptr_t)wlst) != WEED_SUCCESS) {
1272 if (plugin_info) weed_plant_free(plugin_info);
1273 return NULL;
1274 }
1275 }
1276 if (!weed_plant_has_leaf(host_info, WEED_LEAF_NUM_ELEMENTS_FUNC)) {
1277 if (wlne == NULL) {
1278 if (plugin_info) weed_plant_free(plugin_info);
1279 return NULL;
1280 }
1281 if (weed_set_funcptr_value(host_info, WEED_LEAF_NUM_ELEMENTS_FUNC, (weed_funcptr_t)wlne) != WEED_SUCCESS) {
1282 if (plugin_info) weed_plant_free(plugin_info);
1283 return NULL;
1284 }
1285 }
1286 if (!weed_plant_has_leaf(host_info, WEED_LEAF_ELEMENT_SIZE_FUNC)) {
1287 if (wles == NULL) {
1288 if (plugin_info) weed_plant_free(plugin_info);
1289 return NULL;
1290 }
1291 if (weed_set_funcptr_value(host_info, WEED_LEAF_ELEMENT_SIZE_FUNC, (weed_funcptr_t)wles) != WEED_SUCCESS) {
1292 if (plugin_info) weed_plant_free(plugin_info);
1293 return NULL;
1294 }
1295 }
1296 if (!weed_plant_has_leaf(host_info, WEED_PLANT_LIST_LEAVES_FUNC)) {
1297 if (wpll == NULL) {
1298 if (plugin_info) weed_plant_free(plugin_info);
1299 return NULL;
1300 }
1301 if (weed_set_funcptr_value(host_info, WEED_PLANT_LIST_LEAVES_FUNC, (weed_funcptr_t)wpll) != WEED_SUCCESS) {
1302 if (plugin_info) weed_plant_free(plugin_info);
1303 return NULL;
1304 }
1305 }
1306 if (!weed_plant_has_leaf(host_info, WEED_LEAF_GET_FLAGS_FUNC)) {
1307 if (wlgf == NULL) {
1308 if (plugin_info) weed_plant_free(plugin_info);
1309 return NULL;
1310 }
1311 if (weed_set_funcptr_value(host_info, WEED_LEAF_GET_FLAGS_FUNC, (weed_funcptr_t)wlgf) != WEED_SUCCESS) {
1312 if (plugin_info) weed_plant_free(plugin_info);
1313 return NULL;
1314 }
1315 }
1316 }
1317
1318 if (plugin_filter_api_version >= 200) {
1319 if (!weed_plant_has_leaf(host_info, WEED_PLANT_FREE_FUNC)) {
1320 if (wpf == NULL) {
1321 if (plugin_info) weed_plant_free(plugin_info);
1322 return NULL;
1323 }
1324 if (weed_set_funcptr_value(host_info, WEED_PLANT_FREE_FUNC, (weed_funcptr_t)wpf) != WEED_SUCCESS) {
1325 if (plugin_info) weed_plant_free(plugin_info);
1326 return NULL;
1327 }
1328 }
1329 if (!weed_plant_has_leaf(host_info, WEED_LEAF_DELETE_FUNC)) {
1330 if (wld == NULL) {
1331 if (plugin_info) weed_plant_free(plugin_info);
1332 return NULL;
1333 }
1334 if (weed_set_funcptr_value(host_info, WEED_LEAF_DELETE_FUNC, (weed_funcptr_t)wld) != WEED_SUCCESS) {
1335 if (plugin_info) weed_plant_free(plugin_info);
1336 return NULL;
1337 }
1338 }
1339 }
1340
1341 #if WEED_ABI_CHECK_VERSION(200)
1342 // readjust the ABI depending on the weed_abi_version selected by the host
1343
1344 if (plugin_weed_abi_version < 200) {
1345 // added in ABI 200, so remove them for lower versions
1346 if (weed_plant_has_leaf(host_info, WEED_LEAF_REALLOC_FUNC)) {
1347 err = weed_leaf_delete(host_info, WEED_LEAF_REALLOC_FUNC);
1348 if (err != WEED_SUCCESS && err != WEED_ERROR_UNDELETABLE) {
1349 if (plugin_info) weed_plant_free(plugin_info);
1350 if (host_set_host_info == WEED_FALSE) if (host_info) weed_plant_free(host_info);
1351 return NULL;
1352 }
1353 }
1354 weedrealloc = NULL;
1355 if (weed_plant_has_leaf(host_info, WEED_LEAF_CALLOC_FUNC)) {
1356 err = weed_leaf_delete(host_info, WEED_LEAF_CALLOC_FUNC);
1357 if (err != WEED_SUCCESS && err != WEED_ERROR_UNDELETABLE) {
1358 if (plugin_info) weed_plant_free(plugin_info);
1359 if (host_set_host_info == WEED_FALSE) if (host_info) weed_plant_free(host_info);
1360 return NULL;
1361 }
1362 }
1363 weedcalloc = NULL;
1364 if (weed_plant_has_leaf(host_info, WEED_LEAF_MEMMOVE_FUNC)) {
1365 err = weed_leaf_delete(host_info, WEED_LEAF_MEMMOVE_FUNC);
1366 if (err != WEED_SUCCESS && err != WEED_ERROR_UNDELETABLE) {
1367 if (plugin_info) weed_plant_free(plugin_info);
1368 if (host_set_host_info == WEED_FALSE) if (host_info) weed_plant_free(host_info);
1369 return NULL;
1370 }
1371 }
1372 weedmemmove = NULL;
1373 }
1374 #endif
1375
1376 if (plugin_filter_api_version < 200) {
1377 if (weed_plant_has_leaf(host_info, WEED_PLANT_FREE_FUNC)) {
1378 err = weed_leaf_delete(host_info, WEED_PLANT_FREE_FUNC);
1379 if (err != WEED_SUCCESS && err != WEED_ERROR_UNDELETABLE) {
1380 if (plugin_info) weed_plant_free(plugin_info);
1381 if (host_set_host_info == WEED_FALSE) if (host_info) weed_plant_free(host_info);
1382 return NULL;
1383 }
1384 }
1385 wpf = NULL;
1386 if (weed_plant_has_leaf(host_info, WEED_LEAF_DELETE_FUNC)) {
1387 err = weed_leaf_delete(host_info, WEED_LEAF_DELETE_FUNC);
1388 if (err != WEED_SUCCESS && err != WEED_ERROR_UNDELETABLE) {
1389 if (plugin_info) weed_plant_free(plugin_info);
1390 if (host_set_host_info == WEED_FALSE) if (host_info) weed_plant_free(host_info);
1391 return NULL;
1392 }
1393 }
1394 wld = NULL;
1395 }
1396 return host_info;
1397 }
1398
1399
1400
1401