1 /* hb_dict.c
2
3 Copyright (c) 2003-2021 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 */
9
10 #include <ctype.h>
11 #include <stdio.h>
12 #include "handbrake/handbrake.h"
13 #include "handbrake/hb_dict.h"
14
hb_value_type(const hb_value_t * value)15 hb_value_type_t hb_value_type(const hb_value_t *value)
16 {
17 if (value == NULL)
18 return HB_VALUE_TYPE_NULL;
19 hb_value_type_t type = json_typeof(value);
20 if (type == JSON_TRUE || type == JSON_FALSE)
21 return HB_VALUE_TYPE_BOOL;
22 return type;
23 }
24
hb_value_is_number(const hb_value_t * value)25 int hb_value_is_number(const hb_value_t *value)
26 {
27 return json_is_number(value);
28 }
29
hb_value_dup(const hb_value_t * value)30 hb_value_t * hb_value_dup(const hb_value_t *value)
31 {
32 if (value == NULL) return NULL;
33 return json_deep_copy(value);
34 }
35
hb_value_incref(hb_value_t * value)36 hb_value_t* hb_value_incref(hb_value_t *value)
37 {
38 return json_incref(value);
39 }
40
hb_value_decref(hb_value_t * value)41 void hb_value_decref(hb_value_t *value)
42 {
43 if (value == NULL) return;
44 json_decref(value);
45 }
46
hb_value_free(hb_value_t ** _value)47 void hb_value_free(hb_value_t **_value)
48 {
49 hb_value_decref(*_value);
50 *_value = NULL;
51 }
52
hb_value_null()53 hb_value_t * hb_value_null()
54 {
55 return json_null();
56 }
57
hb_value_string(const char * value)58 hb_value_t * hb_value_string(const char * value)
59 {
60 // json_string does not create a value for NULL strings.
61 // So create JSON_NULL in this case
62 if (value == NULL)
63 return json_null();
64 return json_string(value);
65 }
66
hb_value_int(json_int_t value)67 hb_value_t * hb_value_int(json_int_t value)
68 {
69 return json_integer(value);
70 }
71
hb_value_double(double value)72 hb_value_t * hb_value_double(double value)
73 {
74 return json_real(value);
75 }
76
hb_value_bool(int value)77 hb_value_t * hb_value_bool(int value)
78 {
79 return json_boolean(value);
80 }
81
hb_value_json(const char * json)82 hb_value_t * hb_value_json(const char *json)
83 {
84 json_error_t error;
85 hb_value_t *val = json_loads(json, 0, &error);
86 if (val == NULL)
87 {
88 hb_error("hb_value_json: Failed, error %s", error.text);
89 }
90 return val;
91 }
92
hb_value_read_json(const char * path)93 hb_value_t * hb_value_read_json(const char *path)
94 {
95 FILE * fp;
96 json_error_t error;
97
98 fp = hb_fopen(path, "r");
99 if (fp == NULL)
100 {
101 return NULL;
102 }
103 hb_value_t *val = json_loadf(fp, 0, &error);
104 fclose(fp);
105 return val;
106 }
107
xform_null(hb_value_type_t type)108 static hb_value_t* xform_null(hb_value_type_t type)
109 {
110 switch (type)
111 {
112 default:
113 case HB_VALUE_TYPE_NULL:
114 return json_null();
115 case HB_VALUE_TYPE_BOOL:
116 return json_false();
117 case HB_VALUE_TYPE_INT:
118 return json_integer(0);
119 case HB_VALUE_TYPE_DOUBLE:
120 return json_real(0.0);
121 case HB_VALUE_TYPE_STRING:
122 return json_string("");
123 }
124 }
125
xform_bool(const hb_value_t * value,hb_value_type_t type)126 static hb_value_t* xform_bool(const hb_value_t *value, hb_value_type_t type)
127 {
128 json_int_t b = json_is_true(value);
129 switch (type)
130 {
131 default:
132 case HB_VALUE_TYPE_NULL:
133 return json_null();
134 case HB_VALUE_TYPE_BOOL:
135 return json_boolean(b);
136 case HB_VALUE_TYPE_INT:
137 return json_integer(b);
138 case HB_VALUE_TYPE_DOUBLE:
139 return json_real(b);
140 case HB_VALUE_TYPE_STRING:
141 {
142 char *s = hb_strdup_printf("%"JSON_INTEGER_FORMAT, b);
143 hb_value_t *v = json_string(s);
144 free(s);
145 return v;
146 }
147 }
148 }
149
xform_int(const hb_value_t * value,hb_value_type_t type)150 static hb_value_t* xform_int(const hb_value_t *value, hb_value_type_t type)
151 {
152 json_int_t i = json_integer_value(value);
153 switch (type)
154 {
155 default:
156 case HB_VALUE_TYPE_NULL:
157 return json_null();
158 case HB_VALUE_TYPE_BOOL:
159 return json_boolean(i);
160 case HB_VALUE_TYPE_INT:
161 return json_integer(i);
162 case HB_VALUE_TYPE_DOUBLE:
163 return json_real(i);
164 case HB_VALUE_TYPE_STRING:
165 {
166 char *s = hb_strdup_printf("%"JSON_INTEGER_FORMAT, i);
167 hb_value_t *v = json_string(s);
168 free(s);
169 return v;
170 }
171 }
172 }
173
xform_double(const hb_value_t * value,hb_value_type_t type)174 static hb_value_t* xform_double(const hb_value_t *value, hb_value_type_t type)
175 {
176 double d = json_real_value(value);
177 switch (type)
178 {
179 default:
180 case HB_VALUE_TYPE_NULL:
181 return json_null();
182 case HB_VALUE_TYPE_BOOL:
183 return json_boolean((int)d != 0);
184 case HB_VALUE_TYPE_INT:
185 return json_integer(d);
186 case HB_VALUE_TYPE_DOUBLE:
187 return json_real(d);
188 case HB_VALUE_TYPE_STRING:
189 {
190 char *s = hb_strdup_printf("%g", d);
191 hb_value_t *v = json_string(s);
192 free(s);
193 return v;
194 }
195 }
196 }
197
xform_string(const hb_value_t * value,hb_value_type_t type)198 static hb_value_t* xform_string(const hb_value_t *value, hb_value_type_t type)
199 {
200 const char *s = json_string_value(value);
201 switch (type)
202 {
203 default:
204 case HB_VALUE_TYPE_NULL:
205 {
206 return json_null();
207 }
208 case HB_VALUE_TYPE_BOOL:
209 {
210 if (!strcasecmp(s, "true") ||
211 !strcasecmp(s, "yes") ||
212 !strcasecmp(s, "1"))
213 {
214 return json_true();
215 }
216 return json_false();
217 }
218 case HB_VALUE_TYPE_INT:
219 {
220 return json_integer(strtoll(s, NULL, 0));
221 }
222 case HB_VALUE_TYPE_DOUBLE:
223 {
224 return json_real(strtod(s, NULL));
225 }
226 case HB_VALUE_TYPE_STRING:
227 {
228 return json_string(s);
229 }
230 }
231 }
232
xform_array(const hb_value_t * value,hb_value_type_t type)233 static hb_value_t* xform_array(const hb_value_t *value, hb_value_type_t type)
234 {
235 hb_value_t *first = NULL;
236 int count = hb_value_array_len(value);
237
238 if (count > 0)
239 first = hb_value_array_get(value, 0);
240 switch (type)
241 {
242 default:
243 case HB_VALUE_TYPE_NULL:
244 case HB_VALUE_TYPE_BOOL:
245 case HB_VALUE_TYPE_INT:
246 case HB_VALUE_TYPE_DOUBLE:
247 return hb_value_xform(first, type);
248 case HB_VALUE_TYPE_STRING:
249 {
250 char *r = strdup("");
251 int ii;
252 for (ii = 0; ii < count; ii++)
253 {
254 hb_value_t *v = hb_value_array_get(value, ii);
255 hb_value_t *x = hb_value_xform(v, type);
256 const char *s = hb_value_get_string(x);
257 if (s != NULL)
258 {
259 char *tmp = r;
260 r = hb_strdup_printf("%s%s,", tmp, s);
261 free(tmp);
262 }
263 hb_value_free(&x);
264 }
265 int len = strlen(r);
266 hb_value_t *v;
267 if (len > 0)
268 {
269 // Removing trailing ','
270 r[len - 1] = 0;
271 v = json_string(r);
272 }
273 else
274 {
275 free(r);
276 r = NULL;
277 v = json_null();
278 }
279 free(r);
280 return v;
281 }
282 }
283 }
284
xform_dict(const hb_value_t * dict,hb_value_type_t type)285 static hb_value_t* xform_dict(const hb_value_t *dict, hb_value_type_t type)
286 {
287 hb_value_t *first = NULL;
288 hb_dict_iter_t iter = hb_dict_iter_init(dict);
289
290 if (iter != HB_DICT_ITER_DONE)
291 first = hb_dict_iter_value(iter);
292
293 switch (type)
294 {
295 default:
296 case HB_VALUE_TYPE_NULL:
297 case HB_VALUE_TYPE_BOOL:
298 case HB_VALUE_TYPE_INT:
299 case HB_VALUE_TYPE_DOUBLE:
300 return hb_value_xform(first, type);
301 case HB_VALUE_TYPE_STRING:
302 {
303 char *r = strdup("");
304 hb_dict_iter_t iter;
305 for (iter = hb_dict_iter_init(dict);
306 iter != HB_DICT_ITER_DONE;
307 iter = hb_dict_iter_next(dict, iter))
308 {
309 const char *k = hb_dict_iter_key(iter);
310 hb_value_t *v = hb_dict_iter_value(iter);
311 hb_value_t *x = hb_value_xform(v, type);
312 const char *s = hb_value_get_string(x);
313
314 char *tmp = r;
315 r = hb_strdup_printf("%s%s%s%s:",
316 r,
317 k,
318 s ? "=" : "",
319 s ? s : "");
320 free(tmp);
321 hb_value_free(&x);
322 }
323 int len = strlen(r);
324 hb_value_t *v;
325 if (len > 0)
326 {
327 // Removing trailing ':'
328 r[len - 1] = 0;
329 v = json_string(r);
330 }
331 else
332 {
333 free(r);
334 r = NULL;
335 v = json_null();
336 }
337 free(r);
338 return v;
339 }
340 }
341 }
342
hb_value_xform(const hb_value_t * value,hb_value_type_t type)343 hb_value_t* hb_value_xform(const hb_value_t *value, hb_value_type_t type)
344 {
345 hb_value_type_t src_type = hb_value_type(value);
346 if (src_type == type && value != NULL)
347 {
348 json_incref((hb_value_t*)value);
349 return (hb_value_t*)value;
350 }
351 switch (src_type)
352 {
353 default:
354 case HB_VALUE_TYPE_NULL:
355 {
356 return xform_null(type);
357 }
358 case HB_VALUE_TYPE_BOOL:
359 {
360 return xform_bool(value, type);
361 }
362 case HB_VALUE_TYPE_INT:
363 {
364 return xform_int(value, type);
365 }
366 case HB_VALUE_TYPE_DOUBLE:
367 {
368 return xform_double(value, type);
369 }
370 case HB_VALUE_TYPE_STRING:
371 {
372 return xform_string(value, type);
373 }
374 case HB_VALUE_TYPE_ARRAY:
375 {
376 return xform_array(value, type);
377 }
378 case HB_VALUE_TYPE_DICT:
379 {
380 return xform_dict(value, type);
381 }
382 }
383 }
384
hb_value_get_string(const hb_value_t * value)385 const char * hb_value_get_string(const hb_value_t *value)
386 {
387 if (hb_value_type(value) != HB_VALUE_TYPE_STRING) return NULL;
388 return json_string_value(value);
389 }
390
hb_value_get_int(const hb_value_t * value)391 json_int_t hb_value_get_int(const hb_value_t *value)
392 {
393 json_int_t result;
394 hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_INT);
395 result = json_integer_value(v);
396 json_decref(v);
397 return result;
398 }
399
hb_value_get_double(const hb_value_t * value)400 double hb_value_get_double(const hb_value_t *value)
401 {
402 double result;
403 hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_DOUBLE);
404 result = json_real_value(v);
405 json_decref(v);
406 return result;
407 }
408
hb_value_get_bool(const hb_value_t * value)409 int hb_value_get_bool(const hb_value_t *value)
410 {
411 int result;
412 hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_BOOL);
413 result = json_is_true(v);
414 json_decref(v);
415 return result;
416 }
417
418 char*
hb_value_get_string_xform(const hb_value_t * value)419 hb_value_get_string_xform(const hb_value_t *value)
420 {
421 char *result;
422 if (hb_value_type(value) == HB_VALUE_TYPE_NULL)
423 return NULL;
424 hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_STRING);
425 if (hb_value_type(v) == HB_VALUE_TYPE_NULL)
426 return NULL;
427 result = strdup(json_string_value(v));
428 json_decref(v);
429 return result;
430 }
431
hb_value_get_json(const hb_value_t * value)432 char * hb_value_get_json(const hb_value_t *value)
433 {
434 return json_dumps(value, JSON_INDENT(4) | JSON_SORT_KEYS);
435 }
436
hb_value_write_file_json(hb_value_t * value,FILE * file)437 int hb_value_write_file_json(hb_value_t *value, FILE *file)
438 {
439 return json_dumpf(value, file, JSON_INDENT(4) | JSON_SORT_KEYS);
440 }
441
hb_value_write_json(hb_value_t * value,const char * path)442 int hb_value_write_json(hb_value_t *value, const char *path)
443 {
444 return json_dump_file(value, path, JSON_INDENT(4) | JSON_SORT_KEYS);
445 }
446
hb_dict_free(hb_dict_t ** _dict)447 void hb_dict_free(hb_dict_t **_dict)
448 {
449 hb_value_free(_dict);
450 }
451
hb_dict_init()452 hb_dict_t * hb_dict_init()
453 {
454 return json_object();
455 }
456
457 void
hb_dict_clear(hb_dict_t * dict)458 hb_dict_clear(hb_dict_t *dict)
459 {
460 json_object_clear(dict);
461 }
462
hb_dict_elements(hb_dict_t * dict)463 int hb_dict_elements(hb_dict_t * dict)
464 {
465 return json_object_size(dict);
466 }
467
makelower(const char * key)468 static char * makelower(const char *key)
469 {
470 int ii, len = strlen(key);
471 char * lower = malloc(len + 1);
472
473 for (ii = 0; ii < len; ii++)
474 {
475 lower[ii] = tolower(key[ii]);
476 }
477 lower[ii] = '\0';
478 return lower;
479 }
480
hb_dict_set(hb_dict_t * dict,const char * key,hb_value_t * value)481 void hb_dict_set(hb_dict_t * dict, const char *key, hb_value_t *value)
482 {
483 json_object_set_new(dict, key, value);
484 }
485
hb_dict_merge(hb_dict_t * dict,hb_dict_t * value)486 void hb_dict_merge(hb_dict_t * dict, hb_dict_t *value)
487 {
488 json_object_update(dict, value);
489 }
490
hb_dict_case_set(hb_dict_t * dict,const char * key,hb_value_t * value)491 void hb_dict_case_set(hb_dict_t * dict, const char *key, hb_value_t *value)
492 {
493 char * lower = makelower(key);
494 json_object_set_new(dict, lower, value);
495 free(lower);
496 }
497
hb_dict_remove(hb_dict_t * dict,const char * key)498 int hb_dict_remove(hb_dict_t * dict, const char * key)
499 {
500 int result;
501
502 // First try case sensitive lookup
503 result = json_object_del(dict, key) == 0;
504 if (!result)
505 {
506 // If not found, try case insensitive lookup
507 char * lower = makelower(key);
508 result = json_object_del(dict, lower) == 0;
509 free(lower);
510 }
511 return result;
512 }
513
hb_dict_get(const hb_dict_t * dict,const char * key)514 hb_value_t * hb_dict_get(const hb_dict_t * dict, const char * key)
515 {
516 hb_value_t * result;
517
518 // First try case sensitive lookup
519 result = json_object_get(dict, key);
520 if (result == NULL)
521 {
522 // If not found, try case insensitive lookup
523 char * lower = makelower(key);
524 result = json_object_get(dict, lower);
525 free(lower);
526 }
527 return result;
528 }
529
530 // Dictionary extraction helpers
531 //
532 // Extract the given key from the dict and assign to dst *only*
533 // if key is found in dict. Values are converted to the requested
534 // data type.
535 //
536 // return: 1 - key is in dict
537 // 0 - key is not in dict
hb_dict_extract_int(int * dst,const hb_dict_t * dict,const char * key)538 int hb_dict_extract_int(int *dst, const hb_dict_t * dict, const char * key)
539 {
540 if (dict == NULL || key == NULL || dst == NULL)
541 {
542 return 0;
543 }
544
545 hb_value_t *val = hb_dict_get(dict, key);
546 if (val == NULL)
547 {
548 return 0;
549 }
550
551 *dst = hb_value_get_int(val);
552 return 1;
553 }
554
hb_dict_extract_double(double * dst,const hb_dict_t * dict,const char * key)555 int hb_dict_extract_double(double *dst, const hb_dict_t * dict,
556 const char * key)
557 {
558 if (dict == NULL || key == NULL || dst == NULL)
559 {
560 return 0;
561 }
562
563 hb_value_t *val = hb_dict_get(dict, key);
564 if (val == NULL)
565 {
566 return 0;
567 }
568
569 *dst = hb_value_get_double(val);
570 return 1;
571 }
572
hb_dict_extract_bool(int * dst,const hb_dict_t * dict,const char * key)573 int hb_dict_extract_bool(int *dst, const hb_dict_t * dict, const char * key)
574 {
575 if (dict == NULL || key == NULL || dst == NULL)
576 {
577 return 0;
578 }
579
580 hb_value_t *val = hb_dict_get(dict, key);
581 if (val == NULL)
582 {
583 return 0;
584 }
585
586 *dst = hb_value_get_bool(val);
587 return 1;
588 }
589
hb_dict_extract_string(char ** dst,const hb_dict_t * dict,const char * key)590 int hb_dict_extract_string(char **dst, const hb_dict_t * dict, const char * key)
591 {
592 if (dict == NULL || key == NULL || dst == NULL)
593 {
594 return 0;
595 }
596
597 hb_value_t *val = hb_dict_get(dict, key);
598 if (val == NULL)
599 {
600 return 0;
601 }
602
603 *dst = hb_value_get_string_xform(val);
604 return 1;
605 }
606
hb_dict_extract_rational(hb_rational_t * dst,const hb_dict_t * dict,const char * key)607 int hb_dict_extract_rational(hb_rational_t *dst, const hb_dict_t * dict,
608 const char * key)
609 {
610 if (dict == NULL || key == NULL || dst == NULL)
611 {
612 return 0;
613 }
614
615 hb_value_t *val = hb_dict_get(dict, key);
616 if (val == NULL)
617 {
618 return 0;
619 }
620
621 if (hb_value_type(val) == HB_VALUE_TYPE_DICT)
622 {
623 hb_value_t * num_val = hb_dict_get(val, "Num");
624 if (num_val == NULL)
625 {
626 return 0;
627 }
628 hb_value_t * den_val = hb_dict_get(val, "Den");
629 if (den_val == NULL)
630 {
631 return 0;
632 }
633
634 dst->num = hb_value_get_int(num_val);
635 dst->den = hb_value_get_int(den_val);
636 return 1;
637 }
638 else if (hb_value_type(val) == HB_VALUE_TYPE_STRING)
639 {
640 const char * str = hb_value_get_string(val);
641 char ** rational = hb_str_vsplit(str, '/');
642 if (rational[0] != NULL && rational[1] != NULL &&
643 isdigit(rational[0][0]) && isdigit(rational[1][0]))
644 {
645 char *num_end, *den_end;
646
647 // found rational format value
648 int num = strtol(rational[0], &num_end, 0);
649 int den = strtol(rational[1], &den_end, 0);
650 // confirm that the 2 components were entirely numbers
651 if (num_end[0] == 0 && den_end[0] == 0)
652 {
653 dst->num = num;
654 dst->den = den;
655 hb_str_vfree(rational);
656 return 1;
657 }
658 }
659 hb_str_vfree(rational);
660 }
661
662 return 0;
663 }
664
hb_dict_extract_int_array(int * dst,int count,const hb_dict_t * dict,const char * key)665 int hb_dict_extract_int_array(int *dst, int count,
666 const hb_dict_t * dict, const char * key)
667 {
668 if (dict == NULL || key == NULL || dst == NULL)
669 {
670 return 0;
671 }
672
673 hb_value_t *val = hb_dict_get(dict, key);
674 if (hb_value_type(val) != HB_VALUE_TYPE_ARRAY)
675 {
676 return 0;
677 }
678
679 int len = hb_value_array_len(val);
680 count = count < len ? count : len;
681
682 int ii;
683 for (ii = 0; ii < count; ii++)
684 {
685 dst[ii] = hb_value_get_int(hb_value_array_get(val, ii));
686 }
687 return 1;
688 }
689
hb_dict_iter_init(const hb_dict_t * dict)690 hb_dict_iter_t hb_dict_iter_init(const hb_dict_t *dict)
691 {
692 if (dict == NULL)
693 return HB_DICT_ITER_DONE;
694 return json_object_iter((hb_dict_t*)dict);
695 }
696
hb_dict_iter_next(const hb_dict_t * dict,hb_dict_iter_t iter)697 hb_dict_iter_t hb_dict_iter_next(const hb_dict_t *dict, hb_dict_iter_t iter)
698 {
699 return json_object_iter_next((hb_dict_t*)dict, iter);
700 }
701
hb_dict_iter_key(const hb_dict_iter_t iter)702 const char * hb_dict_iter_key(const hb_dict_iter_t iter)
703 {
704 return json_object_iter_key(iter);
705 }
706
hb_dict_iter_value(const hb_dict_iter_t iter)707 hb_value_t * hb_dict_iter_value(const hb_dict_iter_t iter)
708 {
709 return json_object_iter_value(iter);
710 }
711
712 int
hb_dict_iter_next_ex(const hb_dict_t * dict,hb_dict_iter_t * iter,const char ** key,hb_value_t ** val)713 hb_dict_iter_next_ex(const hb_dict_t *dict, hb_dict_iter_t *iter,
714 const char **key, hb_value_t **val)
715 {
716 if (*iter == NULL)
717 return 0;
718 if (key != NULL)
719 *key = json_object_iter_key(*iter);
720 if (val != NULL)
721 *val = json_object_iter_value(*iter);
722 *iter = json_object_iter_next((hb_dict_t*)dict, *iter);
723 return 1;
724 }
725
726 hb_value_array_t*
hb_value_array_init()727 hb_value_array_init()
728 {
729 return json_array();
730 }
731
732 void
hb_value_array_clear(hb_value_array_t * array)733 hb_value_array_clear(hb_value_array_t *array)
734 {
735 json_array_clear(array);
736 }
737
738 hb_value_t*
hb_value_array_get(const hb_value_array_t * array,int index)739 hb_value_array_get(const hb_value_array_t *array, int index)
740 {
741 return json_array_get(array, index);
742 }
743
744 void
hb_value_array_set(hb_value_array_t * array,int index,hb_value_t * value)745 hb_value_array_set(hb_value_array_t *array, int index, hb_value_t *value)
746 {
747 if (index < 0 || index >= json_array_size(array))
748 {
749 hb_error("hb_value_array_set: invalid index %d size %zu",
750 index, json_array_size(array));
751 return;
752 }
753 json_array_set_new(array, index, value);
754 }
755
756 void
hb_value_array_insert(hb_value_array_t * array,int index,hb_value_t * value)757 hb_value_array_insert(hb_value_array_t *array, int index, hb_value_t *value)
758 {
759 json_array_insert_new(array, index, value);
760 }
761
762 void
hb_value_array_append(hb_value_array_t * array,hb_value_t * value)763 hb_value_array_append(hb_value_array_t *array, hb_value_t *value)
764 {
765 json_array_append_new(array, value);
766 }
767
768 void
hb_value_array_concat(hb_value_array_t * array,hb_value_t * value)769 hb_value_array_concat(hb_value_array_t *array, hb_value_t *value)
770 {
771 if (hb_value_type(value) == HB_VALUE_TYPE_ARRAY)
772 {
773 int ii;
774 int len = hb_value_array_len(value);
775
776 for (ii = 0; ii < len; ii++)
777 {
778 hb_value_t * val = hb_value_array_get(value, ii);
779 json_array_append_new(array, hb_value_dup(val));
780 }
781 }
782 else
783 {
784 json_array_append_new(array, hb_value_dup(value));
785 }
786 }
787
788 void
hb_value_array_remove(hb_value_array_t * array,int index)789 hb_value_array_remove(hb_value_array_t *array, int index)
790 {
791 json_array_remove(array, index);
792 }
793
794 void
hb_value_array_copy(hb_value_array_t * dst,const hb_value_array_t * src,int count)795 hb_value_array_copy(hb_value_array_t *dst,
796 const hb_value_array_t *src, int count)
797 {
798 size_t len;
799 int ii;
800
801 // empty the first array if it is not already empty
802 json_array_clear(dst);
803
804 len = hb_value_array_len(src);
805 count = MIN(count, len);
806 for (ii = 0; ii < count; ii++)
807 hb_value_array_append(dst, hb_value_dup(hb_value_array_get(src, ii)));
808 }
809
810 size_t
hb_value_array_len(const hb_value_array_t * array)811 hb_value_array_len(const hb_value_array_t *array)
812 {
813 return json_array_size(array);
814 }
815
hb_encopts_to_dict(const char * encopts,int encoder)816 hb_dict_t * hb_encopts_to_dict(const char * encopts, int encoder)
817 {
818 hb_dict_t * dict = NULL;
819
820 if (encopts && *encopts)
821 {
822 char *cur_opt, *opts_start, *value;
823 const char *name;
824 dict = hb_dict_init();
825 if( !dict )
826 return NULL;
827 cur_opt = opts_start = strdup(encopts);
828 if (opts_start)
829 {
830 while (*cur_opt)
831 {
832 name = cur_opt;
833 cur_opt += strcspn(cur_opt, ":");
834 if (*cur_opt)
835 {
836 *cur_opt = 0;
837 cur_opt++;
838 }
839 value = strchr(name, '=');
840 if (value)
841 {
842 *value = 0;
843 value++;
844 }
845 // x264 has multiple names for some options
846 if (encoder & HB_VCODEC_X264_MASK)
847 name = hb_x264_encopt_name(name);
848 #if HB_PROJECT_FEATURE_X265
849 // x265 has multiple names for some options
850 if (encoder & HB_VCODEC_X265_MASK)
851 name = hb_x265_encopt_name(name);
852 #endif
853 if (name != NULL)
854 {
855 hb_dict_set(dict, name, hb_value_string(value));
856 }
857 }
858 }
859 free(opts_start);
860 }
861 return dict;
862 }
863
hb_dict_to_encopts(const hb_dict_t * dict)864 char * hb_dict_to_encopts(const hb_dict_t * dict)
865 {
866 return hb_value_get_string_xform(dict);
867 }
868
869