xref: /rockchip-linux_mpp/mpp/base/mpp_cfg_io.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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