WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / hb_dict.c
blob1eb42b05938226b788a2994fef12d0fdf444f9ba
1 /* hb_dict.c
3 Copyright (c) 2003-2015 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
10 #include <stdio.h>
11 #include "hb.h"
12 #include "hb_dict.h"
14 hb_value_type_t hb_value_type(const hb_value_t *value)
16 if (value == NULL)
17 return HB_VALUE_TYPE_NULL;
18 hb_value_type_t type = json_typeof(value);
19 if (type == JSON_TRUE || type == JSON_FALSE)
20 return HB_VALUE_TYPE_BOOL;
21 return type;
24 int hb_value_is_number(const hb_value_t *value)
26 return json_is_number(value);
29 hb_value_t * hb_value_dup(const hb_value_t *value)
31 if (value == NULL) return NULL;
32 return json_deep_copy(value);
35 hb_value_t* hb_value_incref(hb_value_t *value)
37 return json_incref(value);
40 void hb_value_decref(hb_value_t *value)
42 if (value == NULL) return;
43 json_decref(value);
46 void hb_value_free(hb_value_t **_value)
48 hb_value_decref(*_value);
49 *_value = NULL;
52 hb_value_t * hb_value_string(const char * value)
54 // json_string does not create a value for NULL strings.
55 // So create JSON_NULL in this case
56 if (value == NULL)
57 return json_null();
58 return json_string(value);
61 hb_value_t * hb_value_int(json_int_t value)
63 return json_integer(value);
66 hb_value_t * hb_value_double(double value)
68 return json_real(value);
71 hb_value_t * hb_value_bool(int value)
73 return json_boolean(value);
76 hb_value_t * hb_value_json(const char *json)
78 json_error_t error;
79 hb_value_t *val = json_loads(json, 0, &error);
80 if (val == NULL)
82 hb_error("hb_value_json: Failed, error %s", error.text);
84 return val;
87 hb_value_t * hb_value_read_json(const char *path)
89 json_error_t error;
90 hb_value_t *val = json_load_file(path, 0, &error);
91 return val;
94 static hb_value_t* xform_null(hb_value_type_t type)
96 switch (type)
98 default:
99 case HB_VALUE_TYPE_NULL:
100 return json_null();
101 case HB_VALUE_TYPE_BOOL:
102 return json_false();
103 case HB_VALUE_TYPE_INT:
104 return json_integer(0);
105 case HB_VALUE_TYPE_DOUBLE:
106 return json_real(0.0);
107 case HB_VALUE_TYPE_STRING:
108 return json_null();
112 static hb_value_t* xform_bool(const hb_value_t *value, hb_value_type_t type)
114 json_int_t b = json_is_true(value);
115 switch (type)
117 default:
118 case HB_VALUE_TYPE_NULL:
119 return json_null();
120 case HB_VALUE_TYPE_BOOL:
121 return json_boolean(b);
122 case HB_VALUE_TYPE_INT:
123 return json_integer(b);
124 case HB_VALUE_TYPE_DOUBLE:
125 return json_real(b);
126 case HB_VALUE_TYPE_STRING:
128 char *s = hb_strdup_printf("%"JSON_INTEGER_FORMAT, b);
129 hb_value_t *v = json_string(s);
130 free(s);
131 return v;
136 static hb_value_t* xform_int(const hb_value_t *value, hb_value_type_t type)
138 json_int_t i = json_integer_value(value);
139 switch (type)
141 default:
142 case HB_VALUE_TYPE_NULL:
143 return json_null();
144 case HB_VALUE_TYPE_BOOL:
145 return json_boolean(i);
146 case HB_VALUE_TYPE_INT:
147 return json_integer(i);
148 case HB_VALUE_TYPE_DOUBLE:
149 return json_real(i);
150 case HB_VALUE_TYPE_STRING:
152 char *s = hb_strdup_printf("%"JSON_INTEGER_FORMAT, i);
153 hb_value_t *v = json_string(s);
154 free(s);
155 return v;
160 static hb_value_t* xform_double(const hb_value_t *value, hb_value_type_t type)
162 double d = json_real_value(value);
163 switch (type)
165 default:
166 case HB_VALUE_TYPE_NULL:
167 return json_null();
168 case HB_VALUE_TYPE_BOOL:
169 return json_boolean((int)d != 0);
170 case HB_VALUE_TYPE_INT:
171 return json_integer(d);
172 case HB_VALUE_TYPE_DOUBLE:
173 return json_real(d);
174 case HB_VALUE_TYPE_STRING:
176 char *s = hb_strdup_printf("%g", d);
177 hb_value_t *v = json_string(s);
178 free(s);
179 return v;
184 static hb_value_t* xform_string(const hb_value_t *value, hb_value_type_t type)
186 const char *s = json_string_value(value);
187 switch (type)
189 default:
190 case HB_VALUE_TYPE_NULL:
192 return json_null();
194 case HB_VALUE_TYPE_BOOL:
196 if (!strcasecmp(s, "true") ||
197 !strcasecmp(s, "yes") ||
198 !strcasecmp(s, "1"))
200 return json_true();
202 return json_false();
204 case HB_VALUE_TYPE_INT:
206 return json_integer(strtoll(s, NULL, 0));
208 case HB_VALUE_TYPE_DOUBLE:
210 return json_real(strtod(s, NULL));
212 case HB_VALUE_TYPE_STRING:
214 return json_string(s);
219 static hb_value_t* xform_array(const hb_value_t *value, hb_value_type_t type)
221 hb_value_t *first = NULL;
222 int count = hb_value_array_len(value);
224 if (count > 0)
225 first = hb_value_array_get(value, 0);
226 switch (type)
228 default:
229 case HB_VALUE_TYPE_NULL:
230 case HB_VALUE_TYPE_BOOL:
231 case HB_VALUE_TYPE_INT:
232 case HB_VALUE_TYPE_DOUBLE:
233 return hb_value_xform(first, type);
234 case HB_VALUE_TYPE_STRING:
236 char *r = strdup("");
237 int ii;
238 for (ii = 0; ii < count; ii++)
240 hb_value_t *v = hb_value_array_get(value, ii);
241 hb_value_t *x = hb_value_xform(v, type);
242 const char *s = hb_value_get_string(x);
243 if (s != NULL)
245 char *tmp = r;
246 r = hb_strdup_printf("%s%s,", tmp, s);
247 free(tmp);
249 hb_value_free(&x);
251 int len = strlen(r);
252 hb_value_t *v;
253 if (len > 0)
255 // Removing trailing ','
256 r[len - 1] = 0;
257 v = json_string(r);
259 else
261 free(r);
262 r = NULL;
263 v = json_null();
265 free(r);
266 return v;
271 static hb_value_t* xform_dict(const hb_value_t *dict, hb_value_type_t type)
273 hb_value_t *first = NULL;
274 hb_dict_iter_t iter = hb_dict_iter_init(dict);
276 if (iter != HB_DICT_ITER_DONE)
277 first = hb_dict_iter_value(iter);
279 switch (type)
281 default:
282 case HB_VALUE_TYPE_NULL:
283 case HB_VALUE_TYPE_BOOL:
284 case HB_VALUE_TYPE_INT:
285 case HB_VALUE_TYPE_DOUBLE:
286 return hb_value_xform(first, type);
287 case HB_VALUE_TYPE_STRING:
289 char *r = strdup("");
290 hb_dict_iter_t iter;
291 for (iter = hb_dict_iter_init(dict);
292 iter != HB_DICT_ITER_DONE;
293 iter = hb_dict_iter_next(dict, iter))
295 const char *k = hb_dict_iter_key(iter);
296 hb_value_t *v = hb_dict_iter_value(iter);
297 hb_value_t *x = hb_value_xform(v, type);
298 const char *s = hb_value_get_string(x);
300 char *tmp = r;
301 r = hb_strdup_printf("%s%s%s%s:",
304 s ? "=" : "",
305 s ? s : "");
306 free(tmp);
307 hb_value_free(&x);
309 int len = strlen(r);
310 hb_value_t *v;
311 if (len > 0)
313 // Removing trailing ':'
314 r[len - 1] = 0;
315 v = json_string(r);
317 else
319 free(r);
320 r = NULL;
321 v = json_null();
323 free(r);
324 return v;
329 hb_value_t* hb_value_xform(const hb_value_t *value, hb_value_type_t type)
331 hb_value_type_t src_type = hb_value_type(value);
332 if (src_type == type && value != NULL)
334 json_incref((hb_value_t*)value);
335 return (hb_value_t*)value;
337 switch (src_type)
339 default:
340 case HB_VALUE_TYPE_NULL:
342 return xform_null(type);
344 case HB_VALUE_TYPE_BOOL:
346 return xform_bool(value, type);
348 case HB_VALUE_TYPE_INT:
350 return xform_int(value, type);
352 case HB_VALUE_TYPE_DOUBLE:
354 return xform_double(value, type);
356 case HB_VALUE_TYPE_STRING:
358 return xform_string(value, type);
360 case HB_VALUE_TYPE_ARRAY:
362 return xform_array(value, type);
364 case HB_VALUE_TYPE_DICT:
366 return xform_dict(value, type);
371 const char * hb_value_get_string(const hb_value_t *value)
373 if (hb_value_type(value) != HB_VALUE_TYPE_STRING) return NULL;
374 return json_string_value(value);
377 json_int_t hb_value_get_int(const hb_value_t *value)
379 json_int_t result;
380 hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_INT);
381 result = json_integer_value(v);
382 json_decref(v);
383 return result;
386 double hb_value_get_double(const hb_value_t *value)
388 double result;
389 hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_DOUBLE);
390 result = json_real_value(v);
391 json_decref(v);
392 return result;
395 int hb_value_get_bool(const hb_value_t *value)
397 int result;
398 hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_BOOL);
399 result = json_is_true(v);
400 json_decref(v);
401 return result;
404 char*
405 hb_value_get_string_xform(const hb_value_t *value)
407 char *result;
408 if (hb_value_type(value) == HB_VALUE_TYPE_NULL)
409 return NULL;
410 hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_STRING);
411 if (hb_value_type(v) == HB_VALUE_TYPE_NULL)
412 return NULL;
413 result = strdup(json_string_value(v));
414 json_decref(v);
415 return result;
418 char * hb_value_get_json(const hb_value_t *value)
420 return json_dumps(value, JSON_INDENT(4) | JSON_SORT_KEYS);
423 int hb_value_write_file_json(hb_value_t *value, FILE *file)
425 return json_dumpf(value, file, JSON_INDENT(4) | JSON_SORT_KEYS);
428 int hb_value_write_json(hb_value_t *value, const char *path)
430 return json_dump_file(value, path, JSON_INDENT(4) | JSON_SORT_KEYS);
433 void hb_dict_free(hb_dict_t **_dict)
435 hb_value_free(_dict);
438 hb_dict_t * hb_dict_init()
440 return json_object();
443 void hb_dict_set(hb_dict_t * dict, const char *key, hb_value_t *value)
445 json_object_set_new(dict, key, value);
448 int hb_dict_remove(hb_dict_t * dict, const char * key)
450 return json_object_del(dict, key) == 0;
453 hb_value_t * hb_dict_get(const hb_dict_t * dict, const char * key)
455 return json_object_get(dict, key);
458 hb_dict_iter_t hb_dict_iter_init(const hb_dict_t *dict)
460 if (dict == NULL)
461 return HB_DICT_ITER_DONE;
462 return json_object_iter((hb_dict_t*)dict);
465 hb_dict_iter_t hb_dict_iter_next(const hb_dict_t *dict, hb_dict_iter_t iter)
467 return json_object_iter_next((hb_dict_t*)dict, iter);
470 const char * hb_dict_iter_key(const hb_dict_iter_t iter)
472 return json_object_iter_key(iter);
475 hb_value_t * hb_dict_iter_value(const hb_dict_iter_t iter)
477 return json_object_iter_value(iter);
481 hb_dict_iter_next_ex(const hb_dict_t *dict, hb_dict_iter_t *iter,
482 const char **key, hb_value_t **val)
484 if (*iter == NULL)
485 return 0;
486 if (key != NULL)
487 *key = json_object_iter_key(*iter);
488 if (val != NULL)
489 *val = json_object_iter_value(*iter);
490 *iter = json_object_iter_next((hb_dict_t*)dict, *iter);
491 return 1;
494 hb_value_array_t*
495 hb_value_array_init()
497 return json_array();
500 void
501 hb_value_array_clear(hb_value_array_t *array)
503 json_array_clear(array);
506 hb_value_t*
507 hb_value_array_get(const hb_value_array_t *array, int index)
509 return json_array_get(array, index);
512 void
513 hb_value_array_set(hb_value_array_t *array, int index, hb_value_t *value)
515 if (index < 0 || index >= json_array_size(array))
517 hb_error("hb_value_array_set: invalid index %d size %zu",
518 index, json_array_size(array));
519 return;
521 json_array_set_new(array, index, value);
524 void
525 hb_value_array_insert(hb_value_array_t *array, int index, hb_value_t *value)
527 json_array_insert_new(array, index, value);
530 void
531 hb_value_array_append(hb_value_array_t *array, hb_value_t *value)
533 json_array_append_new(array, value);
536 void
537 hb_value_array_remove(hb_value_array_t *array, int index)
539 json_array_remove(array, index);
542 void
543 hb_value_array_copy(hb_value_array_t *dst,
544 const hb_value_array_t *src, int count)
546 size_t len;
547 int ii;
549 // empty the first array if it is not already empty
550 json_array_clear(dst);
552 len = hb_value_array_len(src);
553 count = MIN(count, len);
554 for (ii = 0; ii < count; ii++)
555 hb_value_array_append(dst, hb_value_dup(hb_value_array_get(src, ii)));
558 size_t
559 hb_value_array_len(const hb_value_array_t *array)
561 return json_array_size(array);
564 hb_dict_t * hb_encopts_to_dict(const char * encopts, int encoder)
566 hb_dict_t * dict = NULL;
568 if (encopts && *encopts)
570 char *cur_opt, *opts_start, *value;
571 const char *name;
572 dict = hb_dict_init();
573 if( !dict )
574 return NULL;
575 cur_opt = opts_start = strdup(encopts);
576 if (opts_start)
578 while (*cur_opt)
580 name = cur_opt;
581 cur_opt += strcspn(cur_opt, ":");
582 if (*cur_opt)
584 *cur_opt = 0;
585 cur_opt++;
587 value = strchr(name, '=');
588 if (value)
590 *value = 0;
591 value++;
593 // x264 has multiple names for some options
594 if (encoder == HB_VCODEC_X264)
595 name = hb_x264_encopt_name(name);
596 #ifdef USE_X265
597 // x265 has multiple names for some options
598 if (encoder == HB_VCODEC_X265)
599 name = hb_x265_encopt_name(name);
600 #endif
601 if (name != NULL)
603 hb_dict_set(dict, name, hb_value_string(value));
607 free(opts_start);
609 return dict;
612 char * hb_dict_to_encopts(const hb_dict_t * dict)
614 return hb_value_get_string_xform(dict);