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