1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2025 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "mpp_cfg_io"
7
8 #include <errno.h>
9 #include <float.h>
10 #include <string.h>
11 #include <limits.h>
12
13 #include "mpp_env.h"
14 #include "mpp_mem.h"
15 #include "mpp_list.h"
16 #include "mpp_debug.h"
17 #include "mpp_common.h"
18
19 #include "mpp_trie.h"
20 #include "mpp_cfg.h"
21 #include "mpp_cfg_io.h"
22 #include "rk_venc_cfg.h"
23
24 #define MAX_CFG_DEPTH (64)
25
26 #define CFG_IO_DBG_FLOW (0x00000001)
27 #define CFG_IO_DBG_BYTE (0x00000002)
28 #define CFG_IO_DBG_TO (0x00000004)
29 #define CFG_IO_DBG_FROM (0x00000008)
30 #define CFG_IO_DBG_FREE (0x00000010)
31 #define CFG_IO_DBG_NAME (0x00000020)
32 #define CFG_IO_DBG_SHOW (0x00000040)
33 #define CFG_IO_DBG_INFO (0x00000080)
34
35 #define cfg_io_dbg(flag, fmt, ...) _mpp_dbg(mpp_cfg_io_debug, flag, fmt, ## __VA_ARGS__)
36 #define cfg_io_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_cfg_io_debug, flag, fmt, ## __VA_ARGS__)
37
38 #define cfg_io_dbg_flow(fmt, ...) cfg_io_dbg(CFG_IO_DBG_FLOW, fmt, ## __VA_ARGS__)
39 #define cfg_io_dbg_byte(fmt, ...) cfg_io_dbg(CFG_IO_DBG_BYTE, fmt, ## __VA_ARGS__)
40 #define cfg_io_dbg_to(fmt, ...) cfg_io_dbg(CFG_IO_DBG_TO, fmt, ## __VA_ARGS__)
41 #define cfg_io_dbg_from(fmt, ...) cfg_io_dbg(CFG_IO_DBG_FROM, fmt, ## __VA_ARGS__)
42 #define cfg_io_dbg_free(fmt, ...) cfg_io_dbg(CFG_IO_DBG_FREE, fmt, ## __VA_ARGS__)
43 #define cfg_io_dbg_name(fmt, ...) cfg_io_dbg(CFG_IO_DBG_NAME, fmt, ## __VA_ARGS__)
44 #define cfg_io_dbg_show(fmt, ...) cfg_io_dbg_f(CFG_IO_DBG_SHOW, fmt, ## __VA_ARGS__)
45 #define cfg_io_dbg_info(fmt, ...) cfg_io_dbg(CFG_IO_DBG_INFO, fmt, ## __VA_ARGS__)
46
47 typedef enum MppCfgParserType_e {
48 MPP_CFG_PARSER_TYPE_KEY = 0,
49 MPP_CFG_PARSER_TYPE_VALUE,
50 MPP_CFG_PARSER_TYPE_TABLE,
51 MPP_CFG_PARSER_TYPE_ARRAY_TABLE,
52 MPP_CFG_PARSER_TYPE_BUTT,
53 } MppCfgParserType;
54
55 typedef struct MppCfgIoImpl_t MppCfgIoImpl;
56 typedef void (*MppCfgIoFunc)(MppCfgIoImpl *obj, void *data);
57
58 struct MppCfgIoImpl_t {
59 /* list for bothers */
60 struct list_head list;
61 /* list for children */
62 struct list_head child;
63 /* parent of current object */
64 MppCfgIoImpl *parent;
65 /* valid condition callback for the current object */
66 MppCfgObjCond cond;
67
68 MppCfgType type;
69 MppCfgVal val;
70
71 rk_s32 buf_size;
72 /* depth in tree */
73 rk_s32 depth;
74
75 /* internal name storage */
76 char *name;
77 rk_s32 name_len;
78 rk_s32 name_buf_len;
79
80 /* location info for structure access */
81 MppTrie trie;
82 MppCfgInfo info;
83
84 union {
85 /* MPP_CFG_TYPE_STRING */
86 struct {
87 char *string;
88 rk_s32 str_len;
89 };
90 /* MPP_CFG_TYPE_ARRAY */
91 struct {
92 MppCfgIoImpl **elems;
93 rk_s32 array_size;
94 };
95 };
96 };
97
98 typedef struct MppCfgStrBuf_t {
99 char *buf;
100 rk_s32 buf_size;
101 rk_s32 offset;
102 rk_s32 depth;
103 MppCfgStrFmt type;
104 } MppCfgStrBuf;
105
106 static rk_u32 mpp_cfg_io_debug = 0;
107
strof_type(MppCfgType type)108 static const char *strof_type(MppCfgType type)
109 {
110 static const char *str[MPP_CFG_TYPE_BUTT + 1] = {
111 [MPP_CFG_TYPE_INVALID] = "invalid",
112 [MPP_CFG_TYPE_NULL] = "null",
113 [MPP_CFG_TYPE_BOOL] = "bool",
114 [MPP_CFG_TYPE_s32] = "s32",
115 [MPP_CFG_TYPE_u32] = "u32",
116 [MPP_CFG_TYPE_s64] = "s64",
117 [MPP_CFG_TYPE_u64] = "u64",
118 [MPP_CFG_TYPE_f32] = "f32",
119 [MPP_CFG_TYPE_f64] = "f64",
120 [MPP_CFG_TYPE_STRING] = "string",
121 [MPP_CFG_TYPE_RAW] = "raw",
122 [MPP_CFG_TYPE_OBJECT] = "object",
123 [MPP_CFG_TYPE_ARRAY] = "array",
124 [MPP_CFG_TYPE_BUTT] = "unknown",
125 };
126
127 if (type < 0 || type > MPP_CFG_TYPE_BUTT)
128 type = MPP_CFG_TYPE_BUTT;
129
130 return str[type];
131 }
132
dup_str(const char * str,rk_s32 len)133 static char *dup_str(const char *str, rk_s32 len)
134 {
135 char *ret = NULL;
136
137 if (str && len > 0) {
138 ret = mpp_calloc_size(char, len + 1);
139 if (ret) {
140 memcpy(ret, str, len);
141 ret[len] = '\0';
142 }
143 }
144
145 return ret;
146 }
147
get_full_name(MppCfgIoImpl * obj,char * buf,rk_s32 buf_size)148 static rk_s32 get_full_name(MppCfgIoImpl *obj, char *buf, rk_s32 buf_size)
149 {
150 MppCfgIoImpl *curr = obj;
151 char *name[MAX_CFG_DEPTH];
152 char *delmiter = ":";
153 rk_s32 depth = 0;
154 rk_s32 len = 0;
155 rk_s32 i = 0;
156
157 while (curr && curr->parent) {
158 /* skip the root */
159 if (curr->name) {
160 /* Add delimiter on object */
161 if (curr->type >= MPP_CFG_TYPE_OBJECT)
162 name[i++] = delmiter;
163
164 name[i++] = curr->name;
165 }
166
167 curr = curr->parent;
168 depth++;
169
170 if (i >= MAX_CFG_DEPTH) {
171 mpp_loge_f("too deep depth %d\n", depth);
172 return 0;
173 }
174 }
175
176 if (!i) {
177 buf[0] = '\0';
178 return 0;
179 }
180
181 depth = i;
182 for (i = depth - 1; i >= 0; i--) {
183 len += snprintf(buf + len, buf_size - len, "%s", name[i]);
184
185 if (len >= buf_size) {
186 mpp_loge_f("buffer overflow len %d buf_size %d\n", len, buf_size);
187 break;
188 }
189 }
190
191 cfg_io_dbg_name("depth %d obj %-16s -> %s\n", obj->depth, obj->name, buf);
192
193 return len;
194 }
195
loop_all_children(MppCfgIoImpl * impl,MppCfgIoFunc func,void * data)196 void loop_all_children(MppCfgIoImpl *impl, MppCfgIoFunc func, void *data)
197 {
198 MppCfgIoImpl *pos, *n;
199
200 func(impl, data);
201
202 list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) {
203 loop_all_children(pos, func, data);
204 }
205 }
206
mpp_cfg_get_object(MppCfgObj * obj,const char * name,MppCfgType type,MppCfgVal * val)207 rk_s32 mpp_cfg_get_object(MppCfgObj *obj, const char *name, MppCfgType type, MppCfgVal *val)
208 {
209 MppCfgIoImpl *impl = NULL;
210 rk_s32 name_buf_len = 0;
211 rk_s32 name_len = 0;
212 rk_s32 buf_size = 0;
213 rk_s32 str_len = 0;
214
215 if (!obj || type <= MPP_CFG_TYPE_INVALID || type >= MPP_CFG_TYPE_BUTT) {
216 mpp_loge_f("invalid param obj %p name %s type %d val %p\n", obj, name, type, val);
217 return rk_nok;
218 }
219
220 mpp_env_get_u32("mpp_cfg_io_debug", &mpp_cfg_io_debug, mpp_cfg_io_debug);
221
222 if (*obj)
223 mpp_logw_f("obj %p overwrite\n", *obj);
224
225 *obj = NULL;
226
227 if (name) {
228 name_len = strlen(name);
229 name_buf_len = MPP_ALIGN(name_len + 1, 4);
230 }
231
232 if (type == MPP_CFG_TYPE_STRING && val && val->str)
233 str_len = MPP_ALIGN(strlen(val->str) + 1, 4);
234
235 buf_size = sizeof(MppCfgIoImpl) + name_buf_len + str_len;
236 impl = mpp_calloc_size(MppCfgIoImpl, buf_size);
237
238 if (!impl) {
239 mpp_loge_f("failed to alloc impl size %d\n", buf_size);
240 return rk_nok;
241 }
242
243 INIT_LIST_HEAD(&impl->list);
244 INIT_LIST_HEAD(&impl->child);
245
246 if (name_buf_len) {
247 impl->name = (char *)(impl + 1);
248 memcpy(impl->name, name, name_len);
249 impl->name[name_len] = '\0';
250 impl->name_len = name_len;
251 impl->name_buf_len = name_buf_len;
252 }
253
254 if (str_len) {
255 impl->string = (char *)(impl + 1) + name_buf_len;
256 strncpy(impl->string, val->str, str_len);
257 impl->str_len = str_len;
258 }
259
260 impl->type = type;
261 if (val)
262 impl->val = *val;
263 impl->buf_size = buf_size;
264 /* set invalid data type by default */
265 impl->info.data_type = CFG_FUNC_TYPE_BUTT;
266
267 if (type == MPP_CFG_TYPE_STRING)
268 impl->val.str = impl->string;
269
270 *obj = impl;
271
272 return rk_ok;
273 }
274
mpp_cfg_get_array(MppCfgObj * obj,const char * name,rk_s32 count)275 rk_s32 mpp_cfg_get_array(MppCfgObj *obj, const char *name, rk_s32 count)
276 {
277 MppCfgIoImpl *impl = NULL;
278 rk_s32 name_buf_len = 0;
279 rk_s32 name_len = 0;
280 rk_s32 buf_size = 0;
281
282 if (!obj) {
283 mpp_loge_f("invalid param obj %p name %s count %d\n", obj, name, count);
284 return rk_nok;
285 }
286
287 if (*obj)
288 mpp_logw_f("obj %p overwrite\n", *obj);
289
290 *obj = NULL;
291
292 if (name) {
293 name_len = strlen(name);
294 name_buf_len = MPP_ALIGN(name_len + 1, 4);
295 }
296
297 buf_size = sizeof(MppCfgIoImpl) + name_buf_len + count * sizeof(MppCfgObj);
298 impl = mpp_calloc_size(MppCfgIoImpl, buf_size);
299
300 if (!impl) {
301 mpp_loge_f("failed to alloc impl size %d\n", buf_size);
302 return rk_nok;
303 }
304
305 INIT_LIST_HEAD(&impl->list);
306 INIT_LIST_HEAD(&impl->child);
307
308 if (name_len) {
309 impl->name = (char *)(impl + 1);
310 memcpy(impl->name, name, name_len);
311 impl->name[name_len] = '\0';
312 impl->name_len = name_len;
313 impl->name_buf_len = name_buf_len;
314 }
315
316 impl->type = MPP_CFG_TYPE_ARRAY;
317 impl->buf_size = buf_size;
318 /* set invalid data type by default */
319 impl->info.data_type = CFG_FUNC_TYPE_BUTT;
320
321 if (count) {
322 impl->elems = (MppCfgIoImpl **)((char *)(impl + 1) + name_buf_len);
323 impl->array_size = count;
324 }
325
326 *obj = impl;
327
328 return rk_ok;
329 }
330
mpp_cfg_put(MppCfgObj obj)331 rk_s32 mpp_cfg_put(MppCfgObj obj)
332 {
333 MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
334
335 if (!obj) {
336 mpp_loge_f("invalid param obj %p\n", obj);
337 return rk_nok;
338 }
339
340 list_del_init(&impl->list);
341
342 {
343 MppCfgIoImpl *pos, *n;
344
345 list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) {
346 list_del_init(&pos->list);
347 }
348 }
349
350 impl->parent = NULL;
351
352 mpp_free(impl);
353
354 return rk_ok;
355 }
356
mpp_cfg_put_all_child(MppCfgIoImpl * impl)357 static void mpp_cfg_put_all_child(MppCfgIoImpl *impl)
358 {
359 MppCfgIoImpl *pos, *n;
360
361 cfg_io_dbg_free("depth %d - %p free start type %d name %s\n",
362 impl->depth, impl, impl->type, impl->name);
363
364 list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) {
365 list_del_init(&pos->list);
366
367 cfg_io_dbg_free("depth %d - %p free child %p type %d name %s\n",
368 impl->depth, impl, pos, pos->type, pos->name);
369
370 mpp_cfg_put_all_child(pos);
371 }
372
373 cfg_io_dbg_free("depth %d - %p free done type %d name %s\n",
374 impl->depth, impl, impl->type, impl->name);
375
376 mpp_free(impl);
377 }
378
mpp_cfg_put_all(MppCfgObj obj)379 rk_s32 mpp_cfg_put_all(MppCfgObj obj)
380 {
381 MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
382 MppCfgIoImpl *root;
383
384 if (!obj) {
385 mpp_loge_f("invalid param obj %p\n", obj);
386 return rk_nok;
387 }
388
389 if (impl->trie) {
390 mpp_trie_deinit(impl->trie);
391 impl->trie = NULL;
392 }
393
394 root = impl->parent;
395 do {
396 mpp_cfg_put_all_child(impl);
397
398 if (!root)
399 break;
400
401 impl = root;
402 root = impl->parent;
403 } while (impl);
404
405 return rk_ok;
406 }
407
update_depth(MppCfgIoImpl * impl,void * data)408 static void update_depth(MppCfgIoImpl *impl, void *data)
409 {
410 (void)data;
411
412 if (impl->parent)
413 impl->depth = impl->parent->depth + 1;
414 }
415
mpp_cfg_add(MppCfgObj root,MppCfgObj leaf)416 rk_s32 mpp_cfg_add(MppCfgObj root, MppCfgObj leaf)
417 {
418 MppCfgIoImpl *root_impl = (MppCfgIoImpl *)root;
419 MppCfgIoImpl *leaf_impl = (MppCfgIoImpl *)leaf;
420
421 if (!root || !leaf) {
422 mpp_loge_f("invalid param root %p leaf %p\n", root, leaf);
423 return rk_nok;
424 }
425
426 if (root_impl->type <= MPP_CFG_TYPE_INVALID || root_impl->type >= MPP_CFG_TYPE_BUTT) {
427 mpp_loge_f("invalid root type %d\n", root_impl->type);
428 return rk_nok;
429 }
430
431 list_add_tail(&leaf_impl->list, &root_impl->child);
432 leaf_impl->parent = root_impl;
433
434 loop_all_children(root, update_depth, NULL);
435
436 if (root_impl->type == MPP_CFG_TYPE_ARRAY && root_impl->elems) {
437 rk_s32 i;
438
439 for (i = 0; i < root_impl->array_size; i++) {
440 if (!root_impl->elems[i]) {
441 root_impl->elems[i] = leaf_impl;
442 break;
443 }
444 }
445 }
446
447 return rk_ok;
448 }
449
mpp_cfg_del(MppCfgObj obj)450 rk_s32 mpp_cfg_del(MppCfgObj obj)
451 {
452 MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
453 MppCfgIoImpl *parent;
454
455 if (!obj) {
456 mpp_loge_f("invalid param obj %p\n", obj);
457 return rk_nok;
458 }
459
460 parent = impl->parent;
461 if (parent) {
462 list_del_init(&impl->list);
463
464 if (parent->type == MPP_CFG_TYPE_ARRAY && parent->elems) {
465 rk_s32 i;
466
467 for (i = 0; i < parent->array_size; i++) {
468 if (parent->elems[i] == impl) {
469 parent->elems[i] = NULL;
470 break;
471 }
472 }
473 }
474
475 impl->parent = NULL;
476 impl->depth = 0;
477 loop_all_children(impl, update_depth, NULL);
478 }
479
480 return rk_ok;
481 }
482
mpp_cfg_find(MppCfgObj * obj,MppCfgObj root,char * name,rk_s32 type)483 rk_s32 mpp_cfg_find(MppCfgObj *obj, MppCfgObj root, char *name, rk_s32 type)
484 {
485 MppCfgIoImpl *impl = (MppCfgIoImpl *)root;
486 rk_s32 str_start = 0;
487 rk_s32 str_len = 0;
488 rk_s32 i;
489 char delimiter;
490
491 if (!obj || !root || !name) {
492 mpp_loge_f("invalid param obj %p root %p name %s\n", obj, root, name);
493 return rk_nok;
494 }
495
496 delimiter = (type == MPP_CFG_STR_FMT_TOML) ? '.' : ':';
497 str_len = strlen(name);
498
499 for (i = 0; i <= str_len; i++) {
500 if (name[i] == delimiter || name[i] == '\0') {
501 MppCfgIoImpl *pos, *n;
502 MppCfgIoImpl *last_array = NULL;
503 char bak = name[i];
504 rk_s32 found = 0;
505
506 name[i] = '\0';
507 mpp_logi("try match %s\n", name + str_start);
508 list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) {
509 if (pos->name && !strcmp(pos->name, name + str_start)) {
510 impl = pos;
511 found = 1;
512 break;
513 }
514
515 /* if impl is array, find impl->chil is object and has no name, to match its child */
516 if (impl->type == MPP_CFG_TYPE_ARRAY && pos->type == MPP_CFG_TYPE_OBJECT && !pos->name)
517 last_array = pos;
518 }
519
520 if (last_array) {
521 MppCfgIoImpl *array_pos, *array_n;
522
523 list_for_each_entry_safe(array_pos, array_n, &last_array->child, MppCfgIoImpl, list) {
524 if (array_pos->name && !strcmp(array_pos->name, name + str_start)) {
525 impl = array_pos;
526 found = 1;
527 break;
528 }
529 }
530 }
531
532 name[i] = bak;
533
534 if (!found) {
535 *obj = NULL;
536 return rk_nok;
537 }
538
539 str_start = i + 1;
540 }
541 }
542
543 *obj = impl;
544 return rk_ok;
545 }
546
mpp_cfg_set_info(MppCfgObj obj,MppCfgInfo * info)547 rk_s32 mpp_cfg_set_info(MppCfgObj obj, MppCfgInfo *info)
548 {
549 MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
550
551 if (impl && info) {
552 cfg_io_dbg_info("obj %-16s set info type %s offset %d size %d\n",
553 impl->name, strof_cfg_type(info->data_type),
554 info->data_offset, info->data_size);
555
556 if (info->data_type < CFG_FUNC_TYPE_BUTT) {
557 memcpy(&impl->info, info, sizeof(impl->info));
558
559 switch (info->data_type) {
560 case CFG_FUNC_TYPE_s32 : {
561 impl->type = MPP_CFG_TYPE_s32;
562 } break;
563 case CFG_FUNC_TYPE_u32 : {
564 impl->type = MPP_CFG_TYPE_u32;
565 } break;
566 case CFG_FUNC_TYPE_s64 : {
567 impl->type = MPP_CFG_TYPE_s64;
568 } break;
569 case CFG_FUNC_TYPE_u64 : {
570 impl->type = MPP_CFG_TYPE_u64;
571 } break;
572 default : {
573 } break;
574 }
575 } else {
576 impl->info.data_type = CFG_FUNC_TYPE_BUTT;
577 }
578
579 return rk_ok;
580 }
581
582 return rk_nok;
583 }
584
mpp_cfg_set_cond(MppCfgObj obj,MppCfgObjCond cond)585 rk_s32 mpp_cfg_set_cond(MppCfgObj obj, MppCfgObjCond cond)
586 {
587 MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
588
589 if (impl)
590 impl->cond = cond;
591
592 return rk_ok;
593 }
594 typedef struct MppCfgFullNameCtx_t {
595 MppTrie trie;
596 char *buf;
597 rk_s32 buf_size;
598 } MppCfgFullNameCtx;
599
add_obj_info(MppCfgIoImpl * impl,void * data)600 static void add_obj_info(MppCfgIoImpl *impl, void *data)
601 {
602 /* NOTE: skip the root object and the invalid object */
603 if (impl->info.data_type < CFG_FUNC_TYPE_BUTT && impl->parent) {
604 MppCfgFullNameCtx *ctx = (MppCfgFullNameCtx *)data;
605
606 get_full_name(impl, ctx->buf, ctx->buf_size);
607 mpp_trie_add_info(ctx->trie, ctx->buf, &impl->info, sizeof(impl->info));
608 }
609 }
610
mpp_cfg_to_trie(MppCfgObj obj)611 MppTrie mpp_cfg_to_trie(MppCfgObj obj)
612 {
613 MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
614 MppTrie p = NULL;
615
616 do {
617 MppCfgFullNameCtx ctx;
618 rk_s32 ret = rk_nok;
619 char name[256];
620
621 if (!impl) {
622 mpp_loge_f("invalid param obj\n", impl);
623 break;
624 }
625
626 if (impl->parent) {
627 mpp_loge_f("invalid param obj %p not root\n", impl);
628 break;
629 }
630
631 if (impl->trie) {
632 p = impl->trie;
633 break;
634 }
635
636 ret = mpp_trie_init(&p, impl->name ? impl->name : "cfg_io");
637 if (ret || !p) {
638 mpp_loge_f("failed to init obj %s trie\n", impl->name ? impl->name : "cfg_io");
639 break;
640 }
641
642 ctx.trie = p;
643 ctx.buf = name;
644 ctx.buf_size = sizeof(name) - 1;
645
646 loop_all_children(impl, add_obj_info, &ctx);
647 mpp_trie_add_info(p, NULL, NULL, 0);
648 impl->trie = p;
649 } while (0);
650
651 return p;
652 }
653
654 /* read byte functions */
655 /* check valid len, get offset position */
656 #define test_byte_f(str, len) test_byte(str, len, __FUNCTION__)
657 /* check valid pos, get offset + pos position */
658 #define show_byte_f(str, pos) show_byte(str, pos, __FUNCTION__)
659 /* check valid len, get offset + len position and increase offset by len */
660 #define skip_byte_f(str, len) skip_byte(str, len, __FUNCTION__)
661 #define skip_ws_f(str) skip_ws(str, __FUNCTION__)
662
663 /* write byte functions */
664 #define write_byte_f(str, buf, size) write_byte(str, (void *)buf, size, __FUNCTION__)
665 #define write_indent_f(str) write_indent(str, __FUNCTION__)
666 /* revert comma for json */
667 #define revert_comma_f(str) revert_comma(str, __FUNCTION__)
668
test_byte(MppCfgStrBuf * str,rk_s32 len,const char * caller)669 static char *test_byte(MppCfgStrBuf *str, rk_s32 len, const char *caller)
670 {
671 char *ret = NULL;
672
673 if (str->offset + len >= str->buf_size) {
674 cfg_io_dbg_byte("str %p-[%p:%d] offset %d test %d get the end at %s\n",
675 str, str->buf, str->buf_size, str->offset, len, caller);
676 return ret;
677 }
678
679 ret = str->buf + str->offset;
680
681 cfg_io_dbg_byte("str %p-[%p:%d] offset %d test %d ret %p at %s\n",
682 str, str->buf, str->buf_size, str->offset, len, ret, caller);
683
684 return ret;
685 }
686
show_byte(MppCfgStrBuf * str,rk_s32 pos,const char * caller)687 static char *show_byte(MppCfgStrBuf *str, rk_s32 pos, const char *caller)
688 {
689 char *ret = NULL;
690
691 if (str->offset + pos >= str->buf_size) {
692 cfg_io_dbg_byte("str %p-[%p:%d] offset %d show pos %d get the end at %s\n",
693 str, str->buf, str->buf_size, str->offset, pos, caller);
694 return ret;
695 }
696
697 ret = str->buf + str->offset + pos;
698
699 cfg_io_dbg_byte("str %p-[%p:%d] offset %d show %d ret %p at %s\n",
700 str, str->buf, str->buf_size, str->offset, pos, ret, caller);
701
702 return ret;
703 }
704
skip_byte(MppCfgStrBuf * str,rk_s32 len,const char * caller)705 static char *skip_byte(MppCfgStrBuf *str, rk_s32 len, const char *caller)
706 {
707 char *ret = NULL;
708
709 if (str->offset + len >= str->buf_size) {
710 cfg_io_dbg_byte("str %p-[%p:%d] offset %d skip %d get the end at %s\n",
711 str, str->buf, str->buf_size, str->offset, len, caller);
712 return NULL;
713 }
714
715 ret = str->buf + str->offset + len;
716
717 cfg_io_dbg_byte("str %p-[%p:%d] offset %d skip %d ret %p at %s\n",
718 str, str->buf, str->buf_size, str->offset, len, ret, caller);
719
720 str->offset += len;
721 return ret;
722 }
723
skip_ws(MppCfgStrBuf * str,const char * caller)724 static char *skip_ws(MppCfgStrBuf *str, const char *caller)
725 {
726 rk_s32 old = str->offset;
727 char *p;
728
729 cfg_io_dbg_byte("str %p-[%p:%d] offset %d skip ws start at %s\n",
730 str, str->buf, str->buf_size, old, caller);
731
732 while ((p = show_byte(str, 0, caller)) && p[0] <= 32)
733 str->offset++;
734
735 if (str->offset >= str->buf_size) {
736 cfg_io_dbg_byte("str %p-[%p:%d] offset %d skip ws to the end at %s\n",
737 str, str->buf, str->buf_size, str->offset, caller);
738 str->offset--;
739 return NULL;
740 }
741
742 cfg_io_dbg_byte("str %p-[%p:%d] offset %d skip ws to %d at %s\n",
743 str, str->buf, str->buf_size, old, str->offset, caller);
744
745 return str->buf + str->offset;
746 }
747
write_byte(MppCfgStrBuf * str,void * buf,rk_s32 * size,const char * caller)748 static rk_s32 write_byte(MppCfgStrBuf *str, void *buf, rk_s32 *size, const char *caller)
749 {
750 rk_s32 len = size[0];
751
752 if (!len)
753 return rk_ok;
754
755 if (str->offset + len >= str->buf_size) {
756 void *ptr = mpp_realloc_size(str->buf, void, str->buf_size * 2);
757
758 if (!ptr) {
759 mpp_loge("failed to realloc buf size %d -> %d at %s\n",
760 str->buf_size, str->buf_size * 2, caller);
761 return rk_nok;
762 }
763
764 cfg_io_dbg_byte("str %p-[%p:%d] enlarger buffer to [%p:%d] at %s\n",
765 str, str->buf, str->buf_size, ptr, str->buf_size * 2, caller);
766
767 str->buf = ptr;
768 str->buf_size *= 2;
769 }
770
771 cfg_io_dbg_byte("str %p-[%p:%d] write offset %d from [%p:%d] at %s\n",
772 str, str->buf, str->buf_size, str->offset, buf, len, caller);
773
774 memcpy(str->buf + str->offset, buf, len);
775 str->offset += len;
776 str->buf[str->offset] = '\0';
777 size[0] = 0;
778
779 return rk_ok;
780 }
781
write_indent(MppCfgStrBuf * str,const char * caller)782 static rk_s32 write_indent(MppCfgStrBuf *str, const char *caller)
783 {
784 rk_s32 depth;
785
786 cfg_io_dbg_byte("str %p-[%p:%d] write indent %d at %s\n",
787 str, str->buf, str->buf_size, str->depth, caller);
788
789 depth = str->depth;
790 if (str->type == MPP_CFG_STR_FMT_TOML) {
791 depth = depth - 1;
792 depth = depth >= 0 ? depth : 0;
793 }
794
795 if (depth) {
796 char space[17] = " ";
797 rk_s32 i;
798
799 for (i = 0; i < depth; i++) {
800 rk_s32 indent_width = 4;
801
802 if (write_byte_f(str, space, &indent_width))
803 return rk_nok;
804 }
805 }
806
807 return rk_ok;
808 }
809
revert_comma(MppCfgStrBuf * str,const char * caller)810 static rk_s32 revert_comma(MppCfgStrBuf *str, const char *caller)
811 {
812 cfg_io_dbg_byte("str %p-[%p:%d] revert_comma %d at %s\n",
813 str, str->buf, str->buf_size, str->depth, caller);
814
815 if (str->offset <= 1) {
816 cfg_io_dbg_byte("str %p offset %d skip revert_comma at %s\n",
817 str, str->offset, caller);
818 return rk_ok;
819 }
820
821 if (str->buf[str->offset - 2] == ',') {
822 str->buf[str->offset - 2] = str->buf[str->offset - 1];
823 str->buf[str->offset - 1] = str->buf[str->offset];
824 str->offset--;
825 }
826
827 return rk_ok;
828 }
829
mpp_cfg_to_log(MppCfgIoImpl * impl,MppCfgStrBuf * str)830 static rk_s32 mpp_cfg_to_log(MppCfgIoImpl *impl, MppCfgStrBuf *str)
831 {
832 MppCfgIoImpl *pos, *n;
833 char buf[256];
834 rk_s32 len = 0;
835 rk_s32 total = sizeof(buf) - 1;
836 rk_s32 ret = rk_ok;
837
838 write_indent_f(str);
839
840 /* leaf node write once and finish */
841 if (impl->type < MPP_CFG_TYPE_OBJECT) {
842 cfg_io_dbg_to("depth %d leaf write name %s type %d\n", str->depth, impl->name, impl->type);
843
844 if (impl->name)
845 len += snprintf(buf + len, total - len, "%s : ", impl->name);
846
847 switch (impl->type) {
848 case MPP_CFG_TYPE_NULL : {
849 len += snprintf(buf + len, total - len, "null\n");
850 } break;
851 case MPP_CFG_TYPE_BOOL : {
852 len += snprintf(buf + len, total - len, "%s\n", impl->val.b1 ? "true" : "false");
853 } break;
854 case MPP_CFG_TYPE_s32 : {
855 len += snprintf(buf + len, total - len, "%d\n", impl->val.s32);
856 } break;
857 case MPP_CFG_TYPE_u32 : {
858 len += snprintf(buf + len, total - len, "%u\n", impl->val.u32);
859 } break;
860 case MPP_CFG_TYPE_s64 : {
861 len += snprintf(buf + len, total - len, "%lld\n", impl->val.s64);
862 } break;
863 case MPP_CFG_TYPE_u64 : {
864 len += snprintf(buf + len, total - len, "%llu\n", impl->val.u64);
865 } break;
866 case MPP_CFG_TYPE_f32 : {
867 len += snprintf(buf + len, total - len, "%f\n", impl->val.f32);
868 } break;
869 case MPP_CFG_TYPE_f64 : {
870 len += snprintf(buf + len, total - len, "%lf\n", impl->val.f64);
871 } break;
872 case MPP_CFG_TYPE_STRING :
873 case MPP_CFG_TYPE_RAW : {
874 len += snprintf(buf + len, total - len, "\"%s\"\n", (char *)impl->val.str);
875 } break;
876 default : {
877 mpp_loge("invalid type %d\n", impl->type);
878 } break;
879 }
880
881 return write_byte_f(str, buf, &len);
882 }
883
884 cfg_io_dbg_to("depth %d branch write name %s type %d\n", str->depth, impl->name, impl->type);
885
886 if (impl->name)
887 len += snprintf(buf + len, total - len, "%s : ", impl->name);
888
889 if (list_empty(&impl->child)) {
890 len += snprintf(buf + len, total - len, "%s\n",
891 impl->type == MPP_CFG_TYPE_OBJECT ? "{}" : "[]");
892 return write_byte_f(str, buf, &len);
893 }
894
895 len += snprintf(buf + len, total - len, "%c\n",
896 impl->type == MPP_CFG_TYPE_OBJECT ? '{' : '[');
897
898 ret = write_byte_f(str, buf, &len);
899 if (ret)
900 return ret;
901
902 str->depth++;
903
904 list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) {
905 cfg_io_dbg_to("depth %d child write name %s type %d\n", str->depth, pos->name, pos->type);
906 ret = mpp_cfg_to_log(pos, str);
907 if (ret)
908 break;
909 }
910
911 str->depth--;
912
913 write_indent_f(str);
914
915 len += snprintf(buf + len, total - len, "%c\n",
916 impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']');
917
918 return write_byte_f(str, buf, &len);
919 }
920
mpp_cfg_to_json(MppCfgIoImpl * impl,MppCfgStrBuf * str)921 static rk_s32 mpp_cfg_to_json(MppCfgIoImpl *impl, MppCfgStrBuf *str)
922 {
923 MppCfgIoImpl *pos, *n;
924 char buf[256];
925 rk_s32 len = 0;
926 rk_s32 total = sizeof(buf) - 1;
927 rk_s32 ret = rk_ok;
928
929 write_indent_f(str);
930
931 /* leaf node write once and finish */
932 if (impl->type < MPP_CFG_TYPE_OBJECT) {
933 cfg_io_dbg_to("depth %d leaf write name %s type %d\n", str->depth, impl->name, impl->type);
934
935 if (impl->name)
936 len += snprintf(buf + len, total - len, "\"%s\" : ", impl->name);
937
938 switch (impl->type) {
939 case MPP_CFG_TYPE_NULL : {
940 len += snprintf(buf + len, total - len, "null,\n");
941 } break;
942 case MPP_CFG_TYPE_BOOL : {
943 len += snprintf(buf + len, total - len, "%s,\n", impl->val.b1 ? "true" : "false");
944 } break;
945 case MPP_CFG_TYPE_s32 : {
946 len += snprintf(buf + len, total - len, "%d,\n", impl->val.s32);
947 } break;
948 case MPP_CFG_TYPE_u32 : {
949 len += snprintf(buf + len, total - len, "%u,\n", impl->val.u32);
950 } break;
951 case MPP_CFG_TYPE_s64 : {
952 len += snprintf(buf + len, total - len, "%lld,\n", impl->val.s64);
953 } break;
954 case MPP_CFG_TYPE_u64 : {
955 len += snprintf(buf + len, total - len, "%llu,\n", impl->val.u64);
956 } break;
957 case MPP_CFG_TYPE_f32 : {
958 len += snprintf(buf + len, total - len, "%f,\n", impl->val.f32);
959 } break;
960 case MPP_CFG_TYPE_f64 : {
961 len += snprintf(buf + len, total - len, "%lf,\n", impl->val.f64);
962 } break;
963 case MPP_CFG_TYPE_STRING :
964 case MPP_CFG_TYPE_RAW : {
965 len += snprintf(buf + len, total - len, "\"%s\",\n", (char *)impl->val.str);
966 } break;
967 default : {
968 mpp_loge("invalid type %d\n", impl->type);
969 } break;
970 }
971
972 return write_byte_f(str, buf, &len);
973 }
974
975 cfg_io_dbg_to("depth %d branch write name %s type %d\n", str->depth, impl->name, impl->type);
976
977 if (impl->name)
978 len += snprintf(buf + len, total - len, "\"%s\" : ", impl->name);
979
980 if (list_empty(&impl->child)) {
981 len += snprintf(buf + len, total - len, "%s,\n",
982 impl->type == MPP_CFG_TYPE_OBJECT ? "{}" : "[]");
983 return write_byte_f(str, buf, &len);
984 }
985
986 len += snprintf(buf + len, total - len, "%c\n",
987 impl->type == MPP_CFG_TYPE_OBJECT ? '{' : '[');
988
989 ret = write_byte_f(str, buf, &len);
990 if (ret)
991 return ret;
992
993 str->depth++;
994
995 list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) {
996 cfg_io_dbg_to("depth %d child write name %s type %d\n", str->depth, pos->name, pos->type);
997 ret = mpp_cfg_to_json(pos, str);
998 if (ret)
999 break;
1000 }
1001
1002 revert_comma_f(str);
1003
1004 str->depth--;
1005
1006 write_indent_f(str);
1007
1008 if (str->depth)
1009 len += snprintf(buf + len, total - len, "%c,\n",
1010 impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']');
1011 else
1012 len += snprintf(buf + len, total - len, "%c\n",
1013 impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']');
1014
1015 return write_byte_f(str, buf, &len);
1016 }
1017
mpp_toml_parent_is_array_table(MppCfgIoImpl * impl,MppCfgStrBuf * str)1018 static rk_s32 mpp_toml_parent_is_array_table(MppCfgIoImpl *impl, MppCfgStrBuf *str)
1019 {
1020 return str->depth == 1 && impl->type == MPP_CFG_TYPE_OBJECT &&
1021 !impl->name && impl->parent->type == MPP_CFG_TYPE_ARRAY;
1022 }
1023
mpp_toml_top(MppCfgIoImpl * impl,MppCfgStrBuf * str)1024 static rk_s32 mpp_toml_top(MppCfgIoImpl *impl, MppCfgStrBuf *str)
1025 {
1026 char buf[256];
1027 rk_s32 len = 0;
1028 rk_s32 total = sizeof(buf) - 1;
1029
1030 if (impl->name && impl->type == MPP_CFG_TYPE_OBJECT)
1031 len += snprintf(buf + len, total - len, "\n[%s]\n", impl->name);
1032
1033 return write_byte_f(str, buf, &len);
1034 }
1035
mpp_toml_non_top(MppCfgIoImpl * impl,MppCfgStrBuf * str)1036 static rk_s32 mpp_toml_non_top(MppCfgIoImpl *impl, MppCfgStrBuf *str)
1037 {
1038 char buf[256];
1039 rk_s32 len = 0;
1040 rk_s32 total = sizeof(buf) - 1;
1041
1042 if (impl->name)
1043 len += snprintf(buf + len, total - len, "%s = ", impl->name);
1044
1045 if (list_empty(&impl->child)) {
1046 len += snprintf(buf + len, total - len, "%s\n",
1047 impl->type == MPP_CFG_TYPE_OBJECT ? "{}" : "[]");
1048 return write_byte_f(str, buf, &len);
1049 }
1050
1051 if (mpp_toml_parent_is_array_table(impl, str))
1052 len += snprintf(buf + len, total - len, "\n[[%s]]\n", impl->parent->name);
1053 else
1054 len += snprintf(buf + len, total - len, "%c\n",
1055 impl->type == MPP_CFG_TYPE_OBJECT ? '{' : '[');
1056
1057 return write_byte_f(str, buf, &len);
1058 }
1059
mpp_cfg_to_toml(MppCfgIoImpl * impl,MppCfgStrBuf * str,rk_s32 first_time)1060 static rk_s32 mpp_cfg_to_toml(MppCfgIoImpl *impl, MppCfgStrBuf *str, rk_s32 first_time)
1061 {
1062 MppCfgIoImpl *pos, *n;
1063 char buf[256];
1064 rk_s32 len = 0;
1065 rk_s32 total = sizeof(buf) - 1;
1066 rk_s32 ret = rk_ok;
1067
1068 write_indent_f(str);
1069
1070 /* leaf node write once and finish */
1071 if (impl->type < MPP_CFG_TYPE_OBJECT) {
1072 cfg_io_dbg_to("depth %d leaf write name %s type %d\n", str->depth, impl->name, impl->type);
1073
1074 if (impl->name)
1075 len += snprintf(buf + len, total - len, "%s = ", impl->name);
1076
1077 switch (impl->type) {
1078 case MPP_CFG_TYPE_NULL : {
1079 len += snprintf(buf + len, total - len, "null");
1080 } break;
1081 case MPP_CFG_TYPE_BOOL : {
1082 len += snprintf(buf + len, total - len, "%s", impl->val.b1 ? "true" : "false");
1083 } break;
1084 case MPP_CFG_TYPE_s32 : {
1085 len += snprintf(buf + len, total - len, "%d", impl->val.s32);
1086 } break;
1087 case MPP_CFG_TYPE_u32 : {
1088 len += snprintf(buf + len, total - len, "%u", impl->val.u32);
1089 } break;
1090 case MPP_CFG_TYPE_s64 : {
1091 len += snprintf(buf + len, total - len, "%lld", impl->val.s64);
1092 } break;
1093 case MPP_CFG_TYPE_u64 : {
1094 len += snprintf(buf + len, total - len, "%llu", impl->val.u64);
1095 } break;
1096 case MPP_CFG_TYPE_f32 : {
1097 len += snprintf(buf + len, total - len, "%f", impl->val.f32);
1098 } break;
1099 case MPP_CFG_TYPE_f64 : {
1100 len += snprintf(buf + len, total - len, "%lf", impl->val.f64);
1101 } break;
1102 case MPP_CFG_TYPE_STRING :
1103 case MPP_CFG_TYPE_RAW : {
1104 len += snprintf(buf + len, total - len, "\"%s\"", (char *)impl->val.str);
1105 } break;
1106 default : {
1107 mpp_loge("invalid type %d\n", impl->type);
1108 } break;
1109 }
1110
1111 if (str->depth > 1)
1112 len += snprintf(buf + len, total - len, ",\n");
1113 else
1114 len += snprintf(buf + len, total - len, "\n");
1115
1116 return write_byte_f(str, buf, &len);
1117 }
1118
1119 cfg_io_dbg_to("depth %d branch write name %s type %d\n", str->depth, impl->name, impl->type);
1120
1121 if (str->depth == 0) {
1122 ret = mpp_toml_top(impl, str);
1123 } else {
1124 ret = mpp_toml_non_top(impl, str);
1125 }
1126 if (ret)
1127 return ret;
1128
1129 if (list_empty(&impl->child))
1130 return rk_ok;
1131
1132 if (!mpp_toml_parent_is_array_table(impl, str) && !first_time)
1133 str->depth++;
1134
1135 list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) {
1136 cfg_io_dbg_to("depth %d child write name %s type %d\n", str->depth, pos->name, pos->type);
1137 ret = mpp_cfg_to_toml(pos, str, 0);
1138 if (ret)
1139 break;
1140 }
1141
1142 if (str->depth > 1)
1143 revert_comma_f(str);
1144
1145 if (!mpp_toml_parent_is_array_table(impl, str) && !first_time)
1146 str->depth--;
1147
1148 write_indent_f(str);
1149
1150 if (str->depth > 0 && !mpp_toml_parent_is_array_table(impl, str)) {
1151 if (str->depth == 1)
1152 len += snprintf(buf + len, total - len, "%c\n",
1153 impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']');
1154 else
1155 len += snprintf(buf + len, total - len, "%c,\n",
1156 impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']');
1157 }
1158
1159 return write_byte_f(str, buf, &len);
1160 }
1161
parse_number(MppCfgStrBuf * str,MppCfgType * type,MppCfgVal * val)1162 static rk_s32 parse_number(MppCfgStrBuf *str, MppCfgType *type, MppCfgVal *val)
1163 {
1164 char *buf = NULL;
1165 char tmp[64];
1166 long double value;
1167 rk_u32 i;
1168
1169 for (i = 0; i < sizeof(tmp) - 1; i++) {
1170 buf = show_byte_f(str, 0);
1171 if (!buf)
1172 break;
1173
1174 switch (buf[0]) {
1175 case '0' ... '9' :
1176 case '.' :
1177 case 'e' :
1178 case 'E' :
1179 case '+' :
1180 case '-' : {
1181 tmp[i] = buf[0];
1182 } break;
1183 default : {
1184 tmp[i] = '\0';
1185 goto done;
1186 } break;
1187 }
1188 skip_byte_f(str, 1);
1189 }
1190
1191 done:
1192 if (!i)
1193 return rk_nok;
1194
1195 errno = 0;
1196 value = strtold(tmp, NULL);
1197 if (errno) {
1198 mpp_loge_f("failed to parse number %s errno %s\n", tmp, strerror(errno));
1199 return rk_nok;
1200 }
1201
1202 if (strstr(tmp, ".")) {
1203 if (value >= FLT_MIN && value <= FLT_MAX) {
1204 *type = MPP_CFG_TYPE_f32;
1205 val->f32 = (float)value;
1206 } else {
1207 *type = MPP_CFG_TYPE_f64;
1208 val->f64 = (double)value;
1209 }
1210 } else {
1211 if (value >= INT_MIN && value <= INT_MAX) {
1212 *type = MPP_CFG_TYPE_s32;
1213 val->s32 = (int)value;
1214 } else if (value >= 0 && value <= UINT_MAX) {
1215 *type = MPP_CFG_TYPE_u32;
1216 val->u32 = (unsigned int)value;
1217 } else if (value >= (long double)LLONG_MIN && value <= (long double)LLONG_MAX) {
1218 *type = MPP_CFG_TYPE_u64;
1219 val->u64 = (unsigned long long)value;
1220 } else if (value >= 0 && value <= (long double)ULLONG_MAX) {
1221 *type = MPP_CFG_TYPE_s64;
1222 val->s64 = (long long)value;
1223 } else {
1224 mpp_loge_f("invalid number %s\n", tmp);
1225 return rk_nok;
1226 }
1227 }
1228
1229 return rk_ok;
1230 }
1231
parse_log_string(MppCfgStrBuf * str,char ** name,rk_s32 * len,rk_u32 type)1232 static rk_s32 parse_log_string(MppCfgStrBuf *str, char **name, rk_s32 *len, rk_u32 type)
1233 {
1234 char *buf = NULL;
1235 char *start = NULL;
1236 rk_s32 name_len = 0;
1237 char terminator = type ? '\"' : ' ';
1238
1239 *name = NULL;
1240 *len = 0;
1241
1242 /* skip whitespace and find first double quotes */
1243 buf = skip_ws_f(str);
1244 if (!buf)
1245 return -101;
1246
1247 if (type) {
1248 if (buf[0] != '\"')
1249 return -101;
1250
1251 buf = skip_byte_f(str, 1);
1252 if (!buf)
1253 return -102;
1254 }
1255
1256 start = buf;
1257
1258 /* find the terminator */
1259 while ((buf = show_byte_f(str, name_len)) && buf[0] != terminator) {
1260 name_len++;
1261 }
1262
1263 if (!buf || buf[0] != terminator)
1264 return -103;
1265
1266 /* find complete string skip the string and terminator */
1267 buf = skip_byte_f(str, name_len + 1);
1268 if (!buf)
1269 return -104;
1270
1271 *name = start;
1272 *len = name_len;
1273
1274 return rk_ok;
1275 }
1276
1277 static rk_s32 parse_log_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str);
1278
parse_log_array(MppCfgIoImpl * obj,MppCfgStrBuf * str)1279 static rk_s32 parse_log_array(MppCfgIoImpl *obj, MppCfgStrBuf *str)
1280 {
1281 MppCfgIoImpl *parent = obj;
1282 char *buf = NULL;
1283 rk_s32 old = str->offset;
1284 rk_s32 ret = rk_nok;
1285
1286 if (str->depth >= MAX_CFG_DEPTH) {
1287 mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH);
1288 return rk_nok;
1289 }
1290
1291 str->depth++;
1292
1293 cfg_io_dbg_from("depth %d offset %d array parse start\n", str->depth, str->offset);
1294
1295 buf = test_byte_f(str, 0);
1296 if (!buf || buf[0] != '[') {
1297 ret = -2;
1298 goto failed;
1299 }
1300
1301 buf = skip_byte_f(str, 1);
1302 if (!buf) {
1303 ret = -3;
1304 goto failed;
1305 }
1306
1307 /* skip whitespace and check the end of buffer */
1308 buf = skip_ws_f(str);
1309 if (!buf) {
1310 ret = -4;
1311 goto failed;
1312 }
1313
1314 /* check empty object */
1315 if (buf[0] == ']') {
1316 skip_byte_f(str, 1);
1317 cfg_io_dbg_from("depth %d found empty array\n", str->depth);
1318 str->depth--;
1319 return rk_ok;
1320 }
1321
1322 do {
1323 /* find colon for separater */
1324 buf = skip_ws_f(str);
1325 if (!buf) {
1326 ret = -5;
1327 goto failed;
1328 }
1329
1330 /* parse value */
1331 ret = parse_log_value(parent, NULL, str);
1332 if (ret) {
1333 ret = -6;
1334 goto failed;
1335 }
1336
1337 buf = skip_ws_f(str);
1338 if (!buf) {
1339 ret = -7;
1340 goto failed;
1341 }
1342
1343 if (buf[0] == ']')
1344 break;
1345 } while (1);
1346
1347 if (!buf || buf[0] != ']') {
1348 ret = -9;
1349 goto failed;
1350 }
1351
1352 skip_byte_f(str, 1);
1353
1354 cfg_io_dbg_from("depth %d offset %d -> %d array parse success\n",
1355 str->depth, old, str->offset);
1356
1357 str->depth--;
1358 ret = rk_ok;
1359
1360 failed:
1361 if (ret)
1362 cfg_io_dbg_from("depth %d offset %d -> %d array parse failed ret %d\n",
1363 str->depth, old, str->offset, ret);
1364
1365 return ret;
1366 }
1367
1368 static rk_s32 parse_log_object(MppCfgIoImpl *obj, MppCfgStrBuf *str);
1369
parse_log_value(MppCfgIoImpl * parent,const char * name,MppCfgStrBuf * str)1370 static rk_s32 parse_log_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str)
1371 {
1372 MppCfgObj obj = NULL;
1373 char *buf = NULL;
1374
1375 cfg_io_dbg_from("depth %d offset %d: parse value\n", str->depth, str->offset);
1376
1377 buf = test_byte_f(str, 4);
1378 if (buf && !strncmp(buf, "null", 4)) {
1379 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_NULL, NULL);
1380 mpp_cfg_add(parent, obj);
1381
1382 cfg_io_dbg_from("depth %d offset %d: get value null\n", str->depth, str->offset);
1383 skip_byte_f(str, 4);
1384 return rk_ok;
1385 }
1386
1387 if (buf && !strncmp(buf, "true", 4)) {
1388 MppCfgVal val;
1389
1390 val.b1 = 1;
1391 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val);
1392 mpp_cfg_add(parent, obj);
1393
1394 cfg_io_dbg_from("depth %d offset %d: get value true\n", str->depth, str->offset);
1395 skip_byte_f(str, 4);
1396 return rk_ok;
1397 }
1398
1399 buf = test_byte_f(str, 5);
1400 if (buf && !strncmp(buf, "false", 5)) {
1401 MppCfgVal val;
1402
1403 val.b1 = 0;
1404 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val);
1405 mpp_cfg_add(parent, obj);
1406
1407 cfg_io_dbg_from("depth %d offset %d: get value false\n", str->depth, str->offset);
1408 skip_byte_f(str, 5);
1409 return rk_ok;
1410 }
1411
1412 buf = test_byte_f(str, 0);
1413 if (buf && buf[0] == '\"') {
1414 MppCfgVal val;
1415 char *string = NULL;
1416 rk_s32 len = 0;
1417
1418 cfg_io_dbg_from("depth %d offset %d: get value string start\n", str->depth, str->offset);
1419
1420 parse_log_string(str, &string, &len, MPP_CFG_PARSER_TYPE_VALUE);
1421 if (!string)
1422 return rk_nok;
1423
1424 val.str = dup_str(string, len);
1425 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_STRING, &val);
1426 mpp_cfg_add(parent, obj);
1427 MPP_FREE(val.str);
1428
1429 cfg_io_dbg_from("depth %d offset %d: get value string success\n", str->depth, str->offset);
1430 return rk_ok;
1431 }
1432
1433 if (buf && (buf[0] == '-' || (buf[0] >= '0' && buf[0] <= '9'))) {
1434 MppCfgType type;
1435 MppCfgVal val;
1436 rk_s32 ret;
1437
1438 cfg_io_dbg_from("depth %d offset %d: get value number start\n",
1439 str->depth, str->offset);
1440
1441 ret = parse_number(str, &type, &val);
1442 if (ret)
1443 return ret;
1444
1445 mpp_cfg_get_object(&obj, name, type, &val);
1446 mpp_cfg_add(parent, obj);
1447
1448 cfg_io_dbg_from("depth %d offset %d: get value number success\n",
1449 str->depth, str->offset);
1450 return ret;
1451 }
1452
1453 if (buf && buf[0] == '{') {
1454 rk_s32 ret;
1455
1456 cfg_io_dbg_from("depth %d offset %d: get value object start\n",
1457 str->depth, str->offset);
1458
1459 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_OBJECT, NULL);
1460 mpp_cfg_add(parent, obj);
1461
1462 ret = parse_log_object(obj, str);
1463
1464 cfg_io_dbg_from("depth %d offset %d: get value object ret %d\n",
1465 str->depth, str->offset, ret);
1466 return ret;
1467 }
1468
1469 if (buf && buf[0] == '[') {
1470 rk_s32 ret;
1471
1472 cfg_io_dbg_from("depth %d offset %d: get value array start\n",
1473 str->depth, str->offset);
1474
1475 mpp_cfg_get_array(&obj, name, 0);
1476 mpp_cfg_add(parent, obj);
1477
1478 ret = parse_log_array(obj, str);
1479
1480 cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n",
1481 str->depth, str->offset, ret);
1482 return ret;
1483 }
1484
1485 return rk_nok;
1486 }
1487
parse_log_object(MppCfgIoImpl * obj,MppCfgStrBuf * str)1488 static rk_s32 parse_log_object(MppCfgIoImpl *obj, MppCfgStrBuf *str)
1489 {
1490 MppCfgIoImpl *parent = obj;
1491 char *buf = NULL;
1492 rk_s32 old = str->offset;
1493 rk_s32 ret = rk_nok;
1494
1495 if (str->depth >= MAX_CFG_DEPTH) {
1496 mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH);
1497 return rk_nok;
1498 }
1499
1500 str->depth++;
1501
1502 cfg_io_dbg_from("depth %d offset %d object parse start\n", str->depth, str->offset);
1503
1504 buf = test_byte_f(str, 0);
1505 if (!buf || buf[0] != '{') {
1506 ret = -2;
1507 goto failed;
1508 }
1509
1510 buf = skip_byte_f(str, 1);
1511 if (!buf) {
1512 ret = -3;
1513 goto failed;
1514 }
1515
1516 /* skip whitespace and check the end of buffer */
1517 buf = skip_ws_f(str);
1518 if (!buf) {
1519 ret = -4;
1520 goto failed;
1521 }
1522
1523 /* check empty object */
1524 if (buf[0] == '}') {
1525 skip_byte_f(str, 1);
1526 cfg_io_dbg_from("depth %d found empty object\n", str->depth);
1527 str->depth--;
1528 return rk_ok;
1529 }
1530
1531 do {
1532 rk_s32 name_len = 0;
1533 char *name = NULL;
1534 char *tmp = NULL;
1535
1536 /* support array without name */
1537 if (buf[0] == '[') {
1538 MppCfgObj object = NULL;
1539
1540 cfg_io_dbg_from("depth %d offset %d: get value array start\n",
1541 str->depth, str->offset);
1542
1543 mpp_cfg_get_array(&object, NULL, 0);
1544 mpp_cfg_add(parent, object);
1545
1546 ret = parse_log_array(object, str);
1547
1548 cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n",
1549 str->depth, str->offset, ret);
1550
1551 if (ret) {
1552 mpp_cfg_put_all_child(object);
1553 goto failed;
1554 }
1555
1556 goto __next;
1557 }
1558
1559 ret = parse_log_string(str, &name, &name_len, MPP_CFG_PARSER_TYPE_KEY);
1560 if (ret) {
1561 goto failed;
1562 }
1563
1564 tmp = dup_str(name, name_len);
1565 cfg_io_dbg_from("depth %d offset %d found object key %s len %d\n",
1566 str->depth, str->offset, tmp, name_len);
1567 MPP_FREE(tmp);
1568
1569 /* find colon for separater */
1570 buf = skip_ws_f(str);
1571 if (!buf || buf[0] != ':') {
1572 ret = -5;
1573 goto failed;
1574 }
1575
1576 /* skip colon */
1577 buf = skip_byte_f(str, 1);
1578 if (!buf) {
1579 ret = -6;
1580 goto failed;
1581 }
1582
1583 buf = skip_ws_f(str);
1584 if (!buf) {
1585 ret = -7;
1586 goto failed;
1587 }
1588
1589 tmp = dup_str(name, name_len);
1590 if (!tmp) {
1591 mpp_loge_f("failed to dup name\n");
1592 ret = -8;
1593 goto failed;
1594 }
1595
1596 /* parse value */
1597 ret = parse_log_value(parent, tmp, str);
1598 MPP_FREE(tmp);
1599 if (ret) {
1600 ret = -9;
1601 goto failed;
1602 }
1603 __next:
1604 buf = skip_ws_f(str);
1605 if (!buf) {
1606 ret = -10;
1607 goto failed;
1608 }
1609
1610 if (buf[0] == '}')
1611 break;
1612
1613 cfg_io_dbg_from("depth %d offset %d: get next object\n", str->depth, str->offset);
1614 } while (1);
1615
1616 skip_byte_f(str, 1);
1617
1618 cfg_io_dbg_from("depth %d offset %d -> %d object parse success\n",
1619 str->depth, old, str->offset);
1620
1621 str->depth--;
1622 ret = rk_ok;
1623
1624 failed:
1625 if (ret)
1626 cfg_io_dbg_from("depth %d offset %d -> %d object parse failed ret %d\n",
1627 str->depth, old, str->offset, ret);
1628
1629 return ret;
1630 }
1631
mpp_cfg_from_log(MppCfgObj * obj,MppCfgStrBuf * str)1632 static rk_s32 mpp_cfg_from_log(MppCfgObj *obj, MppCfgStrBuf *str)
1633 {
1634 MppCfgObj object = NULL;
1635 char *buf = NULL;
1636 rk_s32 ret = rk_ok;
1637
1638 /* skip white space and check the end of buffer */
1639 buf = skip_ws_f(str);
1640 if (!buf)
1641 return rk_nok;
1642
1643 if (buf[0] == '{') {
1644 ret = mpp_cfg_get_object(&object, NULL, MPP_CFG_TYPE_OBJECT, NULL);
1645 if (ret || !object) {
1646 mpp_loge_f("failed to create top object\n");
1647 return rk_nok;
1648 }
1649
1650 ret = parse_log_object(object, str);
1651 } else if (buf[0] == '[') {
1652 ret = mpp_cfg_get_array(&object, NULL, 0);
1653 if (ret || !object) {
1654 mpp_loge_f("failed to create top object\n");
1655 return rk_nok;
1656 }
1657
1658 ret = parse_log_array(object, str);
1659 } else {
1660 mpp_loge_f("invalid top element '%c' on offset %d\n", buf[0], str->offset);
1661 }
1662
1663 *obj = object;
1664
1665 return ret;
1666 }
1667
parse_json_string(MppCfgStrBuf * str,char ** name,rk_s32 * len)1668 static rk_s32 parse_json_string(MppCfgStrBuf *str, char **name, rk_s32 *len)
1669 {
1670 char *buf = NULL;
1671 char *start = NULL;
1672 rk_s32 name_len = 0;
1673
1674 *name = NULL;
1675 *len = 0;
1676
1677 /* skip whitespace and find first double quotes */
1678 buf = skip_ws_f(str);
1679 if (!buf || buf[0] != '\"')
1680 return -101;
1681
1682 buf = skip_byte_f(str, 1);
1683 if (!buf)
1684 return -102;
1685
1686 start = buf;
1687
1688 /* find the last double quotes */
1689 while ((buf = show_byte_f(str, name_len)) && buf[0] != '\"') {
1690 name_len++;
1691 }
1692
1693 if (!buf || buf[0] != '\"')
1694 return -103;
1695
1696 /* find complete string skip the string and double quotes */
1697 buf = skip_byte_f(str, name_len + 1);
1698 if (!buf)
1699 return -104;
1700
1701 *name = start;
1702 *len = name_len;
1703
1704 return rk_ok;
1705 }
1706
1707 static rk_s32 parse_json_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str);
1708 static rk_s32 parse_json_array(MppCfgIoImpl *obj, MppCfgStrBuf *str);
1709
parse_json_object(MppCfgIoImpl * obj,MppCfgStrBuf * str)1710 static rk_s32 parse_json_object(MppCfgIoImpl *obj, MppCfgStrBuf *str)
1711 {
1712 MppCfgIoImpl *parent = obj;
1713 char *buf = NULL;
1714 rk_s32 old = str->offset;
1715 rk_s32 ret = rk_nok;
1716
1717 if (str->depth >= MAX_CFG_DEPTH) {
1718 mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH);
1719 return rk_nok;
1720 }
1721
1722 str->depth++;
1723
1724 cfg_io_dbg_from("depth %d offset %d object parse start\n", str->depth, str->offset);
1725
1726 buf = test_byte_f(str, 0);
1727 if (!buf || buf[0] != '{') {
1728 ret = -2;
1729 goto failed;
1730 }
1731
1732 buf = skip_byte_f(str, 1);
1733 if (!buf) {
1734 ret = -3;
1735 goto failed;
1736 }
1737
1738 /* skip whitespace and check the end of buffer */
1739 buf = skip_ws_f(str);
1740 if (!buf) {
1741 ret = -4;
1742 goto failed;
1743 }
1744
1745 /* check empty object */
1746 if (buf[0] == '}') {
1747 skip_byte_f(str, 1);
1748 cfg_io_dbg_from("depth %d found empty object\n", str->depth);
1749 str->depth--;
1750 return rk_ok;
1751 }
1752
1753 do {
1754 rk_s32 name_len = 0;
1755 char *name = NULL;
1756 char *tmp = NULL;
1757
1758 if (buf[0] == '[') {
1759 MppCfgObj object = NULL;
1760
1761 cfg_io_dbg_from("depth %d offset %d: get value array start\n",
1762 str->depth, str->offset);
1763
1764 mpp_cfg_get_array(&object, NULL, 0);
1765 mpp_cfg_add(parent, object);
1766
1767 ret = parse_json_array(object, str);
1768
1769 cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n",
1770 str->depth, str->offset, ret);
1771
1772 if (ret) {
1773 mpp_cfg_put_all_child(object);
1774 goto failed;
1775 }
1776
1777 goto __next;
1778 }
1779
1780 ret = parse_json_string(str, &name, &name_len);
1781 if (ret) {
1782 goto failed;
1783 }
1784
1785 /* find colon for separater */
1786 buf = skip_ws_f(str);
1787 if (!buf || buf[0] != ':') {
1788 ret = -5;
1789 goto failed;
1790 }
1791
1792 /* skip colon */
1793 buf = skip_byte_f(str, 1);
1794 if (!buf) {
1795 ret = -6;
1796 goto failed;
1797 }
1798
1799 buf = skip_ws_f(str);
1800 if (!buf) {
1801 ret = -7;
1802 goto failed;
1803 }
1804
1805 tmp = dup_str(name, name_len);
1806 if (!tmp) {
1807 mpp_loge_f("failed to dup name\n");
1808 ret = -8;
1809 goto failed;
1810 }
1811
1812 /* parse value */
1813 ret = parse_json_value(parent, tmp, str);
1814 MPP_FREE(tmp);
1815 if (ret) {
1816 ret = -9;
1817 goto failed;
1818 }
1819 __next:
1820 buf = skip_ws_f(str);
1821 if (!buf) {
1822 ret = -10;
1823 goto failed;
1824 }
1825
1826 if (buf[0] == ',') {
1827 buf = skip_byte_f(str, 1);
1828 if (!buf) {
1829 ret = -11;
1830 goto failed;
1831 }
1832
1833 buf = skip_ws_f(str);
1834 if (buf[0] == '}')
1835 break;
1836
1837 cfg_io_dbg_from("depth %d offset %d: get next object\n", str->depth, str->offset);
1838 continue;
1839 }
1840
1841 break;
1842 } while (1);
1843
1844 buf = skip_ws_f(str);
1845 if (!buf || buf[0] != '}') {
1846 ret = -12;
1847 goto failed;
1848 }
1849
1850 skip_byte_f(str, 1);
1851
1852 cfg_io_dbg_from("depth %d offset %d -> %d object parse success\n",
1853 str->depth, old, str->offset);
1854
1855 str->depth--;
1856 ret = rk_ok;
1857
1858 failed:
1859 if (ret)
1860 cfg_io_dbg_from("depth %d offset %d -> %d object parse failed ret %d\n",
1861 str->depth, old, str->offset, ret);
1862
1863 return ret;
1864 }
1865
parse_json_array(MppCfgIoImpl * obj,MppCfgStrBuf * str)1866 static rk_s32 parse_json_array(MppCfgIoImpl *obj, MppCfgStrBuf *str)
1867 {
1868 MppCfgIoImpl *parent = obj;
1869 char *buf = NULL;
1870 rk_s32 old = str->offset;
1871 rk_s32 ret = rk_nok;
1872
1873 if (str->depth >= MAX_CFG_DEPTH) {
1874 mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH);
1875 return rk_nok;
1876 }
1877
1878 str->depth++;
1879
1880 cfg_io_dbg_from("depth %d offset %d array parse start\n", str->depth, str->offset);
1881
1882 buf = test_byte_f(str, 0);
1883 if (!buf || buf[0] != '[') {
1884 ret = -2;
1885 goto failed;
1886 }
1887
1888 buf = skip_byte_f(str, 1);
1889 if (!buf) {
1890 ret = -3;
1891 goto failed;
1892 }
1893
1894 /* skip whitespace and check the end of buffer */
1895 buf = skip_ws_f(str);
1896 if (!buf) {
1897 ret = -4;
1898 goto failed;
1899 }
1900
1901 /* check empty object */
1902 if (buf[0] == ']') {
1903 skip_byte_f(str, 1);
1904 cfg_io_dbg_from("depth %d found empty array\n", str->depth);
1905 str->depth--;
1906 return rk_ok;
1907 }
1908
1909 do {
1910 /* find colon for separater */
1911 buf = skip_ws_f(str);
1912 if (!buf) {
1913 ret = -5;
1914 goto failed;
1915 }
1916
1917 /* parse value */
1918 ret = parse_json_value(parent, NULL, str);
1919 if (ret) {
1920 ret = -6;
1921 goto failed;
1922 }
1923
1924 buf = skip_ws_f(str);
1925 if (!buf) {
1926 ret = -7;
1927 goto failed;
1928 }
1929
1930 if (buf[0] == ',') {
1931 buf = skip_byte_f(str, 1);
1932 if (!buf) {
1933 ret = -8;
1934 goto failed;
1935 }
1936
1937 buf = skip_ws_f(str);
1938 if (buf[0] == '}')
1939 break;
1940
1941 cfg_io_dbg_from("depth %d offset %d: get next array\n", str->depth, str->offset);
1942 continue;
1943 }
1944 break;
1945 } while (1);
1946
1947 buf = skip_ws_f(str);
1948 if (!buf || buf[0] != ']') {
1949 ret = -9;
1950 goto failed;
1951 }
1952
1953 skip_byte_f(str, 1);
1954
1955 cfg_io_dbg_from("depth %d offset %d -> %d array parse success\n",
1956 str->depth, old, str->offset);
1957
1958 str->depth--;
1959 ret = rk_ok;
1960
1961 failed:
1962 if (ret)
1963 cfg_io_dbg_from("depth %d offset %d -> %d array parse failed ret %d\n",
1964 str->depth, old, str->offset, ret);
1965
1966 return ret;
1967 }
1968
parse_json_value(MppCfgIoImpl * parent,const char * name,MppCfgStrBuf * str)1969 static rk_s32 parse_json_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str)
1970 {
1971 MppCfgObj obj = NULL;
1972 char *buf = NULL;
1973
1974 cfg_io_dbg_from("depth %d offset %d: parse value\n", str->depth, str->offset);
1975
1976 buf = test_byte_f(str, 4);
1977 if (buf && !strncmp(buf, "null", 4)) {
1978 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_NULL, NULL);
1979 mpp_cfg_add(parent, obj);
1980
1981 cfg_io_dbg_from("depth %d offset %d: get value null\n", str->depth, str->offset);
1982 skip_byte_f(str, 4);
1983 return rk_ok;
1984 }
1985
1986 if (buf && !strncmp(buf, "true", 4)) {
1987 MppCfgVal val;
1988
1989 val.b1 = 1;
1990 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val);
1991 mpp_cfg_add(parent, obj);
1992
1993 cfg_io_dbg_from("depth %d offset %d: get value true\n", str->depth, str->offset);
1994 skip_byte_f(str, 4);
1995 return rk_ok;
1996 }
1997
1998 buf = test_byte_f(str, 5);
1999 if (buf && !strncmp(buf, "false", 5)) {
2000 MppCfgVal val;
2001
2002 val.b1 = 0;
2003 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val);
2004 mpp_cfg_add(parent, obj);
2005
2006 cfg_io_dbg_from("depth %d offset %d: get value false\n", str->depth, str->offset);
2007 skip_byte_f(str, 5);
2008 return rk_ok;
2009 }
2010
2011 buf = test_byte_f(str, 0);
2012 if (buf && buf[0] == '\"') {
2013 MppCfgVal val;
2014 char *string = NULL;
2015 rk_s32 len = 0;
2016
2017 cfg_io_dbg_from("depth %d offset %d: get value string start\n", str->depth, str->offset);
2018
2019 parse_json_string(str, &string, &len);
2020 if (!string)
2021 return rk_nok;
2022
2023 val.str = dup_str(string, len);
2024 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_STRING, &val);
2025 mpp_cfg_add(parent, obj);
2026 MPP_FREE(val.str);
2027
2028 cfg_io_dbg_from("depth %d offset %d: get value string success\n", str->depth, str->offset);
2029 return rk_ok;
2030 }
2031
2032 if (buf && (buf[0] == '-' || (buf[0] >= '0' && buf[0] <= '9'))) {
2033 MppCfgType type;
2034 MppCfgVal val;
2035 rk_s32 ret;
2036
2037 cfg_io_dbg_from("depth %d offset %d: get value number start\n",
2038 str->depth, str->offset);
2039
2040 ret = parse_number(str, &type, &val);
2041 if (ret)
2042 return ret;
2043
2044 mpp_cfg_get_object(&obj, name, type, &val);
2045 mpp_cfg_add(parent, obj);
2046
2047 cfg_io_dbg_from("depth %d offset %d: get value number success\n",
2048 str->depth, str->offset);
2049 return ret;
2050 }
2051
2052 if (buf && buf[0] == '{') {
2053 rk_s32 ret;
2054
2055 cfg_io_dbg_from("depth %d offset %d: get value object start\n",
2056 str->depth, str->offset);
2057
2058 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_OBJECT, NULL);
2059 mpp_cfg_add(parent, obj);
2060
2061 ret = parse_json_object(obj, str);
2062
2063 cfg_io_dbg_from("depth %d offset %d: get value object ret %d\n",
2064 str->depth, str->offset, ret);
2065 return ret;
2066 }
2067
2068 if (buf && buf[0] == '[') {
2069 rk_s32 ret;
2070
2071 cfg_io_dbg_from("depth %d offset %d: get value array start\n",
2072 str->depth, str->offset);
2073
2074 mpp_cfg_get_array(&obj, name, 0);
2075 mpp_cfg_add(parent, obj);
2076
2077 ret = parse_json_array(obj, str);
2078
2079 cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n",
2080 str->depth, str->offset, ret);
2081 return ret;
2082 }
2083
2084 return rk_nok;
2085 }
2086
mpp_cfg_from_json(MppCfgObj * obj,MppCfgStrBuf * str)2087 static rk_s32 mpp_cfg_from_json(MppCfgObj *obj, MppCfgStrBuf *str)
2088 {
2089 MppCfgObj object = NULL;
2090 char *buf = NULL;
2091 rk_s32 ret = rk_ok;
2092
2093 /* skip UTF-8 */
2094 buf = test_byte_f(str, 4);
2095 if (buf && !strncmp(buf, "\xEF\xBB\xBF", 3))
2096 skip_byte_f(str, 3);
2097
2098 /* skip white space and check the end of buffer */
2099 buf = skip_ws_f(str);
2100 if (!buf)
2101 return rk_nok;
2102
2103 if (buf[0] == '{') {
2104 ret = mpp_cfg_get_object(&object, NULL, MPP_CFG_TYPE_OBJECT, NULL);
2105 if (ret || !object) {
2106 mpp_loge_f("failed to create top object\n");
2107 return rk_nok;
2108 }
2109
2110 ret = parse_json_object(object, str);
2111 } else if (buf[0] == '[') {
2112 ret = mpp_cfg_get_array(&object, NULL, 0);
2113 if (ret || !object) {
2114 mpp_loge_f("failed to create top object\n");
2115 return rk_nok;
2116 }
2117
2118 ret = parse_json_array(object, str);
2119 } else {
2120 mpp_loge_f("invalid top element '%c' on offset %d\n", buf[0], str->offset);
2121 }
2122
2123 *obj = object;
2124
2125 return ret;
2126 }
2127
parse_toml_nested_table(MppCfgIoImpl * root,MppCfgObj * object,char * name,rk_s32 name_len)2128 static rk_s32 parse_toml_nested_table(MppCfgIoImpl *root, MppCfgObj *object, char *name,
2129 rk_s32 name_len)
2130 {
2131 MppCfgObj obj = NULL;
2132 MppCfgIoImpl *parent = root;
2133 rk_s32 i = 0;
2134 char sub_name_offset = 0;
2135 char sub_name_len = 0;
2136 char sub_name[256] = {0};
2137 rk_s32 ret = rk_ok;
2138
2139 for (i = 0; i <= name_len; i++) {
2140 if (name[i] == '.' || name[i] == '\0') {
2141 sub_name_len = i;
2142 memcpy(sub_name, name, sub_name_len);
2143 sub_name[i] = '\0';
2144 obj = NULL;
2145 mpp_cfg_find(&obj, root, sub_name, MPP_CFG_STR_FMT_TOML);
2146 if (!obj) {
2147 memcpy(sub_name, name + sub_name_offset, sub_name_len - sub_name_offset);
2148 sub_name[sub_name_len - sub_name_offset] = '\0';
2149 ret = mpp_cfg_get_object(&obj, sub_name, MPP_CFG_TYPE_OBJECT, NULL);
2150 if (ret || !obj) {
2151 mpp_loge_f("failed to create object %s\n", name);
2152 ret = -101;
2153 return ret;
2154 }
2155 mpp_cfg_add(parent, obj);
2156 }
2157
2158 parent = obj;
2159 sub_name_offset = i + 1;
2160 }
2161 }
2162
2163 *object = obj;
2164
2165 return ret;
2166 }
2167
parse_toml_nested_array_table(MppCfgIoImpl * root,MppCfgObj * object,char * name,rk_s32 name_len)2168 static rk_s32 parse_toml_nested_array_table(MppCfgIoImpl *root, MppCfgObj *object, char *name,
2169 rk_s32 name_len)
2170 {
2171 MppCfgObj obj = NULL;
2172 MppCfgIoImpl *parent = root;
2173 rk_s32 i = 0;
2174 char sub_name_offset = 0;
2175 char sub_name_len = 0;
2176 char sub_name[256] = {0};
2177 rk_s32 ret = rk_ok;
2178
2179 for (i = 0; i <= name_len; i++) {
2180 if (name[i] == '.' || name[i] == '\0') {
2181 sub_name_len = i;
2182 memcpy(sub_name, name, sub_name_len);
2183 sub_name[i] = '\0';
2184 obj = NULL;
2185 mpp_cfg_find(&obj, root, sub_name, MPP_CFG_STR_FMT_TOML);
2186 if (!obj) {
2187 memcpy(sub_name, name + sub_name_offset, sub_name_len - sub_name_offset);
2188 sub_name[sub_name_len - sub_name_offset] = '\0';
2189
2190 /* if parent type is array, need get its last child as new parent */
2191 if (parent->type == MPP_CFG_TYPE_ARRAY) {
2192 MppCfgIoImpl *child_pos, *child_n;
2193 MppCfgIoImpl *last_child = NULL;
2194 list_for_each_entry_safe(child_pos, child_n, &parent->child, MppCfgIoImpl, list) {
2195 if (!child_pos->name && child_pos->type == MPP_CFG_TYPE_OBJECT) {
2196 last_child = child_pos;
2197 }
2198 }
2199 if (!last_child) {
2200 mpp_loge_f("failed to find last child\n");
2201 ret = -111;
2202 return ret;
2203 }
2204 parent = last_child;
2205 }
2206 if (name[i] == '\0') {
2207 ret = mpp_cfg_get_array(&obj, sub_name, 0);
2208 if (ret || !obj) {
2209 mpp_loge_f("failed to create object %s\n", name);
2210 ret = -112;
2211 return ret;
2212 }
2213 mpp_cfg_add(parent, obj);
2214 } else {
2215 ret = mpp_cfg_get_object(&obj, sub_name, MPP_CFG_TYPE_OBJECT, NULL);
2216 if (ret || !obj) {
2217 mpp_loge_f("failed to create nested object %s\n", name);
2218 ret = -113;
2219 return ret;
2220 }
2221 mpp_cfg_add(parent, obj);
2222 }
2223 }
2224
2225 parent = obj;
2226 sub_name_offset = i + 1;
2227 }
2228 }
2229
2230 *object = obj;
2231
2232 return ret;
2233 }
2234
parse_toml_string(MppCfgStrBuf * str,char ** name,rk_s32 * len,rk_u32 type)2235 static rk_s32 parse_toml_string(MppCfgStrBuf *str, char **name, rk_s32 *len, rk_u32 type)
2236 {
2237 char *buf = NULL;
2238 char *start = NULL;
2239 rk_s32 name_len = 0;
2240 char terminator;
2241
2242 *name = NULL;
2243 *len = 0;
2244
2245 /* skip whitespace and find first double quotes */
2246 buf = skip_ws_f(str);
2247 if (!buf)
2248 return -201;
2249
2250 if (type == MPP_CFG_PARSER_TYPE_VALUE) {
2251 terminator = '\"';
2252 if (buf[0] != '\"')
2253 return -202;
2254
2255 buf = skip_byte_f(str, 1);
2256 if (!buf)
2257 return -203;
2258 } else if (type == MPP_CFG_PARSER_TYPE_KEY) {
2259 terminator = ' ';
2260 } else if (type == MPP_CFG_PARSER_TYPE_TABLE || type == MPP_CFG_PARSER_TYPE_ARRAY_TABLE) {
2261 terminator = ']';
2262 } else {
2263 return -204;
2264 }
2265
2266 start = buf;
2267
2268 /* find the terminator */
2269 while ((buf = show_byte_f(str, name_len)) && buf[0] != terminator) {
2270 name_len++;
2271 }
2272
2273 if (!buf || buf[0] != terminator)
2274 return -205;
2275
2276 /* find complete string skip the string */
2277 if (type == MPP_CFG_PARSER_TYPE_VALUE)
2278 buf = skip_byte_f(str, name_len + 1);
2279 else
2280 buf = skip_byte_f(str, name_len);
2281 if (!buf)
2282 return -206;
2283
2284 *name = start;
2285 *len = name_len;
2286
2287 return rk_ok;
2288 }
2289
2290 static rk_s32 parse_toml_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str);
2291 static rk_s32 parse_toml_object(MppCfgIoImpl *parent, MppCfgStrBuf *str, rk_s32 is_brace);
2292
parse_toml_array(MppCfgIoImpl * obj,MppCfgStrBuf * str)2293 static rk_s32 parse_toml_array(MppCfgIoImpl *obj, MppCfgStrBuf *str)
2294 {
2295 MppCfgIoImpl *parent = obj;
2296 char *buf = NULL;
2297 rk_s32 old = str->offset;
2298 rk_s32 ret = rk_nok;
2299
2300 if (str->depth >= MAX_CFG_DEPTH) {
2301 mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH);
2302 return rk_nok;
2303 }
2304
2305 str->depth++;
2306
2307 cfg_io_dbg_from("depth %d offset %d array parse start\n", str->depth, str->offset);
2308
2309 buf = test_byte_f(str, 0);
2310 if (!buf || buf[0] != '[') {
2311 ret = -61;
2312 goto failed;
2313 }
2314
2315 buf = skip_byte_f(str, 1);
2316 if (!buf) {
2317 ret = -62;
2318 goto failed;
2319 }
2320
2321 /* skip whitespace and check the end of buffer */
2322 buf = skip_ws_f(str);
2323 if (!buf) {
2324 ret = -63;
2325 goto failed;
2326 }
2327
2328 /* check empty object */
2329 if (buf[0] == ']') {
2330 skip_byte_f(str, 1);
2331 cfg_io_dbg_from("depth %d found empty array\n", str->depth);
2332 str->depth--;
2333 return rk_ok;
2334 }
2335
2336 do {
2337 buf = skip_ws_f(str);
2338 if (!buf) {
2339 ret = -64;
2340 goto failed;
2341 }
2342
2343 /* parse value */
2344 ret = parse_toml_value(parent, NULL, str);
2345 if (ret) {
2346 ret = -65;
2347 goto failed;
2348 }
2349
2350 buf = skip_ws_f(str);
2351 if (!buf) {
2352 ret = -66;
2353 goto failed;
2354 }
2355
2356 if (buf[0] == ',') {
2357 buf = skip_byte_f(str, 1);
2358 if (!buf) {
2359 ret = -67;
2360 goto failed;
2361 }
2362
2363 buf = skip_ws_f(str);
2364 if (buf[0] == '}')
2365 break;
2366
2367 cfg_io_dbg_from("depth %d offset %d: get next array\n", str->depth, str->offset);
2368 continue;
2369 }
2370 break;
2371 } while (1);
2372
2373 if (!buf || buf[0] != ']') {
2374 ret = -68;
2375 goto failed;
2376 }
2377
2378 skip_byte_f(str, 1);
2379
2380 cfg_io_dbg_from("depth %d offset %d -> %d array parse success\n",
2381 str->depth, old, str->offset);
2382
2383 str->depth--;
2384 ret = rk_ok;
2385
2386 failed:
2387 if (ret)
2388 cfg_io_dbg_from("depth %d offset %d -> %d array parse failed ret %d\n",
2389 str->depth, old, str->offset, ret);
2390
2391 return ret;
2392 }
2393
parse_toml_value(MppCfgIoImpl * parent,const char * name,MppCfgStrBuf * str)2394 static rk_s32 parse_toml_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str)
2395 {
2396 MppCfgObj obj = NULL;
2397 char *buf = NULL;
2398
2399 cfg_io_dbg_from("depth %d offset %d: parse value\n", str->depth, str->offset);
2400
2401 buf = test_byte_f(str, 4);
2402 if (buf && !strncmp(buf, "null", 4)) {
2403 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_NULL, NULL);
2404 mpp_cfg_add(parent, obj);
2405
2406 cfg_io_dbg_from("depth %d offset %d: get value null\n", str->depth, str->offset);
2407 skip_byte_f(str, 4);
2408 return rk_ok;
2409 }
2410
2411 if (buf && !strncmp(buf, "true", 4)) {
2412 MppCfgVal val;
2413
2414 val.b1 = 1;
2415 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val);
2416 mpp_cfg_add(parent, obj);
2417
2418 cfg_io_dbg_from("depth %d offset %d: get value true\n", str->depth, str->offset);
2419 skip_byte_f(str, 4);
2420 return rk_ok;
2421 }
2422
2423 buf = test_byte_f(str, 5);
2424 if (buf && !strncmp(buf, "false", 5)) {
2425 MppCfgVal val;
2426
2427 val.b1 = 0;
2428 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val);
2429 mpp_cfg_add(parent, obj);
2430
2431 cfg_io_dbg_from("depth %d offset %d: get value false\n", str->depth, str->offset);
2432 skip_byte_f(str, 5);
2433 return rk_ok;
2434 }
2435
2436 buf = test_byte_f(str, 3);
2437 if (buf && !strncmp(buf, "\"\"\"", 3)) {
2438 MppCfgVal val;
2439 char *string = NULL;
2440 rk_s32 len = 0;
2441
2442 skip_byte_f(str, 2);
2443 cfg_io_dbg_from("depth %d offset %d: get value multi line string start\n", str->depth, str->offset);
2444
2445 parse_toml_string(str, &string, &len, MPP_CFG_PARSER_TYPE_VALUE);
2446 if (!string)
2447 return rk_nok;
2448 buf = test_byte_f(str, 1);
2449 if (!buf || strncmp(buf, "\"\"", 2)) {
2450 return rk_nok;
2451 }
2452 skip_byte_f(str, 2);
2453
2454 val.str = dup_str(string, len);
2455 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_STRING, &val);
2456 mpp_cfg_add(parent, obj);
2457 MPP_FREE(val.str);
2458
2459 cfg_io_dbg_from("depth %d offset %d: get value multi line string success\n", str->depth, str->offset);
2460 return rk_ok;
2461 }
2462
2463 buf = test_byte_f(str, 0);
2464 if (buf && buf[0] == '\"') {
2465 MppCfgVal val;
2466 char *string = NULL;
2467 rk_s32 len = 0;
2468
2469 cfg_io_dbg_from("depth %d offset %d: get value string start\n", str->depth, str->offset);
2470
2471 parse_toml_string(str, &string, &len, MPP_CFG_PARSER_TYPE_VALUE);
2472 if (!string)
2473 return rk_nok;
2474
2475 val.str = dup_str(string, len);
2476 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_STRING, &val);
2477 mpp_cfg_add(parent, obj);
2478 MPP_FREE(val.str);
2479
2480 cfg_io_dbg_from("depth %d offset %d: get value string success\n", str->depth, str->offset);
2481 return rk_ok;
2482 }
2483
2484 if (buf && (buf[0] == '-' || (buf[0] >= '0' && buf[0] <= '9'))) {
2485 MppCfgType type;
2486 MppCfgVal val;
2487 rk_s32 ret;
2488
2489 cfg_io_dbg_from("depth %d offset %d: get value number start\n",
2490 str->depth, str->offset);
2491
2492 ret = parse_number(str, &type, &val);
2493 if (ret)
2494 return ret;
2495
2496 mpp_cfg_get_object(&obj, name, type, &val);
2497 mpp_cfg_add(parent, obj);
2498
2499 cfg_io_dbg_from("depth %d offset %d: get value number success\n",
2500 str->depth, str->offset);
2501 return ret;
2502 }
2503
2504 if (buf && buf[0] == '{') {
2505 rk_s32 ret;
2506
2507 cfg_io_dbg_from("depth %d offset %d: get value object start\n",
2508 str->depth, str->offset);
2509
2510 mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_OBJECT, NULL);
2511 mpp_cfg_add(parent, obj);
2512
2513 ret = parse_toml_object(obj, str, 1);
2514
2515 cfg_io_dbg_from("depth %d offset %d: get value object ret %d\n",
2516 str->depth, str->offset, ret);
2517 return ret;
2518 }
2519
2520 if (buf && buf[0] == '[') {
2521 rk_s32 ret;
2522
2523 cfg_io_dbg_from("depth %d offset %d: get value array start\n",
2524 str->depth, str->offset);
2525
2526 mpp_cfg_get_array(&obj, name, 0);
2527 mpp_cfg_add(parent, obj);
2528
2529 ret = parse_toml_array(obj, str);
2530
2531 cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n",
2532 str->depth, str->offset, ret);
2533 return ret;
2534 }
2535
2536 return rk_nok;
2537 }
2538
parse_toml_object(MppCfgIoImpl * parent,MppCfgStrBuf * str,rk_s32 is_brace)2539 static rk_s32 parse_toml_object(MppCfgIoImpl *parent, MppCfgStrBuf *str, rk_s32 is_brace)
2540 {
2541 char *buf = NULL;
2542 rk_s32 ret = rk_nok;
2543 rk_s32 old = str->offset;
2544
2545 if (str->depth >= MAX_CFG_DEPTH) {
2546 mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH);
2547 return rk_nok;
2548 }
2549
2550 str->depth++;
2551 /* skip whitespace and check the end of buffer */
2552 if (is_brace) {
2553 buf = test_byte_f(str, 0);
2554 if (!buf || buf[0] != '{') {
2555 ret = -31;
2556 goto failed;
2557 }
2558
2559 buf = skip_byte_f(str, 1);
2560 if (!buf) {
2561 ret = -32;
2562 goto failed;
2563 }
2564
2565 /* skip whitespace and check the end of buffer */
2566 buf = skip_ws_f(str);
2567 if (!buf) {
2568 ret = -33;
2569 goto failed;
2570 }
2571
2572 /* check empty object */
2573 if (buf[0] == '}') {
2574 skip_byte_f(str, 1);
2575 cfg_io_dbg_from("depth %d found empty object\n", str->depth);
2576 str->depth--;
2577 return rk_ok;
2578 }
2579 } else {
2580 buf = skip_ws_f(str);
2581 if (!buf) {
2582 ret = -34;
2583 goto failed;
2584 }
2585 }
2586
2587 do {
2588 rk_s32 name_len = 0;
2589 char *name = NULL;
2590 char *tmp = NULL;
2591
2592 if (buf[0] == '[') {
2593 MppCfgObj object = NULL;
2594
2595 cfg_io_dbg_from("depth %d offset %d: get value array start\n",
2596 str->depth, str->offset);
2597
2598 mpp_cfg_get_array(&object, NULL, 0);
2599 mpp_cfg_add(parent, object);
2600
2601 ret = parse_toml_array(object, str);
2602
2603 cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n",
2604 str->depth, str->offset, ret);
2605
2606 if (ret) {
2607 mpp_cfg_put_all_child(object);
2608 goto failed;
2609 }
2610
2611 goto __next;
2612 }
2613
2614 ret = parse_toml_string(str, &name, &name_len, MPP_CFG_PARSER_TYPE_KEY);
2615 if (ret) {
2616 ret = -35;
2617 goto failed;
2618 }
2619
2620 /* find equal for separater */
2621 buf = skip_ws_f(str);
2622 if (!buf || buf[0] != '=') {
2623 ret = -36;
2624 goto failed;
2625 }
2626
2627 /* skip equal */
2628 buf = skip_byte_f(str, 1);
2629 if (!buf) {
2630 ret = -37;
2631 goto failed;
2632 }
2633
2634 buf = skip_ws_f(str);
2635 if (!buf) {
2636 ret = -38;
2637 goto failed;
2638 }
2639
2640 tmp = dup_str(name, name_len);
2641 if (!tmp) {
2642 mpp_loge_f("failed to dup name\n");
2643 ret = -39;
2644 goto failed;
2645 }
2646
2647 /* parse value */
2648 ret = parse_toml_value(parent, tmp, str);
2649 MPP_FREE(tmp);
2650 if (ret) {
2651 ret = -40;
2652 goto failed;
2653 }
2654 __next:
2655 buf = skip_ws_f(str);
2656 if (!buf || buf[0] == '[' || buf[0] == '}')
2657 break;
2658
2659 if (buf[0] == ',') {
2660 buf = skip_byte_f(str, 1);
2661 if (!buf) {
2662 ret = -41;
2663 goto failed;
2664 }
2665
2666 buf = skip_ws_f(str);
2667 if (buf[0] == '[' || buf[0] == '}')
2668 break;
2669
2670 cfg_io_dbg_from("depth %d offset %d: get next object\n", str->depth, str->offset);
2671 }
2672 } while (1);
2673
2674 if (is_brace) {
2675 if (buf && buf[0] == '}')
2676 skip_byte_f(str, 1);
2677 else {
2678 ret = -42;
2679 goto failed;
2680 }
2681 }
2682
2683 cfg_io_dbg_from("depth %d offset %d -> %d object parse success\n",
2684 str->depth, old, str->offset);
2685
2686 str->depth--;
2687 ret = rk_ok;
2688
2689 failed:
2690 if (ret)
2691 cfg_io_dbg_from("depth %d offset %d -> %d object parse failed ret %d\n",
2692 str->depth, old, str->offset, ret);
2693
2694 return ret;
2695 }
2696
parse_toml_table(MppCfgIoImpl * parent,MppCfgStrBuf * str)2697 static rk_s32 parse_toml_table(MppCfgIoImpl *parent, MppCfgStrBuf *str)
2698 {
2699 MppCfgObj obj = NULL;
2700 char *buf = NULL;
2701 rk_s32 ret = rk_nok;
2702 rk_s32 name_len = 0;
2703 char *name = NULL;
2704 char *tmp = NULL;
2705
2706 ret = parse_toml_string(str, &name, &name_len, MPP_CFG_PARSER_TYPE_TABLE);
2707 if (ret) {
2708 ret = -11;
2709 goto failed;
2710 }
2711
2712 tmp = dup_str(name, name_len);
2713 if (!tmp) {
2714 mpp_loge_f("failed to dup tmp\n");
2715 ret = -12;
2716 goto failed;
2717 }
2718
2719 if (strchr(tmp, '.')) {
2720 ret = parse_toml_nested_table(parent, &obj, tmp, name_len);
2721 MPP_FREE(tmp);
2722 if (ret || !obj) {
2723 return ret;
2724 }
2725 } else {
2726 ret = mpp_cfg_get_object(&obj, tmp, MPP_CFG_TYPE_OBJECT, NULL);
2727 MPP_FREE(tmp);
2728 if (ret || !obj) {
2729 mpp_loge_f("failed to create object %s\n", tmp);
2730 ret = -13;
2731 goto failed;
2732 }
2733 mpp_cfg_add(parent, obj);
2734 }
2735
2736 buf = test_byte_f(str, 0);
2737 if (!buf || buf[0] != ']') {
2738 ret = -14;
2739 goto failed;
2740 }
2741
2742 buf = skip_byte_f(str, 1);
2743 if (!buf) {
2744 ret = -15;
2745 goto failed;
2746 }
2747
2748 buf = skip_ws_f(str);
2749 if (!buf)
2750 return rk_nok;
2751
2752 if (buf[0] == '[')
2753 ret = rk_ok;
2754 else
2755 ret = parse_toml_object(obj, str, 0);
2756
2757 failed:
2758 if (ret)
2759 cfg_io_dbg_from("table parse failed ret %d\n", ret);
2760
2761 return ret;
2762 }
2763
parse_toml_array_table(MppCfgIoImpl * parent,MppCfgStrBuf * str)2764 static rk_s32 parse_toml_array_table(MppCfgIoImpl *parent, MppCfgStrBuf *str)
2765 {
2766 MppCfgObj obj = NULL;
2767 char *buf = NULL;
2768 rk_s32 ret = rk_nok;
2769 rk_s32 name_len = 0;
2770 char *name = NULL;
2771 char *tmp = NULL;
2772
2773 ret = parse_toml_string(str, &name, &name_len, MPP_CFG_PARSER_TYPE_ARRAY_TABLE);
2774 if (ret) {
2775 ret = -22;
2776 goto failed;
2777 }
2778
2779 tmp = dup_str(name, name_len);
2780 if (!tmp) {
2781 mpp_loge_f("failed to dup tmp\n");
2782 ret = -23;
2783 goto failed;
2784 }
2785
2786 if (strchr(tmp, '.')) {
2787 ret = parse_toml_nested_array_table(parent, &obj, tmp, name_len);
2788 MPP_FREE(tmp);
2789 if (ret || !obj) {
2790 return ret;
2791 }
2792 } else {
2793 mpp_cfg_find(&obj, parent, tmp, MPP_CFG_STR_FMT_TOML);
2794 if (!obj) {
2795 ret = mpp_cfg_get_array(&obj, tmp, 0);
2796 MPP_FREE(tmp);
2797 if (ret || !obj) {
2798 mpp_loge_f("failed to create object %s\n", tmp);
2799 ret = -24;
2800 goto failed;
2801 }
2802 mpp_cfg_add(parent, obj);
2803 } else {
2804 MPP_FREE(tmp);
2805 }
2806 }
2807
2808 /* array object need create object as child */
2809 parent = obj;
2810 obj = NULL;
2811 mpp_cfg_get_object(&obj, NULL, MPP_CFG_TYPE_OBJECT, NULL);
2812 mpp_cfg_add(parent, obj);
2813
2814 buf = test_byte_f(str, 1);
2815 if (!buf || strncmp(buf, "]]", 2)) {
2816 ret = -25;
2817 goto failed;
2818 }
2819
2820 buf = skip_byte_f(str, 2);
2821 if (!buf) {
2822 ret = -26;
2823 goto failed;
2824 }
2825
2826 buf = skip_ws_f(str);
2827 if (!buf)
2828 return rk_nok;
2829
2830 if (buf[0] == '[')
2831 ret = rk_ok;
2832 else
2833 ret = parse_toml_object(obj, str, 0);
2834
2835 failed:
2836 if (ret)
2837 cfg_io_dbg_from("array table parse failed ret %d\n", ret);
2838 return ret;
2839 }
2840
parse_toml_section(MppCfgIoImpl * parent,MppCfgStrBuf * str)2841 static rk_s32 parse_toml_section(MppCfgIoImpl *parent, MppCfgStrBuf *str)
2842 {
2843 char *buf = NULL;
2844 rk_s32 ret = rk_nok;
2845 rk_s32 old = str->offset;
2846
2847 if (str->depth >= MAX_CFG_DEPTH) {
2848 mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH);
2849 return rk_nok;
2850 }
2851
2852 buf = test_byte_f(str, 0);
2853 if (!buf) {
2854 ret = -2;
2855 goto failed;
2856 }
2857
2858 if (buf[0] == '[') {
2859 str->depth++;
2860
2861 buf = skip_byte_f(str, 1);
2862 if (!buf) {
2863 ret = -3;
2864 goto failed;
2865 }
2866 if (buf[0] != '[') {
2867 ret = parse_toml_table(parent, str);
2868 if (ret)
2869 goto failed;
2870 } else {
2871 buf = skip_byte_f(str, 1);
2872 if (!buf) {
2873 ret = -4;
2874 goto failed;
2875 }
2876
2877 ret = parse_toml_array_table(parent, str);
2878 if (ret)
2879 goto failed;
2880 }
2881 str->depth--;
2882 } else {
2883 ret = parse_toml_object(parent, str, 0);
2884 if (ret)
2885 goto failed;
2886 }
2887 cfg_io_dbg_from("depth %d offset %d -> %d section parse success\n",
2888 str->depth, old, str->offset);
2889
2890 ret = rk_ok;
2891
2892 failed:
2893 if (ret)
2894 cfg_io_dbg_from("depth %d offset %d -> %d section parse failed ret %d\n",
2895 str->depth, old, str->offset, ret);
2896
2897 return ret;
2898 }
2899
mpp_cfg_from_toml(MppCfgObj * obj,MppCfgStrBuf * str)2900 static rk_s32 mpp_cfg_from_toml(MppCfgObj *obj, MppCfgStrBuf *str)
2901 {
2902 MppCfgObj object = NULL;
2903 char *buf = NULL;
2904 rk_s32 ret = rk_ok;
2905
2906 /* skip white space and check the end of buffer */
2907 buf = skip_ws_f(str);
2908 if (!buf)
2909 return rk_nok;
2910
2911 ret = mpp_cfg_get_object(&object, NULL, MPP_CFG_TYPE_OBJECT, NULL);
2912 if (ret || !object) {
2913 mpp_loge_f("failed to create top object\n");
2914 return rk_nok;
2915 }
2916
2917 do {
2918 /* parse section */
2919 ret = parse_toml_section(object, str);
2920 if (ret) {
2921 mpp_loge_f("failed to parse section, ret : %d.\n", ret);
2922 return rk_nok;
2923 }
2924
2925 buf = skip_ws_f(str);
2926 if (!buf)
2927 break;
2928 } while (1);
2929
2930 *obj = object;
2931
2932 return ret;
2933 }
2934
mpp_cfg_dump(MppCfgObj obj,const char * func)2935 void mpp_cfg_dump(MppCfgObj obj, const char *func)
2936 {
2937 MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
2938 MppCfgStrBuf str;
2939 rk_s32 ret;
2940
2941 if (!obj) {
2942 mpp_loge_f("invalid param obj %p at %s\n", obj, func);
2943 return;
2944 }
2945
2946 mpp_logi_f("obj %s - %p at %s\n", impl->name ? impl->name : "n/a", impl, func);
2947
2948 str.buf_size = 4096;
2949 str.buf = mpp_malloc_size(void, str.buf_size);
2950 str.offset = 0;
2951 str.depth = 0;
2952 str.type = MPP_CFG_STR_FMT_LOG;
2953
2954 ret = mpp_cfg_to_log(impl, &str);
2955 if (ret)
2956 mpp_loge_f("failed to get log buffer\n");
2957 else
2958 mpp_cfg_print_string(str.buf);
2959
2960 MPP_FREE(str.buf);
2961 }
2962
mpp_cfg_to_string(MppCfgObj obj,MppCfgStrFmt fmt,char ** buf)2963 rk_s32 mpp_cfg_to_string(MppCfgObj obj, MppCfgStrFmt fmt, char **buf)
2964 {
2965 MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
2966 MppCfgStrBuf str;
2967 rk_s32 ret = rk_nok;
2968
2969 if (!obj || !buf || fmt >= MPP_CFG_STR_FMT_BUTT) {
2970 mpp_loge_f("invalid param obj %p fmt %d buf %p\n", obj, fmt, buf);
2971 return ret;
2972 }
2973
2974 mpp_env_get_u32("mpp_cfg_io_debug", &mpp_cfg_io_debug, mpp_cfg_io_debug);
2975
2976 str.buf_size = 4096;
2977 str.buf = mpp_malloc_size(void, str.buf_size);
2978 str.offset = 0;
2979 str.depth = 0;
2980 str.type = fmt;
2981
2982 switch (fmt) {
2983 case MPP_CFG_STR_FMT_LOG : {
2984 ret = mpp_cfg_to_log(impl, &str);
2985 } break;
2986 case MPP_CFG_STR_FMT_JSON : {
2987 ret = mpp_cfg_to_json(impl, &str);
2988 } break;
2989 case MPP_CFG_STR_FMT_TOML : {
2990 ret = mpp_cfg_to_toml(impl, &str, 1);
2991 } break;
2992 default : {
2993 mpp_loge_f("invalid formoffset %d\n", fmt);
2994 } break;
2995 }
2996
2997 if (ret) {
2998 mpp_loge_f("%p %s failed to get string buffer\n", impl, impl->name);
2999 MPP_FREE(str.buf);
3000 }
3001
3002 *buf = str.buf;
3003 return ret;
3004 }
3005
mpp_cfg_from_string(MppCfgObj * obj,MppCfgStrFmt fmt,const char * buf)3006 rk_s32 mpp_cfg_from_string(MppCfgObj *obj, MppCfgStrFmt fmt, const char *buf)
3007 {
3008 MppCfgObj object = NULL;
3009 rk_s32 size;
3010 rk_s32 ret = rk_nok;
3011
3012 if (!obj || fmt >= MPP_CFG_STR_FMT_BUTT || !buf) {
3013 mpp_loge_f("invalid param obj %p fmt %d buf %p\n", obj, fmt, buf);
3014 return ret;
3015 }
3016
3017 mpp_env_get_u32("mpp_cfg_io_debug", &mpp_cfg_io_debug, mpp_cfg_io_debug);
3018
3019 size = strlen(buf);
3020 if (size) {
3021 MppCfgStrBuf str;
3022
3023 size++;
3024
3025 str.buf = (char *)buf;
3026 str.buf_size = size;
3027 str.offset = 0;
3028 str.depth = 0;
3029 str.type = fmt;
3030
3031 cfg_io_dbg_from("buf %p size %d\n", buf, size);
3032 cfg_io_dbg_from("%s", buf);
3033
3034 switch (fmt) {
3035 case MPP_CFG_STR_FMT_LOG : {
3036 ret = mpp_cfg_from_log(&object, &str);
3037 } break;
3038 case MPP_CFG_STR_FMT_JSON : {
3039 ret = mpp_cfg_from_json(&object, &str);
3040 } break;
3041 case MPP_CFG_STR_FMT_TOML : {
3042 ret = mpp_cfg_from_toml(&object, &str);
3043 } break;
3044 default : {
3045 mpp_loge_f("invalid formoffset %d\n", fmt);
3046 } break;
3047 }
3048 }
3049
3050 if (ret)
3051 mpp_loge_f("buf %p size %d failed to get object\n", buf, size);
3052
3053 *obj = object;
3054 return ret;
3055 }
3056
write_struct(MppCfgIoImpl * obj,MppTrie trie,MppCfgStrBuf * str,void * st)3057 static void write_struct(MppCfgIoImpl *obj, MppTrie trie, MppCfgStrBuf *str, void *st)
3058 {
3059 MppCfgInfo *tbl = NULL;
3060
3061 if (obj->name) {
3062 MppTrieInfo *info = NULL;
3063
3064 /* use string to index the location table */
3065 get_full_name(obj, str->buf, str->buf_size);
3066
3067 info = mpp_trie_get_info(trie, str->buf);
3068 if (info)
3069 tbl = mpp_trie_info_ctx(info);
3070 }
3071
3072 if (!tbl)
3073 tbl = &obj->info;
3074
3075 cfg_io_dbg_show("depth %d obj type %s name %s -> info %s offset %d size %d\n",
3076 obj->depth, strof_type(obj->type), obj->name ? str->buf : "null",
3077 strof_cfg_type(tbl->data_type), tbl->data_offset, tbl->data_size);
3078
3079 if (tbl->data_type < CFG_FUNC_TYPE_BUTT) {
3080 switch (tbl->data_type) {
3081 case CFG_FUNC_TYPE_s32 : {
3082 mpp_cfg_set_s32(tbl, st, obj->val.s32);
3083 } break;
3084 case CFG_FUNC_TYPE_u32 : {
3085 mpp_cfg_set_u32(tbl, st, obj->val.u32);
3086 } break;
3087 case CFG_FUNC_TYPE_s64 : {
3088 mpp_cfg_set_s64(tbl, st, obj->val.s64);
3089 } break;
3090 case CFG_FUNC_TYPE_u64 : {
3091 mpp_cfg_set_u64(tbl, st, obj->val.u64);
3092 } break;
3093 default : {
3094 } break;
3095 }
3096 }
3097
3098 {
3099 MppCfgIoImpl *pos, *n;
3100
3101 list_for_each_entry_safe(pos, n, &obj->child, MppCfgIoImpl, list) {
3102 write_struct(pos, trie, str, st);
3103 }
3104 }
3105 }
3106
mpp_cfg_to_struct(MppCfgObj obj,MppCfgObj type,void * st)3107 rk_s32 mpp_cfg_to_struct(MppCfgObj obj, MppCfgObj type, void *st)
3108 {
3109 MppCfgIoImpl *orig;
3110 MppCfgIoImpl *impl;
3111 MppTrie trie;
3112 MppCfgStrBuf str;
3113 char name[256] = { 0 };
3114
3115 if (!obj || !st) {
3116 mpp_loge_f("invalid param obj %p st %p\n", obj, st);
3117 return rk_nok;
3118 }
3119
3120 impl = (MppCfgIoImpl *)obj;
3121 orig = (MppCfgIoImpl *)type;
3122 trie = mpp_cfg_to_trie(orig);
3123
3124 str.buf = name;
3125 str.buf_size = sizeof(name) - 1;
3126 str.offset = 0;
3127 str.depth = 0;
3128
3129 write_struct(impl, trie, &str, st + orig->info.data_offset);
3130
3131 return rk_ok;
3132 }
3133
read_struct(MppCfgIoImpl * impl,MppCfgObj parent,void * st)3134 static MppCfgObj read_struct(MppCfgIoImpl *impl, MppCfgObj parent, void *st)
3135 {
3136 MppCfgInfo *info = &impl->info;
3137 MppCfgIoImpl *ret = NULL;
3138
3139 /* dup node first */
3140 ret = mpp_calloc_size(MppCfgIoImpl, impl->buf_size);
3141 if (!ret) {
3142 mpp_loge_f("failed to alloc impl size %d\n", impl->buf_size);
3143 return NULL;
3144 }
3145
3146 INIT_LIST_HEAD(&ret->list);
3147 INIT_LIST_HEAD(&ret->child);
3148
3149 ret->type = impl->type;
3150 ret->buf_size = impl->buf_size;
3151
3152 if (impl->name_buf_len) {
3153 ret->name = (char *)(ret + 1);
3154 memcpy(ret->name, impl->name, impl->name_buf_len);
3155 ret->name_len = impl->name_len;
3156 ret->name_buf_len = impl->name_buf_len;
3157 }
3158
3159 /* assign value by different type */
3160 switch (info->data_type) {
3161 case CFG_FUNC_TYPE_s32 :
3162 case CFG_FUNC_TYPE_u32 :
3163 case CFG_FUNC_TYPE_s64 :
3164 case CFG_FUNC_TYPE_u64 : {
3165 switch (info->data_type) {
3166 case CFG_FUNC_TYPE_s32 : {
3167 mpp_assert(impl->type == MPP_CFG_TYPE_s32);
3168 mpp_cfg_get_s32(info, st, &ret->val.s32);
3169 } break;
3170 case CFG_FUNC_TYPE_u32 : {
3171 mpp_assert(impl->type == MPP_CFG_TYPE_u32);
3172 mpp_cfg_get_u32(info, st, &ret->val.u32);
3173 } break;
3174 case CFG_FUNC_TYPE_s64 : {
3175 mpp_assert(impl->type == MPP_CFG_TYPE_s64);
3176 mpp_cfg_get_s64(info, st, &ret->val.s64);
3177 } break;
3178 case CFG_FUNC_TYPE_u64 : {
3179 mpp_assert(impl->type == MPP_CFG_TYPE_u64);
3180 mpp_cfg_get_u64(info, st, &ret->val.u64);
3181 } break;
3182 default : {
3183 } break;
3184 }
3185 } break;
3186 case CFG_FUNC_TYPE_st :
3187 case CFG_FUNC_TYPE_ptr : {
3188 ret->val = impl->val;
3189 } break;
3190 default : {
3191 } break;
3192 }
3193
3194 cfg_io_dbg_show("depth %d obj type %s name %s\n", ret->depth,
3195 strof_type(ret->type), ret->name);
3196
3197 if (parent)
3198 mpp_cfg_add(parent, ret);
3199
3200 {
3201 MppCfgIoImpl *pos, *n;
3202
3203 list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) {
3204 read_struct(pos, ret, st);
3205 }
3206 }
3207
3208 return ret;
3209 }
3210
mpp_cfg_from_struct(MppCfgObj * obj,MppCfgObj type,void * st)3211 rk_s32 mpp_cfg_from_struct(MppCfgObj *obj, MppCfgObj type, void *st)
3212 {
3213 MppCfgIoImpl *orig = (MppCfgIoImpl *)type;
3214
3215 if (!obj || !type || !st) {
3216 mpp_loge_f("invalid param obj %p type %p st %p\n", obj, type, st);
3217 return rk_nok;
3218 }
3219
3220 /* NOTE: update structure pointer by data_offset */
3221 *obj = read_struct(orig, NULL, st + orig->info.data_offset);
3222
3223 return *obj ? rk_ok : rk_nok;
3224 }
3225
mpp_cfg_print_string(char * buf)3226 rk_s32 mpp_cfg_print_string(char *buf)
3227 {
3228 rk_s32 start = 0;
3229 rk_s32 pos = 0;
3230 rk_s32 len = strlen(buf);
3231
3232 /* it may be a very long string, split by \n to different line and print */
3233 for (pos = 0; pos < len; pos++) {
3234 if (buf[pos] == '\n') {
3235 buf[pos] = '\0';
3236 mpp_logi("%s\n", &buf[start]);
3237 buf[pos] = '\n';
3238 start = pos + 1;
3239 }
3240 }
3241
3242 return rk_ok;
3243 }
3244