xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/iq_parser_v2/j2s/j2s.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *  Copyright (c) 2020, Rockchip Electronics Co., Ltd
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  */
14 
15 #include "j2s.h"
16 
17 using namespace RkCam;
18 
19 static bool j2s_template_dumping = false;
20 
j2s_alloc_data(j2s_ctx * ctx,size_t size)21 __attribute__((weak)) void* j2s_alloc_data(j2s_ctx* ctx, size_t size)
22 {
23     return malloc(size);
24 }
25 
j2s_release_data(j2s_ctx * ctx,void * ptr)26 __attribute__((weak)) void j2s_release_data(j2s_ctx* ctx, void* ptr)
27 {
28     free(ptr);
29 }
30 
31 static cJSON* _j2s_obj_to_json(j2s_ctx* ctx, int obj_index, void* ptr);
32 
33 static cJSON* _j2s_struct_to_json(j2s_ctx* ctx, int struct_index, void* ptr);
34 
35 static int _j2s_json_to_obj(j2s_ctx* ctx, cJSON* json, cJSON* parent,
36     int obj_index, void* ptr, bool query);
37 
38 static int _j2s_json_to_struct(j2s_ctx* ctx, cJSON* json, int struct_index,
39     void* ptr, bool query);
40 
41 static int _j2s_obj_from_cache(j2s_ctx* ctx, int obj_index, int fd, void* ptr);
42 
43 static int _j2s_struct_from_cache(j2s_ctx* ctx, int struct_index, int fd,
44     void* ptr);
45 
46 static void _j2s_obj_to_cache(j2s_ctx* ctx, int obj_index, int fd, void* ptr);
47 
48 static void _j2s_struct_to_cache(j2s_ctx* ctx, int struct_index, int fd,
49     void* ptr);
50 
51 static int _j2s_struct_free(j2s_ctx* ctx, int struct_index, void* ptr);
52 
j2s_find_struct_index(j2s_ctx * ctx,const char * name)53 static inline int j2s_find_struct_index(j2s_ctx* ctx, const char* name)
54 {
55     if (!name)
56         return -1;
57 
58     for (int i = 0; i < ctx->num_struct; i++) {
59         j2s_struct* struct_obj = &ctx->structs[i];
60         if (!strcmp(struct_obj->name, name))
61             return i;
62     }
63 
64     return -1;
65 }
66 
j2s_struct_free(j2s_ctx * ctx,const char * name,void * ptr)67 int j2s_struct_free(j2s_ctx* ctx, const char* name, void* ptr)
68 {
69     int struct_index = name ? j2s_find_struct_index(ctx, name) : ctx->root_index;
70 
71     return _j2s_struct_free(ctx, struct_index, ptr);
72 }
73 
j2s_struct_to_json(j2s_ctx * ctx,const char * name,void * ptr)74 cJSON* j2s_struct_to_json(j2s_ctx* ctx, const char* name, void* ptr)
75 {
76     int struct_index = name ? j2s_find_struct_index(ctx, name) : ctx->root_index;
77 
78     return _j2s_struct_to_json(ctx, struct_index, ptr);
79 }
80 
j2s_json_to_struct(j2s_ctx * ctx,cJSON * json,const char * name,void * ptr)81 int j2s_json_to_struct(j2s_ctx* ctx, cJSON* json, const char* name, void* ptr)
82 {
83     int struct_index = name ? j2s_find_struct_index(ctx, name) : ctx->root_index;
84 
85     return _j2s_json_to_struct(ctx, json, struct_index, ptr, false);
86 }
87 
j2s_json_from_struct(j2s_ctx * ctx,cJSON * json,const char * name,void * ptr)88 int j2s_json_from_struct(j2s_ctx* ctx, cJSON* json, const char* name,
89     void* ptr)
90 {
91     int struct_index = name ? j2s_find_struct_index(ctx, name) : ctx->root_index;
92 
93     return _j2s_json_to_struct(ctx, json, struct_index, ptr, true);
94 }
95 
j2s_struct_to_cache(j2s_ctx * ctx,const char * name,int fd,void * ptr)96 void j2s_struct_to_cache(j2s_ctx* ctx, const char* name, int fd, void* ptr)
97 {
98     int struct_index = name ? j2s_find_struct_index(ctx, name) : ctx->root_index;
99 
100     _j2s_struct_to_cache(ctx, struct_index, fd, ptr);
101 }
102 
j2s_struct_from_cache(j2s_ctx * ctx,const char * name,int fd,void * ptr)103 int j2s_struct_from_cache(j2s_ctx* ctx, const char* name, int fd, void* ptr)
104 {
105     int struct_index = name ? j2s_find_struct_index(ctx, name) : ctx->root_index;
106 
107     return _j2s_struct_from_cache(ctx, struct_index, fd, ptr);
108 }
109 
110 /* Enum name to value */
j2s_enum_get_value(j2s_ctx * ctx,int enum_index,const char * name)111 static inline int j2s_enum_get_value(j2s_ctx* ctx, int enum_index,
112     const char* name)
113 {
114     j2s_enum* enum_obj;
115 
116     if (enum_index < 0 || !name)
117         return -1;
118 
119     enum_obj = &ctx->enums[enum_index];
120 
121     for (int i = 0; i < enum_obj->num_value; i++) {
122         j2s_enum_value* enum_value = &ctx->enum_values[enum_obj->value_index + i];
123 
124         if (!strcmp(enum_value->name, name))
125             return enum_value->value;
126     }
127 
128     WARN("unknown enum name: %s for %s\n", name, enum_obj->name);
129     return -1;
130 }
131 
132 /* Enum value to name */
j2s_enum_get_name(j2s_ctx * ctx,int enum_index,int value)133 static inline const char* j2s_enum_get_name(j2s_ctx* ctx, int enum_index,
134     int value)
135 {
136     j2s_enum* enum_obj;
137 
138     if (enum_index < 0)
139         goto out;
140 
141     enum_obj = &ctx->enums[enum_index];
142 
143     for (int i = 0; i < enum_obj->num_value; i++) {
144         j2s_enum_value* enum_value = &ctx->enum_values[enum_obj->value_index + i];
145 
146         if (enum_value->value == value)
147             return enum_value->name;
148     }
149 
150     WARN("unknown enum value: %d for %s\n", value, enum_obj->name);
151 out:
152     return "INVALID";
153 }
154 
_j2s_enum_to_json(j2s_ctx * ctx,int enum_index)155 static cJSON* _j2s_enum_to_json(j2s_ctx* ctx, int enum_index)
156 {
157     j2s_enum* enum_obj;
158     cJSON *root, *item;
159 
160     if (enum_index < 0)
161         return NULL;
162 
163     enum_obj = &ctx->enums[enum_index];
164 
165     root = RkCam::cJSON_CreateObject();
166     DASSERT(root, return NULL);
167 
168     for (int i = 0; i < enum_obj->num_value; i++) {
169         j2s_enum_value* enum_value = &ctx->enum_values[enum_obj->value_index + i];
170 
171         item = RkCam::cJSON_CreateNumber(enum_value->value);
172         if (item)
173             RkCam::cJSON_AddItemToObject(root, enum_value->name, item);
174     }
175 
176     return root;
177 }
178 
j2s_enums_to_json(j2s_ctx * ctx)179 cJSON* j2s_enums_to_json(j2s_ctx* ctx)
180 {
181     cJSON *root, *item;
182 
183     if (!ctx->num_enum)
184         return NULL;
185 
186     root = cJSON_CreateObject();
187     DASSERT(root, return NULL);
188 
189     for (int i = 0; i < ctx->num_enum; i++) {
190         j2s_enum* enum_obj = &ctx->enums[i];
191 
192         item = _j2s_enum_to_json(ctx, i);
193         if (item)
194             cJSON_AddItemToObject(root, enum_obj->name, item);
195     }
196 
197     return root;
198 }
199 
_j2s_struct_to_template_json(j2s_ctx * ctx,int struct_index)200 static cJSON* _j2s_struct_to_template_json(j2s_ctx* ctx, int struct_index)
201 {
202     j2s_struct* struct_obj;
203     cJSON* json;
204 
205     if (struct_index < 0)
206         return NULL;
207 
208     struct_obj = &ctx->structs[struct_index];
209     if (struct_obj->child_index < 0)
210         return NULL;
211 
212     DBG("start struct: %s\n", struct_obj->name);
213     j2s_template_dumping = true;
214     json = _j2s_struct_to_json(ctx, struct_index, NULL);
215     j2s_template_dumping = false;
216     DBG("finish struct: %s\n", struct_obj->name);
217 
218     return json;
219 }
220 
j2s_struct_to_template_json(j2s_ctx * ctx,const char * name)221 cJSON* j2s_struct_to_template_json(j2s_ctx* ctx, const char* name)
222 {
223     int struct_index = name ? j2s_find_struct_index(ctx, name) : ctx->root_index;
224 
225     return _j2s_struct_to_template_json(ctx, struct_index);
226 }
227 
j2s_struct_size(j2s_ctx * ctx,int struct_index)228 int j2s_struct_size(j2s_ctx* ctx, int struct_index)
229 {
230     j2s_struct* struct_obj;
231     j2s_obj* child;
232     int child_index, child_size;
233 
234     if (struct_index < 0)
235         return 0;
236 
237     struct_obj = &ctx->structs[struct_index];
238 
239     /* Find last child */
240     for (child = NULL, child_index = struct_obj->child_index; child_index >= 0;
241          child_index = child->next_index)
242         child = &ctx->objs[child_index];
243 
244     if (!child)
245         return 0;
246 
247     if (J2S_IS_POINTER(child)) {
248         child_size = (int)sizeof(void*);
249     } else if (J2S_IS_ARRAY(child)) {
250         child_size = child->elem_size * child->num_elem;
251     } else {
252         child_size = child->elem_size;
253     }
254 
255     return child_size + child->offset;
256 }
257 
j2s_type_name(j2s_type type)258 const char* j2s_type_name(j2s_type type)
259 {
260     switch (type) {
261     case J2S_TYPE_INT_8:
262         return "int8_t";
263     case J2S_TYPE_UINT_8:
264         return "uint8_t";
265     case J2S_TYPE_INT_16:
266         return "int16_t";
267     case J2S_TYPE_UINT_16:
268         return "uint16_t";
269     case J2S_TYPE_INT_32:
270         return "int32_t";
271     case J2S_TYPE_UINT_32:
272         return "uint32_t";
273     case J2S_TYPE_INT_64:
274         return "int64_t";
275     case J2S_TYPE_UINT_64:
276         return "uint64_t";
277     case J2S_TYPE_FLOAT:
278         return "float";
279     case J2S_TYPE_DOUBLE:
280         return "double";
281     case J2S_TYPE_STRING:
282         return "char";
283     case J2S_TYPE_STRUCT:
284         return "struct";
285     default:
286         return "unknown";
287     }
288 }
289 
290 /* Get number value from a obj */
j2s_obj_get_value(j2s_ctx * ctx,int obj_index,void * ptr_)291 static inline double j2s_obj_get_value(j2s_ctx* ctx, int obj_index, void* ptr_)
292 {
293     j2s_obj* obj;
294     double value;
295     char* ptr = (char*)ptr_;
296 
297     if (!ptr || obj_index < 0)
298         return 0;
299 
300     obj = &ctx->objs[obj_index];
301     ptr += obj->offset;
302 
303 #define J2S_FETCH_NUM(type, ptr)   \
304     value = (double)*((type*)ptr); \
305     return value;
306 
307     switch (obj->type) {
308     case J2S_TYPE_INT_8:
309         J2S_FETCH_NUM(int8_t, ptr);
310     case J2S_TYPE_UINT_8:
311         J2S_FETCH_NUM(uint8_t, ptr);
312     case J2S_TYPE_INT_16:
313         J2S_FETCH_NUM(int16_t, ptr);
314     case J2S_TYPE_UINT_16:
315         J2S_FETCH_NUM(uint16_t, ptr);
316     case J2S_TYPE_INT_32:
317         J2S_FETCH_NUM(int32_t, ptr);
318     case J2S_TYPE_UINT_32:
319         J2S_FETCH_NUM(uint32_t, ptr);
320     case J2S_TYPE_INT_64:
321         J2S_FETCH_NUM(int64_t, ptr);
322     case J2S_TYPE_UINT_64:
323         J2S_FETCH_NUM(uint64_t, ptr);
324     case J2S_TYPE_FLOAT:
325         J2S_FETCH_NUM(float, ptr);
326     case J2S_TYPE_DOUBLE:
327         J2S_FETCH_NUM(double, ptr);
328     default:
329         return 0;
330     }
331 }
332 
333 /* Set number value to a obj */
j2s_obj_set_value(j2s_ctx * ctx,int obj_index,double value,void * ptr_)334 static inline int j2s_obj_set_value(j2s_ctx* ctx, int obj_index, double value,
335     void* ptr_)
336 {
337     j2s_obj* obj;
338     char* ptr = (char*)ptr_;
339 
340     if (!ptr || obj_index < 0)
341         return 0;
342 
343     obj = &ctx->objs[obj_index];
344     ptr += obj->offset;
345 
346 #define J2S_STORE_NUM(type, value, ptr) \
347     *(type*)ptr = (type)value;          \
348     return 0;
349 
350     switch (obj->type) {
351     case J2S_TYPE_INT_8:
352         J2S_STORE_NUM(int8_t, value, ptr);
353     case J2S_TYPE_UINT_8:
354         J2S_STORE_NUM(uint8_t, value, ptr);
355     case J2S_TYPE_INT_16:
356         J2S_STORE_NUM(int16_t, value, ptr);
357     case J2S_TYPE_UINT_16:
358         J2S_STORE_NUM(uint16_t, value, ptr);
359     case J2S_TYPE_INT_32:
360         J2S_STORE_NUM(int32_t, value, ptr);
361     case J2S_TYPE_UINT_32:
362         J2S_STORE_NUM(uint32_t, value, ptr);
363     case J2S_TYPE_INT_64:
364         J2S_STORE_NUM(int64_t, value, ptr);
365     case J2S_TYPE_UINT_64:
366         J2S_STORE_NUM(uint64_t, value, ptr);
367     case J2S_TYPE_FLOAT:
368         J2S_STORE_NUM(float, value, ptr);
369     case J2S_TYPE_DOUBLE:
370         J2S_STORE_NUM(double, value, ptr);
371     default:
372         return 0;
373     }
374 }
375 
376 /* Extract array to the first elem */
j2s_extract_array(j2s_obj * obj)377 static inline void j2s_extract_array(j2s_obj* obj)
378 {
379     if (obj->flags & J2S_FLAG_DEP_ARRAY) {
380         obj->flags &= ~J2S_FLAG_DEP_ARRAY;
381         obj->num_elem = obj->elem_size / obj->base_elem_size;
382     } else {
383         obj->flags &= ~J2S_FLAG_ARRAY;
384         obj->num_elem = 1;
385     }
386 
387     obj->elem_size = obj->base_elem_size;
388 }
389 
390 /* Extract dynamic array to normal array */
j2s_extract_dynamic_array(j2s_obj * obj,int len,void * ptr_)391 static inline void* j2s_extract_dynamic_array(j2s_obj* obj, int len,
392     void* ptr_)
393 {
394     char* ptr = (char*)ptr_;
395 
396     if (!j2s_template_dumping) {
397         ptr += obj->offset;
398         ptr = (char*)(*(void**)ptr);
399         if (!ptr)
400             return NULL;
401     }
402 
403     obj->offset = 0;
404     obj->len_index = -1;
405     obj->num_elem = len;
406 
407     if (obj->flags & J2S_FLAG_DEP_POINTER) {
408         obj->flags &= ~J2S_FLAG_DEP_POINTER;
409     } else {
410         obj->flags &= ~J2S_FLAG_ARRAY_POINTER;
411         obj->flags &= ~J2S_FLAG_POINTER;
412     }
413 
414     if (obj->flags & J2S_FLAG_ARRAY) {
415         obj->flags |= J2S_FLAG_DEP_ARRAY;
416     } else {
417         obj->flags |= J2S_FLAG_ARRAY;
418     }
419 
420     return ptr;
421 }
422 
j2s_get_index_json(j2s_ctx * ctx,cJSON * parent,int obj_index)423 static cJSON* j2s_get_index_json(j2s_ctx* ctx, cJSON* parent, int obj_index)
424 {
425     j2s_obj* obj;
426     char index_name[MAX_NAME + 10];
427 
428     if (obj_index < 0)
429         return NULL;
430 
431     obj = &ctx->objs[obj_index];
432 
433     /* Handle array with index obj @<name>_index */
434     snprintf(index_name, sizeof(index_name), "@%s_index", obj->name);
435     return cJSON_GetObjectItemCaseSensitive(parent, index_name);
436 }
437 
_j2s_obj_to_json(j2s_ctx * ctx,int obj_index,void * ptr_)438 static cJSON* _j2s_obj_to_json(j2s_ctx* ctx, int obj_index, void* ptr_)
439 {
440     j2s_obj* obj;
441     cJSON* root;
442     double value;
443     char* ptr = (char*)ptr_;
444 
445     if (obj_index < 0)
446         return NULL;
447 
448     obj = &ctx->objs[obj_index];
449 
450     DBG("handling obj: %s from %p[%d]\n", obj->name, ptr, obj->offset);
451 
452     /* Handle simple string */
453     if (J2S_IS_SIMPLE_STRING(obj)) {
454         if (j2s_template_dumping)
455             return cJSON_CreateString("");
456 
457         ptr += obj->offset;
458         if (obj->flags & J2S_FLAG_POINTER)
459             ptr = *(char**)ptr;
460         return cJSON_CreateString(ptr ? ptr : "");
461     }
462 
463     /* Handle array member */
464     if (J2S_IS_ARRAY(obj)) {
465         j2s_obj tmp_obj;
466         cJSON* item;
467 
468         root = cJSON_CreateArray();
469         DASSERT(root, return NULL);
470 
471         tmp_obj = *obj;
472 
473         /* Walk into array */
474         j2s_extract_array(obj);
475 
476         for (int i = 0; i < tmp_obj.num_elem; i++) {
477             DBG("handling array: %s %d/%d\n", obj->name, i, tmp_obj.num_elem);
478 
479             item = _j2s_obj_to_json(ctx, obj_index, ptr);
480             if (item)
481                 cJSON_AddItemToArray(root, item);
482 
483             obj->offset += tmp_obj.elem_size;
484         }
485 
486         *obj = tmp_obj;
487         return root;
488     }
489 
490     /* Handle dynamic array */
491     if (J2S_IS_POINTER(obj)) {
492         j2s_obj tmp_obj;
493         int len;
494 
495         DASSERT_MSG(obj->len_index >= 0, return NULL,
496             "dynamic array %s missing len\n", obj->name);
497 
498         if (j2s_template_dumping) {
499             len = 1;
500         } else {
501             len = j2s_obj_get_value(ctx, obj->len_index, ptr);
502         }
503 
504         if (!len)
505             return cJSON_CreateArray();
506 
507         tmp_obj = *obj;
508 
509         /* Walk into dynamic array */
510         ptr = (char*)j2s_extract_dynamic_array(obj, len, ptr);
511         DASSERT_MSG(j2s_template_dumping || ptr, return NULL,
512             "found null pointer at %s\n", obj->name);
513 
514         DBG("handling dynamic array: %s %d*%d from %p\n", obj->name, obj->elem_size,
515             obj->num_elem, ptr);
516 
517         root = _j2s_obj_to_json(ctx, obj_index, ptr);
518 
519         *obj = tmp_obj;
520         return root;
521     }
522 
523     /* Handle struct member */
524     if (obj->type == J2S_TYPE_STRUCT)
525         return _j2s_struct_to_json(ctx, obj->struct_index, ptr + obj->offset);
526 
527     /* Handle basic member */
528     if (j2s_template_dumping) {
529         for (int i = 0; i < ctx->num_obj; i++) {
530             if (ctx->objs[i].len_index == obj_index)
531                 return cJSON_CreateNumber(1);
532         }
533 
534         if (obj->enum_index >= 0) {
535             /* Use first value as default */
536             j2s_enum* enum_obj = &ctx->enums[obj->enum_index];
537             j2s_enum_value* enum_value = &ctx->enum_values[enum_obj->value_index];
538 
539             return cJSON_CreateString(enum_value->name);
540         }
541 
542         return cJSON_CreateNumber(0);
543     }
544 
545     value = j2s_obj_get_value(ctx, obj_index, ptr);
546 
547     if (obj->enum_index >= 0) {
548         /* Convert enum value to name */
549         const char* name = j2s_enum_get_name(ctx, obj->enum_index, (int)value);
550         return cJSON_CreateString(name);
551     }
552 
553     return cJSON_CreateNumber(value);
554 }
555 
_j2s_struct_to_json(j2s_ctx * ctx,int struct_index,void * ptr)556 static cJSON* _j2s_struct_to_json(j2s_ctx* ctx, int struct_index, void* ptr)
557 {
558     j2s_struct* struct_obj;
559     j2s_obj* child;
560     cJSON *root, *item;
561     int child_index, ret = 0;
562 
563     if (struct_index < 0)
564         return NULL;
565 
566     struct_obj = &ctx->structs[struct_index];
567     if (struct_obj->child_index < 0)
568         return NULL;
569 
570     root = cJSON_CreateObject();
571     DASSERT(root, return NULL);
572 
573     DBG("start struct: %s from %p\n", struct_obj->name, ptr);
574 
575     ret = -1;
576 
577     /* Walk child list */
578     for (child_index = struct_obj->child_index; child_index >= 0;
579          child_index = child->next_index) {
580         child = &ctx->objs[child_index];
581 
582         DBG("start child: %s (%s) from %p\n", child->name, struct_obj->name, ptr);
583 
584         item = _j2s_obj_to_json(ctx, child_index, ptr);
585         DBG("finish child: %s (%s)\n", child->name, struct_obj->name);
586 
587         if (item) {
588             if (ctx->dump_desc && child_index < ctx->num_desc) {
589                 /* Dump desc to template JSON as @<member> */
590                 char buf[MAX_NAME + 1] = "@";
591 
592                 const char* desc = ctx->descs[child_index];
593                 if (desc) {
594                     cJSON* json = cJSON_CreateString(desc);
595                     DASSERT(json, goto out);
596 
597                     strcat(buf, child->name);
598                     cJSON_AddItemToObject(root, buf, json);
599                 }
600             }
601 
602             cJSON_AddItemToObject(root, child->name, item);
603         }
604     }
605 
606     ret = 0;
607 out:
608     DBG("finish struct: %s\n", struct_obj->name);
609 
610     if (ret < 0) {
611         cJSON_Delete(root);
612         return NULL;
613     }
614     return root;
615 }
616 
_j2s_obj_free(j2s_ctx * ctx,int obj_index,void * ptr_)617 static int _j2s_obj_free(j2s_ctx* ctx, int obj_index, void* ptr_)
618 {
619     j2s_obj* obj;
620     char* ptr = (char*)ptr_;
621 
622     if (obj_index < 0)
623         return -1;
624 
625     obj = &ctx->objs[obj_index];
626 
627     /* Handle simple string */
628     if (J2S_IS_SIMPLE_STRING(obj)) {
629         ptr += obj->offset;
630 
631         if (obj->flags & J2S_FLAG_ARRAY) {
632             return 0;
633         }
634 
635         if (obj->flags & J2S_FLAG_POINTER) {
636             ptr = *(char**)ptr;
637         }
638 
639         if (ptr) {
640             free(ptr);
641         }
642         return 0;
643     }
644 
645     /* Handle array member */
646     if (J2S_IS_ARRAY(obj)) {
647         j2s_obj tmp_obj;
648         tmp_obj = *obj;
649 
650         /* Walk into array */
651         j2s_extract_array(obj);
652 
653         for (int i = 0; i < tmp_obj.num_elem; i++) {
654             _j2s_obj_free(ctx, obj_index, ptr);
655             obj->offset += tmp_obj.elem_size;
656         }
657 
658         *obj = tmp_obj;
659         return 0;
660     }
661 
662     /* Handle dynamic array */
663     if (J2S_IS_POINTER(obj)) {
664         j2s_obj tmp_obj;
665         void* root_ptr = *(void**)ptr;
666         int len;
667 
668         if (obj->len_index < 0) {
669             DBG("dynamic array %s missing len\n", obj->name);
670             return -1;
671         }
672 
673         len = j2s_obj_get_value(ctx, obj->len_index, ptr);
674 
675         if (len <= 0) {
676             DBG("array size error: %s %d\n", obj->name, len);
677             return -1;
678         }
679 
680         tmp_obj = *obj;
681 
682         /* Walk into dynamic array */
683         ptr = (char*)j2s_extract_dynamic_array(obj, len, ptr);
684 
685         _j2s_obj_free(ctx, obj_index, ptr);
686 
687         if (ptr) {
688             free(ptr);
689         }
690 
691         *obj = tmp_obj;
692         return 0;
693     }
694 
695     /* Handle struct member */
696     if (obj->type == J2S_TYPE_STRUCT) {
697         return _j2s_struct_free(ctx, obj->struct_index, ptr + obj->offset);
698     }
699 
700     return 0;
701 }
702 
_j2s_struct_free(j2s_ctx * ctx,int struct_index,void * ptr)703 static int _j2s_struct_free(j2s_ctx* ctx, int struct_index, void* ptr)
704 {
705     j2s_struct* struct_obj = NULL;
706     j2s_obj* child = NULL;
707     int child_index, ret = 0;
708 
709     if (struct_index < 0)
710         return -1;
711 
712     struct_obj = &ctx->structs[struct_index];
713     if (struct_obj->child_index < 0)
714         return -1;
715 
716     ret = -1;
717 
718     /* Walk child list */
719     for (child_index = struct_obj->child_index; child_index >= 0;
720          child_index = child->next_index) {
721         child = &ctx->objs[child_index];
722         ret = _j2s_obj_free(ctx, child_index, ptr);
723     }
724 
725     return ret;
726 }
727 
j2s_json_to_array_with_index(j2s_ctx * ctx,cJSON * json,cJSON * index_json,cJSON * parent,j2s_obj * obj,void * ptr,bool query)728 static int j2s_json_to_array_with_index(j2s_ctx* ctx, cJSON* json,
729     cJSON* index_json, cJSON* parent,
730     j2s_obj* obj, void* ptr, bool query)
731 {
732     j2s_obj tmp_obj;
733     cJSON *index_item, *item;
734     int size, index, ret = -1;
735 
736     size = cJSON_GetArraySize(index_json);
737     if (!size)
738         return 0;
739 
740     tmp_obj = *obj;
741 
742     /* Walk into array */
743     j2s_extract_array(obj);
744 
745     if (query) {
746         cJSON* root;
747 
748         /* Clear the original array */
749         root = cJSON_CreateArray();
750         cJSON_ReplaceItemInObjectCaseSensitive(parent, obj->name, root);
751 
752         for (int i = 0; i < size; i++) {
753             index_item = cJSON_GetArrayItem(index_json, i);
754             index = cJSON_GetNumberValue(index_item);
755             obj->offset = tmp_obj.offset + index * tmp_obj.elem_size;
756             item = NULL;
757 
758             DBG("handling index array: %s %d/%d\n", obj->name, index,
759                 tmp_obj.num_elem);
760 
761             /* Query item */
762             if (index < tmp_obj.num_elem)
763                 item = _j2s_obj_to_json(ctx, obj - ctx->objs, ptr);
764 
765             if (!item) {
766                 item = cJSON_CreateObject();
767                 if (!item) {
768                     ret = -1;
769                     break;
770                 }
771             }
772 
773             cJSON_AddItemToArray(root, item);
774         }
775     } else {
776         for (int i = 0; i < size; i++) {
777             index_item = cJSON_GetArrayItem(index_json, i);
778             index = cJSON_GetNumberValue(index_item);
779             obj->offset = tmp_obj.offset + index * tmp_obj.elem_size;
780 
781             DBG("handling index array: %s %d/%d\n", obj->name, index,
782                 tmp_obj.num_elem);
783 
784             if (index >= tmp_obj.num_elem)
785                 continue;
786 
787             /* Apply item */
788             item = cJSON_GetArrayItem(json, i);
789             if (!item)
790                 break;
791 
792             ret = _j2s_json_to_obj(ctx, item, parent, obj - ctx->objs, ptr, false);
793             if (ret < 0)
794                 break;
795         }
796     }
797 
798     *obj = tmp_obj;
799     return ret;
800 }
801 
_j2s_json_to_obj(j2s_ctx * ctx,cJSON * json,cJSON * parent,int obj_index,void * ptr_,bool query)802 static int _j2s_json_to_obj(j2s_ctx* ctx, cJSON* json, cJSON* parent,
803     int obj_index, void* ptr_, bool query)
804 {
805     j2s_obj* obj;
806     cJSON* root = json;
807     int ret = 0;
808     char* ptr = (char*)ptr_;
809 
810     if (obj_index < 0)
811         return -1;
812 
813     obj = &ctx->objs[obj_index];
814 
815     DBG("handling obj: %s from %p[%d]\n", obj->name, ptr, obj->offset);
816 
817     /* Handle simple string */
818     if (J2S_IS_SIMPLE_STRING(obj)) {
819         ptr += obj->offset;
820 
821         if (query) {
822             if (obj->flags == J2S_FLAG_POINTER)
823                 ptr = *(char**)ptr;
824 
825             cJSON_SetValuestring(root, ptr ? ptr : "");
826         } else {
827             char* str = cJSON_GetStringValue(root);
828 
829             if (obj->flags == J2S_FLAG_ARRAY) {
830                 strncpy(ptr, str ? str : "", obj->num_elem);
831             } else {
832                 char** buf = (char**)ptr;
833                 if (*buf)
834                     free(*buf);
835                 *buf = strdup(str ? str : "");
836             }
837         }
838 
839         return 0;
840     }
841 
842     /* Handle array member */
843     if (J2S_IS_ARRAY(obj)) {
844         j2s_obj tmp_obj;
845         cJSON *item, *index_json;
846 
847         index_json = j2s_get_index_json(ctx, parent, obj_index);
848         if (index_json && obj->type != J2S_TYPE_STRING && obj->flags != J2S_FLAG_ARRAY) {
849             cJSON_DetachItemViaPointer(parent, index_json);
850             index_json = NULL;
851             WARN("ignoring index for dep types %s\n", obj->name);
852         }
853 
854         if (index_json)
855             return j2s_json_to_array_with_index(ctx, json, index_json, parent, obj,
856                 ptr, query);
857 
858         tmp_obj = *obj;
859 
860         /* Walk into array */
861         j2s_extract_array(obj);
862 
863         for (int i = 0; i < tmp_obj.num_elem; i++) {
864             DBG("handling array: %s %d/%d\n", obj->name, i, tmp_obj.num_elem);
865 
866             item = cJSON_GetArrayItem(root, i);
867             if (!item)
868                 continue;
869 
870             ret = _j2s_json_to_obj(ctx, item, parent, obj_index, ptr, query);
871             if (ret < 0)
872                 break;
873 
874             obj->offset += tmp_obj.elem_size;
875         }
876 
877         *obj = tmp_obj;
878         return ret;
879     }
880 
881     /* Handle dynamic array */
882     if (J2S_IS_POINTER(obj)) {
883         j2s_obj tmp_obj;
884         cJSON *len_json, *index_json;
885         char* len_name;
886         int len, old_len;
887 
888         DASSERT_MSG(obj->len_index >= 0, return -1,
889             "dynamic array %s missing len\n", obj->name);
890 
891         len_name = ctx->objs[obj->len_index].name;
892 
893         len_json = cJSON_GetObjectItemCaseSensitive(parent, len_name);
894         if (!len_json && !query)
895             WARN("missing len in json for dynamic array '%s'\n", obj->name);
896 
897         index_json = j2s_get_index_json(ctx, parent, obj_index);
898 
899         if (query && !index_json) {
900             /* Query dynamic array len */
901             if (len_json)
902                 cJSON_DetachItemViaPointer(parent, len_json);
903 
904             len_json = _j2s_obj_to_json(ctx, obj->len_index, ptr);
905             DASSERT_MSG(len_json, return -1, "failed to query %s\n", len_name);
906 
907             cJSON_AddItemToObject(parent, len_name, len_json);
908 
909             /* Force query the whole dynamic array */
910             cJSON_DetachItemViaPointer(parent, json);
911             cJSON_Delete(json);
912 
913             json = _j2s_obj_to_json(ctx, obj_index, ptr);
914             DASSERT_MSG(json, return -1, "failed to query %s\n", obj->name);
915 
916             cJSON_AddItemToObject(parent, obj->name, json);
917             return 0;
918         }
919 
920         old_len = j2s_obj_get_value(ctx, obj->len_index, ptr);
921 
922         if (len_json) {
923             len = cJSON_GetArraySize(json);
924             /* Fallback to array size */
925             cJSON_SetNumberValue(len_json, len);
926         } else if (index_json) {
927             len = old_len;
928         } else {
929             /* Fallback to array size */
930             len = cJSON_GetArraySize(json);
931         }
932 
933         if (len != old_len) {
934             /* Dynamic array size changed, realloc it */
935             void** buf = (void**)(ptr + obj->offset);
936 
937             if (old_len && *buf)
938                 j2s_release_data(ctx, *buf);
939 
940             *buf = j2s_alloc_data(ctx, len * obj->elem_size);
941 
942             j2s_obj_set_value(ctx, obj->len_index, len, ptr);
943 
944             DBG("re-alloc %s from %d*%d to %d*%d = %p\n", obj->name, old_len,
945                 obj->elem_size, len, obj->elem_size, *buf);
946         }
947 
948         if (!len)
949             return 0;
950 
951         tmp_obj = *obj;
952 
953         /* Walk into dynamic array */
954         ptr = (char*)j2s_extract_dynamic_array(obj, len, ptr);
955         DASSERT_MSG(ptr, return -1, "found null pointer at %s\n", obj->name);
956 
957         DBG("handling dynamic array: %s %d*%d from %p\n", obj->name, obj->elem_size,
958             obj->num_elem, ptr);
959 
960         ret = _j2s_json_to_obj(ctx, root, parent, obj_index, ptr, query);
961 
962         *obj = tmp_obj;
963         return ret;
964     }
965 
966     /* Handle struct member */
967     if (obj->type == J2S_TYPE_STRUCT)
968         return _j2s_json_to_struct(ctx, root, obj->struct_index, ptr + obj->offset,
969             query);
970 
971     /* Handle basic member */
972     if (query) {
973         double value = j2s_obj_get_value(ctx, obj_index, ptr);
974 
975         if (obj->enum_index >= 0) {
976             /* Convert enum value to name */
977             const char* name = j2s_enum_get_name(ctx, obj->enum_index, (int)value);
978             cJSON_SetValuestring(root, name);
979             return 0;
980         }
981 
982         cJSON_SetNumberValue(root, value);
983         return 0;
984     } else {
985         double value;
986 
987         if (obj->enum_index >= 0) {
988             /* Convert enum name to value */
989             char* name = cJSON_GetStringValue(root);
990 
991             value = (double)j2s_enum_get_value(ctx, obj->enum_index, name);
992         } else {
993             value = cJSON_GetNumberValue(root);
994         }
995 
996         j2s_obj_set_value(ctx, obj_index, value, ptr);
997         return 0;
998     }
999 }
1000 
_j2s_json_to_struct(j2s_ctx * ctx,cJSON * json,int struct_index,void * ptr,bool query)1001 static int _j2s_json_to_struct(j2s_ctx* ctx, cJSON* json, int struct_index,
1002     void* ptr, bool query)
1003 {
1004     j2s_struct* struct_obj;
1005     j2s_obj* child;
1006     cJSON *item, *root = json;
1007     int child_index, ret = 0;
1008 
1009     if (struct_index < 0)
1010         return -1;
1011 
1012     struct_obj = &ctx->structs[struct_index];
1013 
1014     DBG("start struct: %s from %p\n", struct_obj->name, ptr);
1015 
1016     /* Walk child list */
1017     for (child_index = struct_obj->child_index; child_index >= 0;
1018          child_index = child->next_index) {
1019         child = &ctx->objs[child_index];
1020 
1021         item = cJSON_GetObjectItemCaseSensitive(root, child->name);
1022         if (!item)
1023             continue;
1024 
1025         DBG("start child: %s (%s) from %p\n", child->name, struct_obj->name, ptr);
1026         ret = _j2s_json_to_obj(ctx, item, root, child_index, ptr, query);
1027         DBG("finish child: %s (%s)\n", child->name, struct_obj->name);
1028         if (ret < 0)
1029             break;
1030     }
1031 
1032     DBG("finish struct: %s\n", struct_obj->name);
1033     return ret;
1034 }
1035 
j2s_restore_obj(j2s_ctx * ctx,j2s_obj * obj,int fd,void * ptr_)1036 static int j2s_restore_obj(j2s_ctx* ctx, j2s_obj* obj, int fd, void* ptr_)
1037 {
1038     char buf[MAX_NAME];
1039     void** data_ptr;
1040     int size;
1041     char* ptr = (char*)ptr_;
1042 
1043     if (!J2S_IS_POINTER(obj))
1044         return 0;
1045 
1046     data_ptr = (void**)(ptr + obj->offset);
1047 
1048     if (read(fd, buf, MAX_NAME) != MAX_NAME)
1049         return -1;
1050 
1051     if (strncmp(obj->name, buf, MAX_NAME) < 0)
1052         return -1;
1053 
1054     if (read(fd, &size, sizeof(int)) != sizeof(int))
1055         return -1;
1056 
1057     if (!size) {
1058         *data_ptr = NULL;
1059         return 0;
1060     }
1061 
1062     *data_ptr = j2s_alloc_data(ctx, size);
1063     if (!*data_ptr)
1064         return -1;
1065 
1066     if (read(fd, *data_ptr, size) != size) {
1067         j2s_release_data(ctx, *data_ptr);
1068         return -1;
1069     }
1070 
1071     DBG("restore obj: %s to %p, size %d\n", obj->name, *data_ptr, size);
1072 
1073     return size;
1074 }
1075 
j2s_store_obj(j2s_obj * obj,int fd,void * ptr_)1076 static void j2s_store_obj(j2s_obj* obj, int fd, void* ptr_)
1077 {
1078     char buf[MAX_NAME] = { 0 };
1079     int size;
1080     ssize_t bytes_written = 0;
1081     char* ptr = (char*)ptr_;
1082 
1083     if (!J2S_IS_POINTER(obj))
1084         return;
1085 
1086     ptr = (char*)(*(void**)(ptr + obj->offset));
1087     if (!ptr)
1088         return;
1089 
1090     if (J2S_IS_SIMPLE_STRING(obj)) {
1091         size = strlen(ptr) + 1;
1092     } else {
1093         size = obj->num_elem * obj->elem_size;
1094     }
1095 
1096     DBG("store obj: %s from %p, size %d\n", obj->name, ptr, size);
1097 
1098     strcpy(buf, obj->name);
1099     bytes_written = write(fd, buf, MAX_NAME);
1100     bytes_written = write(fd, &size, sizeof(int));
1101     bytes_written = write(fd, ptr, size);
1102 }
1103 
_j2s_obj_from_cache(j2s_ctx * ctx,int obj_index,int fd,void * ptr)1104 static int _j2s_obj_from_cache(j2s_ctx* ctx, int obj_index, int fd, void* ptr)
1105 {
1106     j2s_obj* obj;
1107     int ret = 0;
1108 
1109     if (obj_index < 0)
1110         return -1;
1111 
1112     obj = &ctx->objs[obj_index];
1113 
1114     DBG("handling obj: %s from %p[%d]\n", obj->name, ptr, obj->offset);
1115 
1116     /* Handle simple string */
1117     if (J2S_IS_SIMPLE_STRING(obj))
1118         return j2s_restore_obj(ctx, obj, fd, ptr);
1119 
1120     /* Handle array member */
1121     if (J2S_IS_ARRAY(obj)) {
1122         j2s_obj tmp_obj = *obj;
1123 
1124         if (obj->type != J2S_TYPE_STRUCT && obj->type != J2S_TYPE_STRING)
1125             return 0;
1126 
1127         /* Walk into array */
1128         j2s_extract_array(obj);
1129 
1130         for (int i = 0; i < tmp_obj.num_elem; i++) {
1131             DBG("handling array: %s %d/%d\n", obj->name, i, tmp_obj.num_elem);
1132 
1133             ret = _j2s_obj_from_cache(ctx, obj_index, fd, ptr);
1134             if (ret < 0)
1135                 break;
1136 
1137             obj->offset += tmp_obj.elem_size;
1138         }
1139 
1140         *obj = tmp_obj;
1141         return ret;
1142     }
1143 
1144     /* Handle dynamic array */
1145     if (J2S_IS_POINTER(obj)) {
1146         j2s_obj tmp_obj = *obj;
1147         int size;
1148 
1149         size = j2s_restore_obj(ctx, obj, fd, ptr);
1150         if (size <= 0)
1151             return size;
1152 
1153         /* Walk into dynamic array */
1154         ptr = j2s_extract_dynamic_array(obj, size / obj->elem_size, ptr);
1155 
1156         DBG("handling dynamic array: %s %d*%d from %p\n", obj->name, obj->elem_size,
1157             obj->num_elem, ptr);
1158 
1159         ret = _j2s_obj_from_cache(ctx, obj_index, fd, ptr);
1160 
1161         *obj = tmp_obj;
1162         return ret;
1163     }
1164 
1165     /* Handle struct member */
1166     if (obj->type == J2S_TYPE_STRUCT)
1167         return _j2s_struct_from_cache(ctx, obj->struct_index, fd,
1168             (char*)ptr + obj->offset);
1169 
1170     return 0;
1171 }
1172 
_j2s_struct_from_cache(j2s_ctx * ctx,int struct_index,int fd,void * ptr)1173 static int _j2s_struct_from_cache(j2s_ctx* ctx, int struct_index, int fd,
1174     void* ptr)
1175 {
1176     j2s_struct* struct_obj;
1177     j2s_obj* child;
1178     int child_index;
1179 
1180     if (struct_index < 0)
1181         return -1;
1182 
1183     if (struct_index == ctx->root_index) {
1184         int root_size = j2s_struct_size(ctx, ctx->root_index);
1185         if (read(fd, ptr, root_size) != root_size)
1186             return -1;
1187     }
1188 
1189     struct_obj = &ctx->structs[struct_index];
1190 
1191     /* Walk child list */
1192     for (child_index = struct_obj->child_index; child_index >= 0;
1193          child_index = child->next_index) {
1194         child = &ctx->objs[child_index];
1195         if (_j2s_obj_from_cache(ctx, child_index, fd, ptr) < 0)
1196             return -1;
1197     }
1198 
1199     return 0;
1200 }
1201 
_j2s_obj_to_cache(j2s_ctx * ctx,int obj_index,int fd,void * ptr)1202 static void _j2s_obj_to_cache(j2s_ctx* ctx, int obj_index, int fd, void* ptr)
1203 {
1204     j2s_obj* obj;
1205 
1206     if (obj_index < 0)
1207         return;
1208 
1209     obj = &ctx->objs[obj_index];
1210 
1211     DBG("handling obj: %s from %p[%d]\n", obj->name, ptr, obj->offset);
1212 
1213     /* Handle simple string */
1214     if (J2S_IS_SIMPLE_STRING(obj)) {
1215         j2s_store_obj(obj, fd, ptr);
1216         return;
1217     }
1218 
1219     /* Handle array member */
1220     if (J2S_IS_ARRAY(obj)) {
1221         j2s_obj tmp_obj = *obj;
1222 
1223         if (obj->type != J2S_TYPE_STRUCT && obj->type != J2S_TYPE_STRING)
1224             return;
1225 
1226         /* Walk into array */
1227         j2s_extract_array(obj);
1228 
1229         for (int i = 0; i < tmp_obj.num_elem; i++) {
1230             DBG("handling array: %s %d/%d\n", obj->name, i, tmp_obj.num_elem);
1231 
1232             _j2s_obj_to_cache(ctx, obj_index, fd, ptr);
1233             obj->offset += tmp_obj.elem_size;
1234         }
1235 
1236         *obj = tmp_obj;
1237         return;
1238     }
1239 
1240     /* Handle dynamic array */
1241     if (J2S_IS_POINTER(obj)) {
1242         j2s_obj tmp_obj = *obj;
1243         int len;
1244 
1245         if (obj->len_index < 0)
1246             return;
1247 
1248         len = j2s_obj_get_value(ctx, obj->len_index, ptr);
1249         if (!len)
1250             return;
1251 
1252         obj->num_elem = len;
1253         j2s_store_obj(obj, fd, ptr);
1254 
1255         /* Walk into dynamic array */
1256         ptr = j2s_extract_dynamic_array(obj, len, ptr);
1257 
1258         DBG("handling dynamic array: %s %d*%d from %p\n", obj->name, obj->elem_size,
1259             obj->num_elem, ptr);
1260 
1261         _j2s_obj_to_cache(ctx, obj_index, fd, ptr);
1262 
1263         *obj = tmp_obj;
1264         return;
1265     }
1266 
1267     /* Handle struct member */
1268     if (obj->type == J2S_TYPE_STRUCT)
1269         _j2s_struct_to_cache(ctx, obj->struct_index, fd, (char*)ptr + obj->offset);
1270 }
1271 
_j2s_struct_to_cache(j2s_ctx * ctx,int struct_index,int fd,void * ptr)1272 static void _j2s_struct_to_cache(j2s_ctx* ctx, int struct_index, int fd,
1273     void* ptr)
1274 {
1275     j2s_struct* struct_obj;
1276     j2s_obj* child;
1277     int child_index;
1278     ssize_t bytes_written = 0;
1279 
1280     if (struct_index < 0)
1281         return;
1282 
1283     if (struct_index == ctx->root_index)
1284         bytes_written = write(fd, ptr, j2s_struct_size(ctx, struct_index));
1285 
1286     struct_obj = &ctx->structs[struct_index];
1287 
1288     /* Walk child list */
1289     for (child_index = struct_obj->child_index; child_index >= 0;
1290          child_index = child->next_index) {
1291         child = &ctx->objs[child_index];
1292         _j2s_obj_to_cache(ctx, child_index, fd, ptr);
1293     }
1294 }
1295