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 #include "j2s_generated.h"
17
18 #include <sys/stat.h>
19
20 using namespace RkCam;
21
22 #define J2S_POOL_SIZE (2048 * 1024)
23
aligned_size(int ori_size,int alig)24 static int aligned_size(int ori_size, int alig) {
25 return (ori_size + (alig - 1)) & ~(alig - 1);
26 }
27
j2s_alloc_map_record(j2s_ctx * ctx,void * dst,void * ptr,size_t len)28 int j2s_alloc_map_record(j2s_ctx *ctx, void *dst, void *ptr, size_t len) {
29 if (!ctx || !ctx->priv) {
30 return -1;
31 }
32
33 j2s_pool_t *j2s_pool = (j2s_pool_t *)ctx->priv;
34
35 if (!j2s_pool->maps_list) {
36 j2s_pool->maps_list = (map_index_t *)calloc(1, sizeof(map_index_t));
37 j2s_pool->map_len = 1;
38 } else {
39 j2s_pool->map_len++;
40 j2s_pool->maps_list = (map_index_t *)realloc(
41 j2s_pool->maps_list, j2s_pool->map_len * sizeof(map_index_t));
42 }
43
44 j2s_pool->maps_list[j2s_pool->map_len - 1].dst_offset =
45 (void *)((uint8_t *)dst - j2s_pool->data);
46
47 j2s_pool->maps_list[j2s_pool->map_len - 1].ptr_offset =
48 (void *)((uint8_t *)ptr - j2s_pool->data);
49
50 j2s_pool->maps_list[j2s_pool->map_len - 1].len = len;
51
52 return 0;
53 }
54
j2s_alloc_data(j2s_ctx * ctx,size_t size,size_t * real_size)55 void *j2s_alloc_data(j2s_ctx *ctx, size_t size, size_t* real_size) {
56 void *ptr = NULL;
57 j2s_pool_t *j2s_pool = (j2s_pool_t *)ctx->priv;
58
59 if (!j2s_pool) {
60 ctx->priv = malloc(sizeof(j2s_pool_t));
61 j2s_pool = (j2s_pool_t *)ctx->priv;
62 }
63
64 if (!j2s_pool) {
65 ERR("Create j2s Pool failed!\n");
66 return NULL;
67 }
68
69 if (j2s_pool->used + size >= J2S_POOL_SIZE) {
70 ERR("Error: j2s poll over flow!!\n");
71 return NULL;
72 }
73 if (!j2s_pool->data) {
74 j2s_pool->data = (uint8_t *)malloc(J2S_POOL_SIZE);
75 ptr = j2s_pool->data;
76 } else {
77 ptr = ((uint8_t *)j2s_pool->data + j2s_pool->used);
78 }
79
80 DBG("%palloc [%zu]/[%zu]@[%p]-offset[%zu]\n", ctx, size, j2s_pool->used, ptr,
81 (uint8_t *)ptr - j2s_pool->data);
82
83 // 32bit 16 64bit 32
84 size_t offset = aligned_size(size, sizeof(void *) * 4);
85 j2s_pool->used += offset;
86 *real_size = offset;
87
88 if (!ptr)
89 return NULL;
90
91 return ptr;
92 }
93
j2s_read_file(const char * file,size_t * size)94 void *j2s_read_file(const char *file, size_t *size) {
95 struct stat st;
96 void *buf;
97 int fd;
98
99 DASSERT_MSG(file && !stat(file, &st), return NULL, "no such file: '%s'\n",
100 file ? file : "<null>");
101
102 fd = open(file, O_RDONLY);
103 DASSERT_MSG(fd >= 0, return NULL, "failed to open: '%s'\n", file);
104
105 buf = malloc(st.st_size + 1);
106 DASSERT(buf, return NULL);
107
108 DBG("Read file: '%s'\n", file);
109
110 if (read(fd, buf, st.st_size) != st.st_size) {
111 ERR("failed to read: '%s'\n", file);
112 free(buf);
113 close(fd);
114 return NULL;
115 }
116
117 ((char *)buf)[st.st_size] = '\0';
118 *size = st.st_size;
119
120 close(fd);
121 return buf;
122 }
123
j2s_init(j2s_ctx * ctx)124 void j2s_init(j2s_ctx *ctx) {
125 DBG("J2S version: %s\n", J2S_VERSION);
126
127 return _j2s_init(ctx);
128 }
129
j2s_deinit(j2s_ctx * ctx)130 void j2s_deinit(j2s_ctx *ctx) {
131 DBG("J2S deinit: %p\n", ctx);
132 }
133
j2s_json_file_to_struct(j2s_ctx * ctx,const char * file,const char * name,void * ptr)134 int j2s_json_file_to_struct(j2s_ctx *ctx, const char *file, const char *name,
135 void *ptr) {
136 struct stat st;
137 size_t size;
138 char *buf;
139 int ret = -1;
140
141 DASSERT_MSG(file && !stat(file, &st), return -1, "no such file: '%s'\n",
142 file ? file : "<null>");
143
144 memset(ptr, 0, j2s_struct_size(ctx, ctx->root_index));
145
146 buf = (char *)j2s_read_file(file, &size);
147 if (!buf)
148 goto out;
149
150 DBG("Parse file: '%s', content:\n%s\n", file, buf);
151
152 if (j2s_modify_struct(ctx, buf, name, ptr) < 0)
153 goto out;
154
155 ret = 0;
156 out:
157 if (buf)
158 free(buf);
159 return ret;
160 }
161
j2s_dump_struct(j2s_ctx * ctx,const char * name,void * ptr)162 char *j2s_dump_struct(j2s_ctx *ctx, const char *name, void *ptr) {
163 cJSON *json, *item;
164 char *buf;
165
166 DBG("Dump: %s\n", name ? name : "root struct");
167
168 if (!name) {
169 json = j2s_root_struct_to_json(ctx, ptr);
170 } else {
171 json = j2s_struct_to_json(ctx, name, ptr);
172 }
173
174 DASSERT(json, return NULL);
175
176 if (ctx->dump_enums) {
177 item = j2s_enums_to_json(ctx);
178 if (item)
179 cJSON_AddItemToObject(json, "@enum", item);
180 }
181
182 if (ctx->format_json) {
183 buf = cJSON_Print(json);
184 } else {
185 buf = cJSON_PrintUnformatted(json);
186 }
187
188 cJSON_Delete(json);
189 return buf;
190 }
191
j2s_modify_struct(j2s_ctx * ctx,const char * str,const char * name,void * ptr)192 int j2s_modify_struct(j2s_ctx *ctx, const char *str, const char *name,
193 void *ptr) {
194 cJSON *json;
195 int ret = -1;
196
197 json = cJSON_Parse(str);
198 DASSERT_MSG(json, return -1, "failed to parse: '%s'\n", str);
199
200 DBG("Modify:\n%s\n", str);
201
202 ret = j2s_json_to_struct(ctx, json, name, ptr);
203
204 cJSON_Delete(json);
205 return ret;
206 }
207
j2s_query_struct(j2s_ctx * ctx,const char * str,void * ptr)208 char *j2s_query_struct(j2s_ctx *ctx, const char *str, void *ptr) {
209 cJSON *json;
210 char *buf;
211
212 json = cJSON_Parse(str);
213 DASSERT_MSG(json, return NULL, "failed to parse: '%s'\n", str);
214
215 DBG("Query:\n%s\n", str);
216
217 if (j2s_json_from_root_struct(ctx, json, ptr) < 0) {
218 cJSON_Delete(json);
219 return NULL;
220 }
221
222 if (ctx->format_json) {
223 buf = cJSON_Print(json);
224 } else {
225 buf = cJSON_PrintUnformatted(json);
226 }
227
228 cJSON_Delete(json);
229 return buf;
230 }
231
j2s_dump_template_struct(j2s_ctx * ctx,const char * name)232 char *j2s_dump_template_struct(j2s_ctx *ctx, const char *name) {
233 cJSON *json, *item;
234 char *buf;
235
236 DBG("Dump template: %s\n", name ? name : "root struct");
237
238 if (!name) {
239 json = j2s_root_struct_to_template_json(ctx);
240 } else {
241 json = j2s_struct_to_template_json(ctx, name);
242 }
243
244 DASSERT(json, return NULL);
245
246 if (ctx->dump_enums) {
247 item = j2s_enums_to_json(ctx);
248 if (item)
249 cJSON_AddItemToObject(json, "@enum", item);
250 }
251
252 if (ctx->format_json) {
253 buf = cJSON_Print(json);
254 } else {
255 buf = cJSON_PrintUnformatted(json);
256 }
257
258 cJSON_Delete(json);
259 return buf;
260 }
261
j2s_dump_structs(j2s_ctx * ctx,j2s_struct_info * info)262 char *j2s_dump_structs(j2s_ctx *ctx, j2s_struct_info *info) {
263 cJSON *json, *item;
264 char *buf;
265
266 if (!info || !info->name)
267 return NULL;
268
269 DBG("Dump structs\n");
270
271 json = cJSON_CreateObject();
272 DASSERT(json, return NULL);
273
274 for (; info->name; info++) {
275 item = j2s_struct_to_json(ctx, info->name, info->ptr);
276 if (!item)
277 continue;
278
279 cJSON_AddItemToObject(json, info->name, item);
280 }
281
282 if (ctx->dump_enums) {
283 item = j2s_enums_to_json(ctx);
284 if (item)
285 cJSON_AddItemToObject(json, "@enum", item);
286 }
287
288 if (ctx->format_json) {
289 buf = cJSON_Print(json);
290 } else {
291 buf = cJSON_PrintUnformatted(json);
292 }
293
294 cJSON_Delete(json);
295 return buf;
296 }
297