/src/libredwg/src/in_json.c
Line | Count | Source |
1 | | /*****************************************************************************/ |
2 | | /* LibreDWG - free implementation of the DWG file format */ |
3 | | /* */ |
4 | | /* Copyright (C) 2020-2025 Free Software Foundation, Inc. */ |
5 | | /* */ |
6 | | /* This library is free software, licensed under the terms of the GNU */ |
7 | | /* General Public License as published by the Free Software Foundation, */ |
8 | | /* either version 3 of the License, or (at your option) any later version. */ |
9 | | /* You should have received a copy of the GNU General Public License */ |
10 | | /* along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
11 | | /*****************************************************************************/ |
12 | | |
13 | | /* |
14 | | * in_json.c: parse JSON via jsmn/jsmn.h |
15 | | * written by Reini Urban |
16 | | */ |
17 | | |
18 | | #include "config.h" |
19 | | #include <stdio.h> |
20 | | #include <stdlib.h> |
21 | | #include <string.h> |
22 | | #include <assert.h> |
23 | | #include <math.h> |
24 | | #include <errno.h> |
25 | | #include <limits.h> |
26 | | |
27 | | #define IS_ENCODER |
28 | | #define IS_JSON |
29 | | #include "common.h" |
30 | | #include "importer.h" |
31 | | #include "bits.h" |
32 | | #include "dwg.h" |
33 | | #include "hash.h" |
34 | | #include "decode.h" |
35 | | #include "dynapi.h" |
36 | | #include "classes.h" |
37 | | #include "in_json.h" |
38 | | |
39 | | static unsigned int loglevel; |
40 | 240k | #define DWG_LOGLEVEL loglevel |
41 | | #include "logging.h" |
42 | | |
43 | | #include "in_dxf.h" |
44 | | |
45 | | // not exported |
46 | | #define JSMN_STATIC |
47 | | // probably not needed in the final version (counting keys) |
48 | | #undef JSMN_PARENT_LINKS |
49 | | // our files are bigger than 8000 |
50 | | // In strict mode primitive must be followed by "," or "}" or "]"; |
51 | | // comma/object/array |
52 | | // In strict mode an object or array can't become a key |
53 | | // In strict mode primitives are: numbers and booleans |
54 | | #undef JSMN_STRICT |
55 | | #include "../jsmn/jsmn.h" |
56 | | |
57 | | typedef struct jsmntokens |
58 | | { |
59 | | unsigned int index; |
60 | | jsmntok_t *tokens; |
61 | | long num_tokens; |
62 | | } jsmntokens_t; |
63 | | |
64 | | // synced with enum jsmntype_t |
65 | | static const char *const t_typename[] |
66 | | = { "UNDEFINED", "OBJECT", "ARRAY", "STRING", "PRIMITIVE" }; |
67 | | |
68 | | /* the current version per spec block */ |
69 | | static unsigned int cur_ver = 0; |
70 | | static char *created_by; |
71 | | static Bit_Chain *g_dat; |
72 | | |
73 | | #define json_expect(tokens, typ) \ |
74 | | if (tokens->tokens[tokens->index].type != JSMN_##typ) \ |
75 | | return DWG_ERR_INVALIDTYPE |
76 | | |
77 | | /*-------------------------------------------------------------------------------- |
78 | | * MACROS |
79 | | */ |
80 | | |
81 | | #define ACTION injson |
82 | | |
83 | | /******************************************************************/ |
84 | | #define _FIELD_FLOAT(nam, type) \ |
85 | | else if (strEQc (key, #nam)) \ |
86 | | { \ |
87 | | _obj->nam = (BITCODE_##type)json_float (dat, tokens); \ |
88 | | LOG_TRACE (#nam ": " FORMAT_##type "\n", _obj->nam) \ |
89 | | } |
90 | | #define _FIELD_LONG(nam, type) \ |
91 | 101k | else if (strEQc (key, #nam)) \ |
92 | 100k | { \ |
93 | 0 | _obj->nam = (BITCODE_##type)json_long (dat, tokens); \ |
94 | 0 | LOG_TRACE (#nam ": " FORMAT_##type "\n", _obj->nam) \ |
95 | 0 | } |
96 | | #define SUB_FIELD_LONG(o, nam, type) \ |
97 | 0 | else if (strEQc (key, #nam)) \ |
98 | 0 | { \ |
99 | 0 | _obj->o.nam = (BITCODE_##type)json_long (dat, tokens); \ |
100 | 0 | LOG_TRACE (#nam ": " FORMAT_##type "\n", _obj->o.nam) \ |
101 | 0 | } |
102 | | #define _FIELD_LONGLONG(nam, type) \ |
103 | 50.7k | else if (strEQc (key, #nam)) \ |
104 | 49.7k | { \ |
105 | 1.06k | _obj->nam = (BITCODE_##type)json_longlong (dat, tokens); \ |
106 | 1.06k | LOG_TRACE (#nam ": " FORMAT_##type "\n", _obj->nam) \ |
107 | 1.06k | } |
108 | | #define _FIELD_LONGT(nam, type, fmt) \ |
109 | 54.0k | else if (strEQc (key, #nam)) \ |
110 | 54.0k | { \ |
111 | 0 | _obj->nam = (BITCODE_##type)json_long (dat, tokens); \ |
112 | 0 | LOG_TRACE (#nam ": " FORMAT_##fmt "\n", _obj->nam) \ |
113 | 0 | } |
114 | | #define FIELD_TFF(nam, len, dxf) \ |
115 | 3.75k | else if (strEQc (key, #nam)) \ |
116 | 3.75k | { \ |
117 | 0 | char *s = json_string (dat, tokens); \ |
118 | 0 | if (s) \ |
119 | 0 | { \ |
120 | 0 | size_t slen = strlen (s); \ |
121 | 0 | memcpy (&_obj->nam, s, MIN (len, slen)); \ |
122 | 0 | LOG_TRACE (#nam ": \"%.*s\"\n", len, _obj->nam); \ |
123 | 0 | free (s); \ |
124 | 0 | } \ |
125 | 0 | else \ |
126 | 0 | { \ |
127 | 0 | LOG_TRACE (#nam ": NULL\n"); \ |
128 | 0 | } \ |
129 | 0 | } |
130 | | #define FIELD_TFFx(nam, len, dxf) \ |
131 | 157k | else if (strEQc (key, #nam)) \ |
132 | 155k | { \ |
133 | 0 | size_t slen; \ |
134 | 0 | unsigned char *s = json_binary (dat, tokens, #nam, &slen); \ |
135 | 0 | if (s) \ |
136 | 0 | { \ |
137 | 0 | slen = MIN (len, slen); \ |
138 | 0 | memcpy (&_obj->nam, s, slen); \ |
139 | 0 | LOG_TRACE (#nam ": \"%.*s\"\n", (int)slen, _obj->nam); \ |
140 | 0 | free (s); \ |
141 | 0 | } \ |
142 | 0 | } |
143 | | #define FIELD_BINARY(nam, lenf, dxf) \ |
144 | 0 | else if (strEQc (key, #nam)) \ |
145 | 0 | { \ |
146 | 0 | size_t slen; \ |
147 | 0 | _obj->nam = json_binary (dat, tokens, #nam, &slen); \ |
148 | 0 | _obj->lenf = slen & 0xFFFFFFFF; \ |
149 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
150 | 0 | } |
151 | | #define FIELD_T(nam, dxf) \ |
152 | 0 | else if (strEQc (key, #nam)) \ |
153 | 0 | { \ |
154 | 0 | LOG_TRACE (#nam ": \"%.*s\"\n", t->end - t->start, \ |
155 | 0 | &dat->chain[t->start]); \ |
156 | 0 | if (t->type == JSMN_STRING) \ |
157 | 0 | { \ |
158 | 0 | /*if (dwg->header.version >= R_2007) \ |
159 | 0 | _obj->nam = (BITCODE_T)json_wstring (dat, tokens); \ |
160 | 0 | else*/ \ |
161 | 0 | _obj->nam = json_string (dat, tokens); \ |
162 | 0 | } \ |
163 | 0 | else \ |
164 | 0 | { \ |
165 | 0 | _obj->nam = NULL; \ |
166 | 0 | json_advance_unknown (dat, tokens, t->type, 0); \ |
167 | 0 | } \ |
168 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
169 | 0 | } |
170 | | #define FIELD_T32(nam, dxf) \ |
171 | 0 | else if (strEQc (key, #nam)) \ |
172 | 0 | { \ |
173 | 0 | LOG_TRACE (#nam ": \"%.*s\"\n", t->end - t->start, \ |
174 | 0 | &dat->chain[t->start]); \ |
175 | 0 | if (t->type == JSMN_STRING) \ |
176 | 0 | _obj->nam = (BITCODE_T32)json_string (dat, tokens); \ |
177 | 0 | else \ |
178 | 0 | { \ |
179 | 0 | _obj->nam = NULL; \ |
180 | 0 | json_advance_unknown (dat, tokens, t->type, 0); \ |
181 | 0 | } \ |
182 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
183 | 0 | } |
184 | | #define FIELD_T16(nam, dxf) \ |
185 | 209k | else if (strEQc (key, #nam)) \ |
186 | 209k | { \ |
187 | 2.20k | LOG_TRACE (#nam ": \"%.*s\"\n", t->end - t->start, \ |
188 | 2.20k | &dat->chain[t->start]); \ |
189 | 2.20k | if (t->type == JSMN_STRING) \ |
190 | 2.20k | { \ |
191 | 8 | _obj->nam = json_string (dat, tokens); \ |
192 | 8 | } \ |
193 | 2.20k | else \ |
194 | 2.20k | { \ |
195 | 2.20k | _obj->nam = NULL; \ |
196 | 2.20k | json_advance_unknown (dat, tokens, t->type, 0); \ |
197 | 2.20k | } \ |
198 | 2.20k | JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
199 | 2.20k | } |
200 | | #define FIELD_TU16(nam, dxf) \ |
201 | | else if (strEQc (key, #nam)) \ |
202 | | { \ |
203 | | LOG_TRACE (#nam ": \"%.*s\"\n", t->end - t->start, \ |
204 | | &dat->chain[t->start]); \ |
205 | | if (t->type == JSMN_STRING) \ |
206 | | _obj->nam = json_wstring (dat, tokens); \ |
207 | | else \ |
208 | | { \ |
209 | | _obj->nam = NULL; \ |
210 | | json_advance_unknown (dat, tokens, t->type, 0); \ |
211 | | } \ |
212 | | JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
213 | | } |
214 | | #define FIELD_TIMERLL(nam, dxf) \ |
215 | 5.23k | else if (strEQc (key, #nam)) \ |
216 | 5.23k | { \ |
217 | 0 | json_TIMERLL (dat, tokens, #nam, "TIMERLL", &_obj->nam); \ |
218 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
219 | 0 | } |
220 | | |
221 | | #define FIELD_B(nam, dxf) _FIELD_LONG (nam, B) |
222 | | #define FIELD_BB(nam, dxf) _FIELD_LONG (nam, BB) |
223 | | #define FIELD_3B(nam, dxf) _FIELD_LONG (nam, 3B) |
224 | 11.2k | #define FIELD_BS(nam, dxf) _FIELD_LONG (nam, BS) |
225 | | #define FIELD_BL(nam, dxf) _FIELD_LONG (nam, BL) |
226 | | #define FIELD_BLL(nam, dxf) _FIELD_LONG (nam, BLL) |
227 | 12.7k | #define FIELD_RC(nam, dxf) _FIELD_LONG (nam, RC) |
228 | | #define FIELD_RCd(nam, dxf) _FIELD_LONG (nam, RCd) |
229 | | #define FIELD_RCx(nam, dxf) _FIELD_LONGT (nam, RC, RCx) |
230 | 7.50k | #define FIELD_RS(nam, dxf) _FIELD_LONG (nam, RS) |
231 | 0 | #define FIELD_RSx(nam, dxf) _FIELD_LONGT (nam, RS, RSx) |
232 | 69.6k | #define FIELD_RL(nam, dxf) _FIELD_LONG (nam, RL) |
233 | 4.15k | #define FIELD_RLx(nam, dxf) _FIELD_LONGT (nam, RL, RLx) |
234 | 49.8k | #define FIELD_RLd(nam, dxf) _FIELD_LONGT (nam, RL, RLd) |
235 | 50.7k | #define FIELD_RLL(nam, dxf) _FIELD_LONGLONG (nam, RLL) |
236 | 0 | #define FIELD_HV(nam, dxf) _FIELD_LONGLONG (nam, HV) |
237 | | #define FIELD_MC(nam, dxf) _FIELD_LONG (nam, MC) |
238 | | #define FIELD_MS(nam, dxf) _FIELD_LONG (nam, MS) |
239 | | |
240 | | #define FIELD_BD(nam, dxf) _FIELD_FLOAT (nam, BD) |
241 | | #define FIELD_RD(nam, dxf) _FIELD_FLOAT (nam, RD) |
242 | | |
243 | | // NOTE: Only for int types for now, no float. There don't exist any inlined |
244 | | // float vectors |
245 | | #define FIELD_VECTOR_INL(nam, typ, _size, dxf) \ |
246 | 0 | else if (strEQc (key, #nam) && t->type == JSMN_ARRAY && t->size == _size) \ |
247 | 0 | { \ |
248 | 0 | tokens->index++; \ |
249 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
250 | 0 | for (int vcount = 0; vcount < _size; vcount++) \ |
251 | 0 | { \ |
252 | 0 | _obj->nam[vcount] = (BITCODE_##typ)json_long (dat, tokens); \ |
253 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
254 | 0 | LOG_TRACE (#nam "[%d]: " FORMAT_##typ " [" #typ " %d]\n", vcount, \ |
255 | 0 | _obj->nam[vcount], dxf); \ |
256 | 0 | } \ |
257 | 0 | } |
258 | | // e.g. FIELD_VECTOR (histories, RL, num_histories, 0) |
259 | | #define FIELD_VECTOR(nam, typ, _sizef, dxf) \ |
260 | 0 | else if (strEQc (key, #nam) && t->type == JSMN_ARRAY) \ |
261 | 0 | { \ |
262 | 0 | _obj->nam = (BITCODE_##typ *)calloc (t->size, sizeof (BITCODE_##typ)); \ |
263 | 0 | _obj->_sizef = t->size; \ |
264 | 0 | tokens->index++; \ |
265 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
266 | 0 | for (int vcount = 0; vcount < (int)t->size; vcount++) \ |
267 | 0 | { \ |
268 | 0 | _obj->nam[vcount] = (BITCODE_##typ)json_long (dat, tokens); \ |
269 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
270 | 0 | LOG_TRACE (#nam "[%d]: " FORMAT_##typ " [" #typ " %d]\n", vcount, \ |
271 | 0 | _obj->nam[vcount], dxf); \ |
272 | 0 | } \ |
273 | 0 | } |
274 | | |
275 | | #define JSON_TOKENS_CHECK_OVERFLOW(ret) \ |
276 | 383k | if (tokens->index > (unsigned int)tokens->num_tokens) \ |
277 | 383k | { \ |
278 | 2.24k | LOG_ERROR ("Unexpected end of JSON at %u of %ld tokens", tokens->index, \ |
279 | 2.24k | tokens->num_tokens); \ |
280 | 2.24k | ret; \ |
281 | 2.24k | } |
282 | | #define JSON_TOKENS_CHECK_OVERFLOW_LABEL(label) \ |
283 | | JSON_TOKENS_CHECK_OVERFLOW (goto label) |
284 | | #define JSON_TOKENS_CHECK_OVERFLOW_ERR \ |
285 | 252k | JSON_TOKENS_CHECK_OVERFLOW (return DWG_ERR_INVALIDDWG) |
286 | | #define JSON_TOKENS_CHECK_OVERFLOW_NULL \ |
287 | 8 | JSON_TOKENS_CHECK_OVERFLOW (return NULL) |
288 | 129k | #define JSON_TOKENS_CHECK_OVERFLOW_VOID JSON_TOKENS_CHECK_OVERFLOW (return) |
289 | | |
290 | | // advance until next known first-level type |
291 | | // on OBJECT to end of OBJECT |
292 | | // on ARRAY to end of ARRAY |
293 | | // on STRING (key) get next |
294 | | static int |
295 | | json_advance_unknown (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens, |
296 | | jsmntype_t type, int depth) |
297 | 117k | { |
298 | 117k | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
299 | 117k | int error = 0; |
300 | 117k | JSON_TOKENS_CHECK_OVERFLOW_ERR |
301 | 115k | if (depth > 25) |
302 | 2.21k | { |
303 | 2.21k | LOG_ERROR ("JSON recursion limit"); |
304 | 2.21k | return DWG_ERR_INVALIDDWG; |
305 | 2.21k | } |
306 | 113k | if (!depth || ((dat->opts & DWG_OPTS_LOGLEVEL) >= 3)) |
307 | 113k | LOG_TRACE ("Skip JSON %s %.*s at %u of %ld tokens\n", t_typename[t->type], |
308 | 113k | t->end - t->start, &dat->chain[t->start], tokens->index, |
309 | 113k | tokens->num_tokens); |
310 | 113k | switch (t->type) |
311 | 113k | { |
312 | 21.5k | case JSMN_OBJECT: |
313 | 21.7k | case JSMN_ARRAY: |
314 | 21.7k | tokens->index++; |
315 | 21.7k | JSON_TOKENS_CHECK_OVERFLOW_ERR |
316 | 30.1k | for (int i = 0; i < t->size; i++) |
317 | 8.34k | { |
318 | 8.34k | if (t->type == JSMN_OBJECT) |
319 | 8.13k | tokens->index++; // skip the key also |
320 | 8.34k | error |= json_advance_unknown (dat, tokens, t->type, depth + 1); |
321 | 8.34k | } |
322 | 21.7k | return error; |
323 | 13.3k | case JSMN_STRING: |
324 | 44.2k | case JSMN_PRIMITIVE: |
325 | 44.2k | tokens->index++; |
326 | 44.2k | JSON_TOKENS_CHECK_OVERFLOW_ERR |
327 | 44.2k | return error; |
328 | 47.2k | case JSMN_UNDEFINED: |
329 | 47.2k | default: |
330 | 47.2k | return error; |
331 | 113k | } |
332 | 0 | return error; |
333 | 113k | } |
334 | | |
335 | | static void |
336 | | json_fixed_key (char *key, Bit_Chain *restrict dat, |
337 | | jsmntokens_t *restrict tokens) |
338 | 66.9k | { |
339 | 66.9k | const jsmntok_t *t; |
340 | 66.9k | int len; |
341 | 66.9k | JSON_TOKENS_CHECK_OVERFLOW_VOID |
342 | 66.9k | t = &tokens->tokens[tokens->index]; |
343 | 66.9k | len = t->end - t->start; |
344 | 66.9k | *key = 0; |
345 | 66.9k | if (t->type != JSMN_STRING) |
346 | 46.7k | { |
347 | 46.7k | LOG_ERROR ("Expected JSON STRING"); |
348 | 46.7k | json_advance_unknown (dat, tokens, t->type, 0); |
349 | 46.7k | JSON_TOKENS_CHECK_OVERFLOW_VOID |
350 | 46.7k | return; |
351 | 46.7k | } |
352 | 20.1k | if (len >= 80) |
353 | 0 | { |
354 | 0 | LOG_ERROR ("Overlong JSON STRING len=%d >= 80", len); |
355 | 0 | tokens->index++; |
356 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
357 | 0 | return; |
358 | 0 | } |
359 | 20.1k | if (len > 0) |
360 | 16.1k | { |
361 | 16.1k | memcpy (key, &dat->chain[t->start], len); |
362 | 16.1k | key[len] = '\0'; |
363 | 16.1k | tokens->index++; |
364 | 16.1k | JSON_TOKENS_CHECK_OVERFLOW_VOID |
365 | 16.1k | } |
366 | 4.05k | else |
367 | 20.1k | LOG_ERROR ("Empty JSON key"); |
368 | 20.1k | return; |
369 | 20.1k | } |
370 | | |
371 | | ATTRIBUTE_MALLOC |
372 | | static char * |
373 | | json_string (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens) |
374 | 8 | { |
375 | 8 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
376 | 8 | char *key = NULL; |
377 | 8 | int len; |
378 | 8 | JSON_TOKENS_CHECK_OVERFLOW_NULL; |
379 | 8 | len = t->end - t->start; |
380 | 8 | if (t->type != JSMN_STRING) |
381 | 0 | { |
382 | 0 | LOG_ERROR ("Expected JSON STRING"); |
383 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
384 | 0 | JSON_TOKENS_CHECK_OVERFLOW_NULL |
385 | 0 | return NULL; |
386 | 0 | } |
387 | | // Unquote \", convert Unicode to \\U+xxxx as in bit_embed_TU |
388 | | // unquote \\ to \. |
389 | 8 | if (memchr (&dat->chain[t->start], '\\', len)) |
390 | 8 | { |
391 | 8 | len += 8; |
392 | 8 | key = (char *)calloc (1, len); |
393 | 8 | if (!key) |
394 | 0 | goto outofmemory; |
395 | 8 | dat->chain[t->end] = '\0'; |
396 | 8 | while (!bit_utf8_to_TV (key, &dat->chain[t->start], len, |
397 | 8 | t->end - t->start, 1, dat->codepage)) |
398 | 0 | { |
399 | 0 | LOG_INSANE ("Not enough room in quoted string len=%d\n", len - 8) |
400 | 0 | len += 8; |
401 | 0 | if (len > 6 * (t->end - t->start)) |
402 | 0 | { |
403 | 0 | LOG_ERROR ("bit_utf8_to_TV loop len=%d vs %d \"%.*s\"", len, |
404 | 0 | t->end - t->start, t->end - t->start, |
405 | 0 | &dat->chain[t->start]); |
406 | 0 | len = t->end - t->start; |
407 | 0 | free (key); |
408 | 0 | goto normal; |
409 | 0 | } |
410 | 0 | key = (char *)realloc (key, len); |
411 | 0 | if (!key) |
412 | 0 | goto outofmemory; |
413 | 0 | } |
414 | 8 | } |
415 | 0 | else |
416 | 0 | { |
417 | 0 | normal: |
418 | 0 | key = (char *)malloc (len + 1); |
419 | 0 | if (!key) |
420 | 0 | goto outofmemory; |
421 | 0 | memcpy (key, &dat->chain[t->start], len); |
422 | 0 | key[len] = '\0'; |
423 | 0 | } |
424 | 8 | tokens->index++; |
425 | 8 | return key; |
426 | 0 | outofmemory: |
427 | 0 | LOG_ERROR ("Out of memory"); |
428 | 0 | return NULL; |
429 | 8 | } |
430 | | |
431 | | ATTRIBUTE_MALLOC |
432 | | static char * |
433 | | json_fixed_string (Bit_Chain *restrict dat, const int len, |
434 | | jsmntokens_t *restrict tokens) |
435 | 0 | { |
436 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
437 | 0 | char *str = (char *)calloc (len + 1, 1); |
438 | 0 | int l; |
439 | 0 | JSON_TOKENS_CHECK_OVERFLOW_NULL; |
440 | 0 | l = t->end - t->start; |
441 | 0 | if (!str) |
442 | 0 | goto outofmemory; |
443 | 0 | if (t->type != JSMN_STRING) |
444 | 0 | { |
445 | 0 | LOG_ERROR ("Expected JSON STRING"); |
446 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
447 | 0 | JSON_TOKENS_CHECK_OVERFLOW_NULL |
448 | 0 | return NULL; |
449 | 0 | } |
450 | | // Unquote \", convert Unicode to \\U+xxxx as in bit_embed_TU |
451 | | // unquote \\ to \. |
452 | 0 | if (memchr (&dat->chain[t->start], '\\', l)) |
453 | 0 | { |
454 | 0 | int dlen = len; |
455 | 0 | dat->chain[t->end] = '\0'; |
456 | 0 | while (!bit_utf8_to_TV (str, &dat->chain[t->start], dlen, l, 1, |
457 | 0 | dat->codepage)) |
458 | 0 | { |
459 | 0 | LOG_INSANE ("Not enough room in quoted string len=%d\n", len) |
460 | 0 | dlen += 8; |
461 | 0 | if (dlen > 6 * l) |
462 | 0 | { |
463 | 0 | LOG_ERROR ("bit_utf8_to_TV loop len=%d vs %d \"%.*s\"", len, l, |
464 | 0 | l, &dat->chain[t->start]); |
465 | | // len = t->end - t->start; |
466 | 0 | free (str); |
467 | 0 | str = NULL; |
468 | 0 | goto normal; |
469 | 0 | } |
470 | 0 | str = (char *)realloc (str, dlen); |
471 | 0 | if (!str) |
472 | 0 | goto outofmemory; |
473 | 0 | } |
474 | 0 | str[len] = '\0'; |
475 | 0 | } |
476 | 0 | else |
477 | 0 | { |
478 | 0 | char *p; |
479 | 0 | normal: |
480 | 0 | if (!str) |
481 | 0 | return NULL; |
482 | 0 | if (l > len) |
483 | 0 | { |
484 | 0 | memcpy (str, &dat->chain[t->start], len); |
485 | 0 | LOG_WARN ("Overlarge JSON TF value \"%.*s\" stripped to \"%s\"", l, |
486 | 0 | &dat->chain[t->start], str); |
487 | 0 | str[len] = '\0'; |
488 | 0 | } |
489 | 0 | else |
490 | 0 | { |
491 | 0 | memcpy (str, &dat->chain[t->start], l); |
492 | 0 | str[l] = '\0'; |
493 | 0 | } |
494 | 0 | } |
495 | 0 | tokens->index++; |
496 | 0 | return str; |
497 | 0 | outofmemory: |
498 | 0 | LOG_ERROR ("Out of memory"); |
499 | 0 | return NULL; |
500 | 0 | } |
501 | | |
502 | | ATTRIBUTE_MALLOC |
503 | | static unsigned char * |
504 | | json_binary (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens, |
505 | | const char *restrict key, size_t *lenp) |
506 | 0 | { |
507 | | // convert from hex |
508 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
509 | 0 | const size_t len = t->end - t->start; |
510 | 0 | const char *str = (char *)&dat->chain[t->start]; |
511 | 0 | const size_t blen = len / 2; |
512 | 0 | size_t read; |
513 | 0 | unsigned char *buf = len ? (unsigned char *)malloc (blen + 1) : NULL; |
514 | 0 | char *pos = (char *)str; |
515 | 0 | char *old; |
516 | |
|
517 | 0 | *lenp = 0; |
518 | 0 | if (t->type != JSMN_STRING || !pos) |
519 | 0 | { |
520 | 0 | LOG_ERROR ("Expected JSON STRING"); |
521 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
522 | 0 | free (buf); |
523 | 0 | JSON_TOKENS_CHECK_OVERFLOW_NULL |
524 | 0 | return NULL; |
525 | 0 | } |
526 | 0 | if (!buf) |
527 | 0 | { |
528 | 0 | if (len) |
529 | 0 | LOG_ERROR ("Out of memory"); |
530 | 0 | tokens->index++; |
531 | 0 | return NULL; |
532 | 0 | } |
533 | 0 | if ((read = in_hex2bin (buf, pos, blen) != blen)) |
534 | 0 | LOG_ERROR ("json_binary in_hex2bin with key %s at pos %" PRIuSIZE |
535 | 0 | " of %" PRIuSIZE, |
536 | 0 | key, read, blen); |
537 | 0 | if (buf) |
538 | 0 | { |
539 | 0 | buf[blen] = '\0'; |
540 | 0 | LOG_TRACE ("%s: '%.*s'... [BINARY %" PRIuSIZE "]\n", key, |
541 | 0 | MIN ((int)len, 60), str, len); |
542 | 0 | *lenp = blen; |
543 | 0 | } |
544 | 0 | tokens->index++; |
545 | 0 | return buf; |
546 | 0 | } |
547 | | |
548 | | static double |
549 | | json_float (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens) |
550 | 0 | { |
551 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
552 | | // int len = t->end - t->start; |
553 | 0 | if (t->type != JSMN_PRIMITIVE) |
554 | 0 | { |
555 | 0 | LOG_ERROR ("Expected JSON PRIMITIVE"); |
556 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
557 | 0 | JSON_TOKENS_CHECK_OVERFLOW (return (double)NAN) |
558 | 0 | return (double)NAN; |
559 | 0 | } |
560 | 0 | JSON_TOKENS_CHECK_OVERFLOW (return (double)NAN) |
561 | 0 | tokens->index++; |
562 | 0 | return strtod ((char *)&dat->chain[t->start], NULL); |
563 | 0 | } |
564 | | |
565 | | static uint32_t |
566 | | json_long (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens) |
567 | 0 | { |
568 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
569 | | // int len = t->end - t->start; |
570 | 0 | if (t->type != JSMN_PRIMITIVE) |
571 | 0 | { |
572 | 0 | LOG_ERROR ("Expected JSON PRIMITIVE"); |
573 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
574 | 0 | JSON_TOKENS_CHECK_OVERFLOW (return 0) |
575 | 0 | return 0; |
576 | 0 | } |
577 | 0 | JSON_TOKENS_CHECK_OVERFLOW (return 0) |
578 | 0 | tokens->index++; |
579 | 0 | return (uint32_t)strtol ((char *)&dat->chain[t->start], NULL, 10); |
580 | 0 | } |
581 | | |
582 | | static uint64_t |
583 | | json_longlong (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens) |
584 | 1.06k | { |
585 | 1.06k | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
586 | | // int len = t->end - t->start; |
587 | 1.06k | if (t->type != JSMN_PRIMITIVE) |
588 | 457 | { |
589 | 457 | LOG_ERROR ("Expected JSON PRIMITIVE"); |
590 | 457 | json_advance_unknown (dat, tokens, t->type, 0); |
591 | 457 | JSON_TOKENS_CHECK_OVERFLOW (return 0) |
592 | 457 | return 0; |
593 | 457 | } |
594 | 605 | JSON_TOKENS_CHECK_OVERFLOW (return 0) |
595 | 605 | tokens->index++; |
596 | 605 | #ifdef HAVE_STRTOULL |
597 | 605 | return strtoull ((char *)&dat->chain[t->start], NULL, 10); |
598 | | #else |
599 | | return strtoll ((char *)&dat->chain[t->start], NULL, 10); |
600 | | #endif |
601 | 605 | } |
602 | | |
603 | | static void |
604 | | json_3DPOINT (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens, |
605 | | const char *restrict name, const char *restrict key, |
606 | | const char *restrict type, BITCODE_3DPOINT *restrict pt) |
607 | 0 | { |
608 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
609 | 0 | if (t->type != JSMN_ARRAY || t->size != 3) |
610 | 0 | { |
611 | | // older DWG's often are only 2D |
612 | 0 | if (t->type != JSMN_ARRAY || dat->from_version >= R_13b1) |
613 | 0 | { |
614 | 0 | LOG_ERROR ("JSON 3DPOINT must be ARRAY of size 3") |
615 | 0 | return; |
616 | 0 | } |
617 | 0 | } |
618 | 0 | tokens->index++; |
619 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
620 | 0 | pt->x = json_float (dat, tokens); |
621 | 0 | pt->y = json_float (dat, tokens); |
622 | 0 | if (t->size == 3) |
623 | 0 | { |
624 | 0 | pt->z = json_float (dat, tokens); |
625 | 0 | LOG_TRACE ("%s.%s: (%f, %f, %f) [%s]\n", name, key, pt->x, pt->y, pt->z, |
626 | 0 | type); |
627 | 0 | } |
628 | 0 | else |
629 | 0 | { |
630 | 0 | pt->z = 0.0; |
631 | 0 | LOG_TRACE ("%s.%s: (%f, %f) [%s]\n", name, key, pt->x, pt->y, type); |
632 | 0 | } |
633 | 0 | } |
634 | | |
635 | | static void |
636 | | json_2DPOINT (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens, |
637 | | const char *restrict name, const char *restrict key, |
638 | | const char *restrict type, BITCODE_2DPOINT *restrict pt) |
639 | 0 | { |
640 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
641 | 0 | if (t->type != JSMN_ARRAY || t->size != 2) |
642 | 0 | { |
643 | 0 | LOG_ERROR ("JSON 2DPOINT must be ARRAY of size 2") |
644 | 0 | return; |
645 | 0 | } |
646 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
647 | 0 | tokens->index++; |
648 | 0 | pt->x = json_float (dat, tokens); |
649 | 0 | pt->y = json_float (dat, tokens); |
650 | 0 | LOG_TRACE ("%s.%s: (%f, %f) [%s]\n", name, key, pt->x, pt->y, type); |
651 | 0 | } |
652 | | |
653 | | static void |
654 | | json_TIMERLL (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens, |
655 | | const char *restrict name, const char *restrict type, |
656 | | BITCODE_TIMERLL *restrict tl) |
657 | 0 | { |
658 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
659 | 0 | if (t->type != JSMN_ARRAY || t->size != 2) |
660 | 0 | { |
661 | 0 | LOG_ERROR ("JSON TIMERLL must be ARRAY of size 2") |
662 | 0 | return; |
663 | 0 | } |
664 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
665 | 0 | tokens->index++; |
666 | 0 | tl->days = json_long (dat, tokens); |
667 | 0 | tl->ms = json_long (dat, tokens); |
668 | 0 | LOG_TRACE ("%s (%u, %u) [%s]\n", name, (unsigned)tl->days, (unsigned)tl->ms, |
669 | 0 | type); |
670 | 0 | } |
671 | | |
672 | | ATTRIBUTE_MALLOC |
673 | | static BITCODE_H |
674 | | json_HANDLE (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
675 | | jsmntokens_t *restrict tokens, const char *name, const char *key, |
676 | | const Dwg_Object *restrict obj, const int i) |
677 | 0 | { |
678 | 0 | uint32_t code, size, r11_idx; |
679 | 0 | BITCODE_RLL value, absref; |
680 | 0 | BITCODE_H ref; |
681 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
682 | 0 | if (t->type != JSMN_ARRAY || t->size < 2 || t->size > 5) |
683 | 0 | { |
684 | 0 | LOG_ERROR ("JSON HANDLE must be ARRAY of [ code, value ] or " |
685 | 0 | "[ code, size, value, absref ] or [ size, r11_idx, absref ]") |
686 | 0 | return NULL; |
687 | 0 | } |
688 | 0 | JSON_TOKENS_CHECK_OVERFLOW_NULL |
689 | 0 | tokens->index++; |
690 | 0 | code = json_long (dat, tokens); |
691 | 0 | if (i < 0) |
692 | 0 | { |
693 | 0 | LOG_TRACE ("%s.%s: ", name, key); |
694 | 0 | } |
695 | 0 | else // H* |
696 | 0 | { |
697 | 0 | LOG_TRACE ("%s.%s[%d]: ", name, key, i); |
698 | 0 | } |
699 | 0 | if (t->size >= 4) |
700 | 0 | { |
701 | 0 | size = json_long (dat, tokens); |
702 | 0 | value = json_longlong (dat, tokens); |
703 | 0 | absref = json_longlong (dat, tokens); |
704 | 0 | if (!code && strEQc (key, "sort_ents")) |
705 | 0 | ref = dwg_add_handleref (dwg, code, absref, NULL); |
706 | 0 | else |
707 | 0 | ref = dwg_add_handleref (dwg, code, absref, |
708 | 0 | (!code || code >= 6) ? obj : NULL); |
709 | 0 | if (t->size > 4) |
710 | 0 | ref->r11_idx = json_long (dat, tokens); // unused |
711 | 0 | if ((BITCODE_RC)size != ref->handleref.size |
712 | 0 | || value != ref->handleref.value) |
713 | 0 | { |
714 | | // Wrong user-input: GH #346 mingw64, oss-fuzz #39755 |
715 | | // but valid for !HANDLING preR13 |
716 | 0 | if (strEQ (name, "HEADER") && !dwg->header_vars.HANDLING |
717 | 0 | && dat->from_version <= R_11 |
718 | 0 | && (strEQc (key, "HANDSEED") || strEQc (key, "UCSNAME"))) |
719 | 0 | ; |
720 | 0 | else |
721 | 0 | LOG_ERROR ("Invalid handle %.*s => " FORMAT_REF " code=" FORMAT_BL |
722 | 0 | " size=" FORMAT_BL " value=" FORMAT_RLL |
723 | 0 | " absref=" FORMAT_RLL, |
724 | 0 | t->end - t->start, &dat->chain[t->start], |
725 | 0 | ARGS_REF (ref), code, size, value, absref); |
726 | 0 | ref->handleref.size = (BITCODE_RC)size; |
727 | 0 | ref->handleref.value = value; |
728 | 0 | ref->absolute_ref = absref; |
729 | 0 | } |
730 | 0 | if (t->size > 4) |
731 | 0 | LOG_TRACE (FORMAT_REF11 " [H]\n", ARGS_REF11 (ref)) |
732 | 0 | else |
733 | 0 | LOG_TRACE (FORMAT_REF " [H]\n", ARGS_REF (ref)) |
734 | 0 | } |
735 | 0 | else if (dat->from_version >= R_13b1) |
736 | 0 | { |
737 | | // code as 1st |
738 | 0 | if (t->size == 3) // since 0.12.5.5543 [code size value] |
739 | 0 | size = json_long (dat, tokens); |
740 | 0 | absref = json_longlong (dat, tokens); |
741 | 0 | ref = dwg_add_handleref (dwg, code, absref, |
742 | 0 | (!code || code >= 6) ? obj : NULL); |
743 | 0 | LOG_TRACE (FORMAT_REF " [H]\n", ARGS_REF (ref)) |
744 | 0 | } |
745 | 0 | else // r11 for HANDLING=1 and/or _CONTROL entries |
746 | 0 | { |
747 | | // [size idx absref] or [0 size absref] |
748 | 0 | size = code; |
749 | 0 | code = 0; |
750 | 0 | r11_idx = json_long (dat, tokens); |
751 | 0 | if (t->size == 3) |
752 | 0 | { |
753 | 0 | if (size == 0) // since 0.12.5.5543 [0 size value] |
754 | 0 | { |
755 | 0 | size = r11_idx; |
756 | 0 | r11_idx = 0; |
757 | 0 | } |
758 | 0 | else |
759 | 0 | code = 3; // r11 control entries default to 3 |
760 | 0 | absref = json_longlong (dat, tokens); |
761 | 0 | } |
762 | 0 | else |
763 | 0 | absref = r11_idx; // 2nd item, the value |
764 | 0 | ref = dwg_add_handleref (dwg, code, absref, obj); |
765 | 0 | if (t->size == 2) // [size absref] |
766 | 0 | ref->handleref.value = absref; |
767 | 0 | else |
768 | 0 | ref->r11_idx = r11_idx; |
769 | 0 | ref->handleref.size = size; |
770 | 0 | LOG_TRACE (FORMAT_REF11 " [H]\n", ARGS_REF11 (ref)) |
771 | 0 | } |
772 | 0 | return ref; |
773 | 0 | } |
774 | | |
775 | | static void |
776 | | json_CMC (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
777 | | jsmntokens_t *restrict tokens, const char *name, const char *fname, |
778 | | Dwg_Color *restrict color) |
779 | 0 | { |
780 | 0 | char key[80]; |
781 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
782 | 0 | memset (color, 0, sizeof (Dwg_Color)); |
783 | 0 | if (t->type == JSMN_OBJECT) |
784 | 0 | { // 2004+ |
785 | 0 | tokens->index++; // hash of index, rgb... |
786 | 0 | for (int j = 0; j < t->size; j++) |
787 | 0 | { |
788 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
789 | 0 | json_fixed_key (key, dat, tokens); |
790 | 0 | if (strEQc (key, "index")) |
791 | 0 | { |
792 | 0 | uint32_t num = json_long (dat, tokens); |
793 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
794 | 0 | color->index = (BITCODE_BSd)num; |
795 | 0 | LOG_TRACE ("%s.%s.index " FORMAT_BSd " [CMC]\n", name, fname, |
796 | 0 | color->index); |
797 | 0 | } |
798 | 0 | else if (strEQc (key, "rgb")) |
799 | 0 | { |
800 | 0 | char hex[80]; |
801 | 0 | json_fixed_key (hex, dat, tokens); |
802 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
803 | 0 | sscanf (hex, "%x", &color->rgb); |
804 | 0 | color->method = color->rgb >> 0x18; |
805 | 0 | LOG_TRACE ("%s.%s.rgb %x (method %x) [CMC]\n", name, fname, |
806 | 0 | color->rgb, color->method); |
807 | 0 | } |
808 | 0 | else if (strEQc (key, "flag")) |
809 | 0 | { |
810 | 0 | uint32_t num = json_long (dat, tokens); |
811 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
812 | 0 | LOG_TRACE ("%s.%s.flag %lu [CMC]\n", name, fname, |
813 | 0 | (unsigned long)num); |
814 | 0 | color->flag = (BITCODE_BS)num; |
815 | 0 | } |
816 | 0 | else if (strEQc (key, "alpha")) |
817 | 0 | { |
818 | 0 | uint32_t num = json_long (dat, tokens); |
819 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
820 | 0 | LOG_TRACE ("%s.%s.alpha %u [CMC]\n", name, fname, (unsigned)num); |
821 | 0 | color->alpha = (BITCODE_RC)num; |
822 | 0 | color->alpha_type = 3; |
823 | 0 | } |
824 | 0 | else if (strEQc (key, "handle")) // [4, value] ARRAY |
825 | 0 | { |
826 | 0 | color->handle |
827 | 0 | = json_HANDLE (dat, dwg, tokens, name, fname, NULL, -1); |
828 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
829 | 0 | } |
830 | 0 | else if (strEQc (key, "name")) |
831 | 0 | { |
832 | 0 | char *str = json_string (dat, tokens); |
833 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
834 | 0 | LOG_TRACE ("%s.%s.name \"%s\" [CMC]\n", name, fname, str); |
835 | 0 | color->name = str; |
836 | 0 | color->flag |= 1; |
837 | 0 | } |
838 | 0 | else if (strEQc (key, "book_name")) |
839 | 0 | { |
840 | 0 | char *str = json_string (dat, tokens); |
841 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
842 | 0 | LOG_TRACE ("%s.%s.book_name \"%s\" [CMC]\n", name, fname, str); |
843 | 0 | color->book_name = str; |
844 | 0 | color->flag |= 2; |
845 | 0 | } |
846 | 0 | else |
847 | 0 | { |
848 | 0 | LOG_WARN ("Unknown color key %s.%s.%s", name, fname, key); |
849 | 0 | tokens->index++; |
850 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
851 | 0 | } |
852 | 0 | } |
853 | 0 | } |
854 | 0 | else if (t->type == JSMN_PRIMITIVE) |
855 | 0 | { // pre 2004 |
856 | 0 | uint32_t num = json_long (dat, tokens); |
857 | 0 | color->index = (BITCODE_BSd)num; |
858 | 0 | LOG_TRACE ("%s.%s.index " FORMAT_BSd " [CMC]\n", name, fname, |
859 | 0 | color->index); |
860 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
861 | 0 | } |
862 | 0 | } |
863 | | |
864 | | static void |
865 | | json_TIMEBLL (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens, |
866 | | const char *name, BITCODE_TIMEBLL *date) |
867 | 0 | { |
868 | 0 | double ms; |
869 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
870 | | // the double format looses the last two digits 6-8 |
871 | 0 | if (t->type == JSMN_ARRAY && t->size == 2) |
872 | 0 | { |
873 | 0 | tokens->index++; |
874 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
875 | 0 | date->days = json_long (dat, tokens); |
876 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
877 | 0 | date->ms = json_long (dat, tokens); |
878 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
879 | 0 | date->value |
880 | 0 | = date->days |
881 | 0 | + (86400.0 * date->ms); // just for display, not calculations |
882 | 0 | } |
883 | 0 | else |
884 | 0 | { |
885 | 0 | double num; |
886 | 0 | num = json_float (dat, tokens); |
887 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
888 | 0 | date->value = num; |
889 | 0 | date->days = (BITCODE_BL)trunc (num); |
890 | 0 | date->ms = (BITCODE_BL)(86400.0 * (date->value - date->days)); |
891 | 0 | } |
892 | 0 | LOG_TRACE ("%s: %.08f (%u, %u) [TIMEBLL]\n", name, date->value, date->days, |
893 | 0 | date->ms); |
894 | 0 | } |
895 | | |
896 | | // array of subclass objects |
897 | | static void * |
898 | | json_records (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens, |
899 | | void *_obj, const char *subclass, BITCODE_BL *nump) |
900 | 0 | { |
901 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
902 | 0 | if (t->type != JSMN_ARRAY) |
903 | 0 | { |
904 | 0 | LOG_ERROR ("Expected %s ARRAY of OBJECTs", subclass); |
905 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
906 | 0 | JSON_TOKENS_CHECK_OVERFLOW_NULL |
907 | 0 | *nump = 0; |
908 | 0 | return NULL; |
909 | 0 | } |
910 | | // see subclass arrays, _set_struct_field |
911 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
912 | 0 | JSON_TOKENS_CHECK_OVERFLOW_NULL |
913 | 0 | return NULL; |
914 | 0 | } |
915 | | |
916 | | // of primitives only. may return NULL |
917 | | static void * |
918 | | json_vector (Bit_Chain *restrict dat, jsmntokens_t *restrict tokens, |
919 | | const char *key, const char *type, BITCODE_BL *nump) |
920 | 0 | { |
921 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
922 | 0 | BITCODE_BL *a_bl = NULL; |
923 | 0 | BITCODE_RLL *a_rll = NULL; |
924 | 0 | BITCODE_BD *a_bd = NULL; |
925 | 0 | BITCODE_TV *a_tv = NULL; |
926 | 0 | void *arr; |
927 | 0 | int len = t->size; |
928 | 0 | int size, is_str = 0, is_float = 0; |
929 | |
|
930 | 0 | if (t->type != JSMN_ARRAY) |
931 | 0 | { |
932 | 0 | LOG_ERROR ("Expected %s ARRAY", "key"); |
933 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
934 | 0 | JSON_TOKENS_CHECK_OVERFLOW_NULL |
935 | 0 | *nump = 0; |
936 | 0 | return NULL; |
937 | 0 | } |
938 | 0 | if (strEQc (type, "BL")) |
939 | 0 | { |
940 | 0 | size = sizeof (BITCODE_BL); |
941 | 0 | a_bl = len ? (BITCODE_BL *)calloc (len, size) : NULL; |
942 | 0 | arr = a_bl; |
943 | 0 | } |
944 | 0 | else if (strEQc (type, "RLL")) |
945 | 0 | { |
946 | 0 | size = sizeof (BITCODE_RLL); |
947 | 0 | a_rll = len ? (BITCODE_RLL *)calloc (len, size) : NULL; |
948 | 0 | arr = a_rll; |
949 | 0 | } |
950 | 0 | else if (strEQc (type, "BD")) |
951 | 0 | { |
952 | 0 | is_float = 1; |
953 | 0 | size = sizeof (BITCODE_BD); |
954 | 0 | a_bd = len ? (BITCODE_BD *)calloc (len, size) : NULL; |
955 | 0 | arr = a_bd; |
956 | 0 | } |
957 | 0 | else if (strEQc (type, "TV")) |
958 | 0 | { |
959 | 0 | is_str = 1; |
960 | 0 | size = sizeof (BITCODE_TV); |
961 | 0 | a_tv = len ? (BITCODE_TV *)calloc (len, size) : NULL; |
962 | 0 | arr = a_tv; |
963 | 0 | } |
964 | 0 | else |
965 | 0 | { |
966 | 0 | LOG_ERROR ("Unhandled json_vector type %s", type); |
967 | 0 | return NULL; |
968 | 0 | } |
969 | | // json_set_numfield (_obj, fields, key, size1); |
970 | 0 | *nump = len; |
971 | 0 | if (!len) |
972 | 0 | LOG_TRACE ("%s: [%s] empty\n", key, type); |
973 | 0 | tokens->index++; |
974 | 0 | for (int k = 0; k < len; k++) |
975 | 0 | { |
976 | 0 | JSON_TOKENS_CHECK_OVERFLOW_NULL; |
977 | 0 | t = &tokens->tokens[tokens->index]; |
978 | 0 | if (t->type != JSMN_PRIMITIVE) |
979 | 0 | { |
980 | 0 | LOG_ERROR ("Expected %s PRIMITIVE", "key"); |
981 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
982 | 0 | return arr; |
983 | 0 | } |
984 | 0 | if (is_str && a_tv) |
985 | 0 | { |
986 | 0 | a_tv[k] = json_string (dat, tokens); |
987 | 0 | JSON_TOKENS_CHECK_OVERFLOW_NULL; |
988 | 0 | LOG_TRACE ("%s[%d]: %s [%s]\n", key, k, a_tv[k], type); |
989 | 0 | } |
990 | 0 | else if (is_float && a_bd) |
991 | 0 | { |
992 | 0 | a_bd[k] = json_float (dat, tokens); |
993 | 0 | LOG_TRACE ("%s[%d]: %f [%s]\n", key, k, a_bd[k], type); |
994 | 0 | } |
995 | 0 | else if (strEQc (type, "RLL") && a_rll) |
996 | 0 | { |
997 | 0 | a_rll[k] = json_longlong (dat, tokens); |
998 | 0 | LOG_TRACE ("%s[%d]: " FORMAT_RLL " [%s]\n", key, k, a_rll[k], type); |
999 | 0 | } |
1000 | 0 | else if (strEQc (type, "BL") && a_bl) |
1001 | 0 | { |
1002 | 0 | a_bl[k] = json_long (dat, tokens); |
1003 | 0 | LOG_TRACE ("%s[%d]: " FORMAT_BL " [%s]\n", key, k, a_bl[k], type); |
1004 | 0 | } |
1005 | 0 | } |
1006 | | // dwg_dynapi_field_set_value (dwg, _obj, f, &nums, 1); |
1007 | 0 | return (void *)arr; |
1008 | 0 | } |
1009 | | |
1010 | | static int |
1011 | | json_created_by (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
1012 | | jsmntokens_t *restrict tokens) |
1013 | 0 | { |
1014 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
1015 | 0 | (void)dwg; |
1016 | 0 | if (t->type != JSMN_STRING) |
1017 | 0 | { |
1018 | 0 | LOG_ERROR ("Expected %s STRING", "created_by"); |
1019 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
1020 | 0 | return DWG_ERR_INVALIDTYPE; |
1021 | 0 | } |
1022 | 0 | created_by = json_string (dat, tokens); |
1023 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR; |
1024 | 0 | LOG_TRACE ("created_by %s\n", created_by); |
1025 | 0 | tokens->index--; // advanced by the loop |
1026 | 0 | return 0; |
1027 | 0 | } |
1028 | | |
1029 | | static int |
1030 | | json_FILEHEADER (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
1031 | | jsmntokens_t *restrict tokens) |
1032 | 0 | { |
1033 | 0 | const char *section = "FILEHEADER"; |
1034 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
1035 | 0 | Dwg_Header *_obj = &dwg->header; |
1036 | 0 | Dwg_Object *obj = NULL; |
1037 | 0 | char version[80] = {0}; |
1038 | 0 | int size = t->size; |
1039 | |
|
1040 | 0 | if (t->type != JSMN_OBJECT) |
1041 | 0 | { |
1042 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
1043 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
1044 | 0 | section); |
1045 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
1046 | 0 | return DWG_ERR_INVALIDTYPE; |
1047 | 0 | } |
1048 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
1049 | 0 | tokens->index, t->size); |
1050 | 0 | tokens->index++; |
1051 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1052 | | // t = &tokens->tokens[tokens->index]; |
1053 | | // json_expect(tokens, STRING); |
1054 | | // FIELD_TV (version, 0); |
1055 | 0 | for (int i = 0; i < size; i++) |
1056 | 0 | { |
1057 | 0 | char key[80]; |
1058 | 0 | json_fixed_key (key, dat, tokens); |
1059 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1060 | 0 | t = &tokens->tokens[tokens->index]; |
1061 | 0 | if (strEQc (key, "version")) |
1062 | 0 | { |
1063 | 0 | version[0] = '\0'; |
1064 | 0 | json_fixed_key (version, dat, tokens); |
1065 | 0 | dat->from_version = dwg->header.from_version |
1066 | 0 | = dwg_version_hdr_type (version); |
1067 | | // is_tu = dat->from_version >= R_2007; |
1068 | 0 | LOG_TRACE ("FILEHEADER.from_version = %s (%s)\n", version, |
1069 | 0 | dwg_version_type (dat->from_version)); |
1070 | 0 | if (dat->from_version == R_INVALID) |
1071 | 0 | { |
1072 | 0 | LOG_ERROR ("Invalid FILEHEADER.version %s", version); |
1073 | 0 | return DWG_ERR_INVALIDDWG; |
1074 | 0 | } |
1075 | 0 | } |
1076 | | // clang-format off |
1077 | 0 | FIELD_RC (is_maint, 0) |
1078 | 0 | FIELD_RC (zero_one_or_three, 0) |
1079 | | // preR13 only |
1080 | 0 | FIELD_RS (numentity_sections, 0) |
1081 | 0 | FIELD_RL (sections, 0) |
1082 | 0 | FIELD_RS (numheader_vars, 0) |
1083 | 0 | FIELD_RLx (entities_start, 0) |
1084 | 0 | FIELD_RLx (entities_end, 0) |
1085 | 0 | FIELD_RLx (blocks_start, 0) |
1086 | 0 | FIELD_RLx (blocks_size, 0) |
1087 | 0 | FIELD_RLx (extras_start, 0) |
1088 | 0 | FIELD_RLx (extras_size, 0) |
1089 | | |
1090 | 0 | FIELD_RL (thumbnail_address, 0) //@0x0d |
1091 | 0 | FIELD_RC (dwg_version, 0) |
1092 | 0 | FIELD_RC (maint_version, 0) |
1093 | 0 | FIELD_RS (codepage, 0) //@0x13: 29/30 for ANSI_1252, since r2007 UTF-16 |
1094 | 0 | FIELD_RL (sections, 0) // until r2000 |
1095 | 0 | // SINCE (R_2004a) |
1096 | 0 | FIELD_RC (unknown_0, 0) |
1097 | 0 | FIELD_RC (app_dwg_version, 0) |
1098 | 0 | FIELD_RC (app_maint_version, 0) |
1099 | 0 | FIELD_RL (security_type, 0) |
1100 | 0 | FIELD_RL (rl_1c_address, 0) /* mostly 0 */ |
1101 | 0 | FIELD_RL (summaryinfo_address, 0) |
1102 | 0 | FIELD_RL (vbaproj_address, 0) |
1103 | 0 | FIELD_RL (r2004_header_address, 0) /* mostly 128/0x80 */ |
1104 | 0 | |
1105 | 0 | // clang-format on |
1106 | 0 | else if (strEQc (key, "HEADER")) |
1107 | 0 | { |
1108 | 0 | LOG_WARN ("Unexpected next section %s", key) |
1109 | 0 | tokens->index--; |
1110 | 0 | tokens->index--; |
1111 | 0 | return 0; |
1112 | 0 | } |
1113 | 0 | else |
1114 | 0 | { |
1115 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
1116 | 0 | tokens->index++; |
1117 | 0 | } |
1118 | 0 | } |
1119 | 0 | LOG_TRACE ("End of %s\n", section) |
1120 | | // revised beta version |
1121 | 0 | { |
1122 | 0 | Dwg_Version_Type v = *version ? |
1123 | 0 | dwg_version_hdr_type2 (version, _obj->dwg_version) : R_INVALID; |
1124 | 0 | if (v != R_INVALID && v != dwg->header.from_version) |
1125 | 0 | { |
1126 | 0 | dat->from_version = dwg->header.from_version = v; |
1127 | 0 | LOG_TRACE ("FILEHEADER.from_version = %s (%s) via dwg_version\n", |
1128 | 0 | version, dwg_version_type (v)); |
1129 | 0 | } |
1130 | 0 | } |
1131 | 0 | tokens->index--; |
1132 | 0 | return 0; |
1133 | 0 | } |
1134 | | |
1135 | | static int |
1136 | | json_HEADER (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
1137 | | jsmntokens_t *restrict tokens) |
1138 | 1 | { |
1139 | 1 | const char *section = "HEADER"; |
1140 | 1 | const char *name = section; |
1141 | 1 | jsmntok_t *t = &tokens->tokens[tokens->index]; |
1142 | | // Dwg_Header_Variables *_obj = &dwg->header_vars; |
1143 | 1 | Dwg_Object *obj = NULL; |
1144 | 1 | int size = t->size; |
1145 | | |
1146 | 1 | if (t->type != JSMN_OBJECT) |
1147 | 1 | { |
1148 | 1 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
1149 | 1 | t_typename[t->type], tokens->index, tokens->num_tokens, |
1150 | 1 | section); |
1151 | 1 | json_advance_unknown (dat, tokens, t->type, 0); |
1152 | 1 | return DWG_ERR_INVALIDTYPE; |
1153 | 1 | } |
1154 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
1155 | 0 | tokens->index, t->size); |
1156 | 0 | tokens->index++; |
1157 | 0 | for (int i = 0; i < size; i++) |
1158 | 0 | { |
1159 | 0 | char key[80]; |
1160 | 0 | Dwg_DYNAPI_field *f; |
1161 | |
|
1162 | 0 | json_fixed_key (key, dat, tokens); |
1163 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1164 | 0 | t = &tokens->tokens[tokens->index]; |
1165 | 0 | f = (Dwg_DYNAPI_field *)dwg_dynapi_header_field (key); |
1166 | 0 | if (!f) |
1167 | 0 | { |
1168 | 0 | if (t->type == JSMN_ARRAY && strEQc (key, "layer_colors")) |
1169 | 0 | { |
1170 | 0 | tokens->index++; |
1171 | 0 | for (int index = 0; index < MAX (t->size, 128); index++) |
1172 | 0 | { |
1173 | 0 | dwg->header_vars.layer_colors[index] |
1174 | 0 | = (BITCODE_RS)json_long (dat, tokens); |
1175 | 0 | LOG_TRACE ("%s: " FORMAT_RS " [RS]\n", key, |
1176 | 0 | dwg->header_vars.layer_colors[index]); |
1177 | 0 | } |
1178 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR; |
1179 | 0 | } |
1180 | 0 | else |
1181 | 0 | { |
1182 | 0 | LOG_WARN ("Unknown key HEADER.%s", key) |
1183 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
1184 | 0 | continue; |
1185 | 0 | } |
1186 | 0 | } |
1187 | 0 | else if (t->type == JSMN_PRIMITIVE |
1188 | 0 | && (strEQc (f->type, "BD") || strEQc (f->type, "RD"))) |
1189 | 0 | { |
1190 | 0 | double num = json_float (dat, tokens); |
1191 | 0 | LOG_TRACE ("%s: " FORMAT_RD " [%s]\n", key, num, f->type) |
1192 | 0 | dwg_dynapi_header_set_value (dwg, key, &num, 0); |
1193 | 0 | } |
1194 | 0 | else if (t->type == JSMN_PRIMITIVE && f->size <= 4 // not a RS[] |
1195 | 0 | && (strEQc (f->type, "RC") || strEQc (f->type, "B") |
1196 | 0 | || strEQc (f->type, "BB") || strEQc (f->type, "RS") |
1197 | 0 | || strEQc (f->type, "BS") || strEQc (f->type, "RL") |
1198 | 0 | || strEQc (f->type, "BL") || strEQc (f->type, "RSd") |
1199 | 0 | || strEQc (f->type, "BLd") || strEQc (f->type, "BSd"))) |
1200 | 0 | { |
1201 | 0 | uint32_t num = json_long (dat, tokens); |
1202 | 0 | LOG_TRACE ("%s: " FORMAT_BL " [%s]\n", key, num, f->type) |
1203 | 0 | dwg_dynapi_header_set_value (dwg, key, &num, 0); |
1204 | 0 | } |
1205 | 0 | else if (t->type == JSMN_PRIMITIVE && f->size == 8 // not a RLL[] |
1206 | 0 | && (strEQc (f->type, "RLL") || strEQc (f->type, "BLL"))) |
1207 | 0 | { |
1208 | 0 | uint64_t num = json_longlong (dat, tokens); |
1209 | 0 | LOG_TRACE ("%s: " FORMAT_RLL " [%s]\n", key, num, f->type) |
1210 | 0 | dwg_dynapi_header_set_value (dwg, key, &num, 0); |
1211 | 0 | } |
1212 | 0 | else if (t->type == JSMN_STRING |
1213 | 0 | && (strEQc (f->type, "TV") || strEQc (f->type, "T"))) |
1214 | 0 | { |
1215 | 0 | size_t len; |
1216 | 0 | char *str = json_string (dat, tokens); |
1217 | 0 | LOG_TRACE ("%s: \"%s\" [%s]\n", key, str, f->type); |
1218 | 0 | if (dwg->header.version < R_13b1 && strEQc (key, "MENU") |
1219 | 0 | && (len = strlen (str) > 15)) |
1220 | 0 | { // split into MENU + MENUEXT |
1221 | 0 | strncpy ((char *)dwg->header_vars.MENUEXT, &str[15], 45); |
1222 | 0 | str[15] = '\0'; |
1223 | 0 | dwg->header_vars.MENU = strdup (str); |
1224 | 0 | dwg->header_vars.MENUEXT[45] = '\0'; |
1225 | 0 | } |
1226 | 0 | else |
1227 | 0 | dwg_dynapi_header_set_value (dwg, key, &str, 1); |
1228 | 0 | free (str); |
1229 | 0 | } |
1230 | 0 | else if (t->type == JSMN_ARRAY |
1231 | 0 | && (strEQc (f->type, "3BD") || strEQc (f->type, "3RD") |
1232 | 0 | || strEQc (f->type, "3DPOINT") || strEQc (f->type, "BE") |
1233 | 0 | || strEQc (f->type, "3BD_1"))) |
1234 | 0 | { |
1235 | 0 | BITCODE_3DPOINT pt; |
1236 | 0 | json_3DPOINT (dat, tokens, name, key, f->type, &pt); |
1237 | 0 | dwg_dynapi_header_set_value (dwg, key, &pt, 1); |
1238 | 0 | } |
1239 | 0 | else if (t->type == JSMN_ARRAY |
1240 | 0 | && (strEQc (f->type, "2BD") || strEQc (f->type, "2RD") |
1241 | 0 | || strEQc (f->type, "2DPOINT") |
1242 | 0 | || strEQc (f->type, "2BD_1"))) |
1243 | 0 | { |
1244 | 0 | BITCODE_2DPOINT pt; |
1245 | 0 | json_2DPOINT (dat, tokens, name, key, f->type, &pt); |
1246 | 0 | dwg_dynapi_header_set_value (dwg, key, &pt, 1); |
1247 | 0 | } |
1248 | 0 | else if (t->type == JSMN_ARRAY |
1249 | 0 | && (strEQc (f->type, "BS") || strEQc (f->type, "RS"))) |
1250 | 0 | { |
1251 | 0 | int size1 = t->size; |
1252 | 0 | BITCODE_BS *nums = (BITCODE_BS *)calloc (f->size, 1); |
1253 | 0 | tokens->index++; |
1254 | | // fail if not malloced or inlined array (but json has an array) |
1255 | 0 | if (f->size <= 2 && size1 > 1) |
1256 | 0 | { |
1257 | 0 | LOG_ERROR ( |
1258 | 0 | "Invalid JSON: HEADER.%s array where primitive expected", |
1259 | 0 | f->name); |
1260 | 0 | free (nums); |
1261 | 0 | tokens->index += size1; |
1262 | 0 | return 0; |
1263 | 0 | } |
1264 | 0 | for (int k = 0; k < size1; k++) |
1265 | 0 | { |
1266 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1267 | 0 | if (k < (f->size / 2)) |
1268 | 0 | { |
1269 | 0 | nums[k] = (BITCODE_BS)json_long (dat, tokens); |
1270 | 0 | LOG_TRACE ("%s.%s[%d]: " FORMAT_BS " [%s]\n", name, key, k, |
1271 | 0 | nums[k], f->type); |
1272 | 0 | } |
1273 | 0 | else |
1274 | 0 | { |
1275 | 0 | LOG_WARN ("Ignored %s.%s[%d]: " FORMAT_BL " [%s]", name, key, |
1276 | 0 | k, json_long (dat, tokens), f->type); |
1277 | 0 | } |
1278 | 0 | } |
1279 | 0 | if (!size1) |
1280 | 0 | LOG_TRACE ("%s.%s: [%s] empty\n", name, key, f->type); |
1281 | 0 | if (!f->is_malloc) |
1282 | 0 | { |
1283 | 0 | dwg_dynapi_header_set_value (dwg, key, nums, 1); |
1284 | 0 | free (nums); |
1285 | 0 | } |
1286 | 0 | else |
1287 | 0 | dwg_dynapi_header_set_value (dwg, key, &nums, 1); |
1288 | 0 | } |
1289 | 0 | else if (strEQc (f->type, "TIMEBLL") || strEQc (f->type, "TIMERLL")) |
1290 | 0 | { |
1291 | 0 | BITCODE_TIMEBLL date = { 0 }; |
1292 | 0 | json_TIMEBLL (dat, tokens, key, &date); |
1293 | 0 | dwg_dynapi_header_set_value (dwg, key, &date, 0); |
1294 | 0 | } |
1295 | 0 | else if (strEQc (f->type, "CMC")) |
1296 | 0 | { |
1297 | 0 | BITCODE_CMC color = { 0 }; |
1298 | 0 | json_CMC (dat, dwg, tokens, name, key, &color); |
1299 | 0 | dwg_dynapi_header_set_value (dwg, key, &color, 0); |
1300 | 0 | } |
1301 | 0 | else if (t->type == JSMN_ARRAY && strEQc (f->type, "H")) |
1302 | 0 | { |
1303 | 0 | BITCODE_H hdl |
1304 | 0 | = json_HANDLE (dat, dwg, tokens, section, key, NULL, -1); |
1305 | 0 | if (hdl) |
1306 | 0 | dwg_dynapi_header_set_value (dwg, key, &hdl, 0); |
1307 | 0 | } |
1308 | | //... |
1309 | 0 | else if (t->type == JSMN_OBJECT && strEQc (key, "CLASSES")) |
1310 | 0 | { |
1311 | 0 | LOG_WARN ("Unexpected next section %s", key) |
1312 | 0 | tokens->index--; |
1313 | 0 | tokens->index--; |
1314 | 0 | return 0; |
1315 | 0 | } |
1316 | 0 | else |
1317 | 0 | { |
1318 | 0 | LOG_WARN ("Unhandled %s [%s] with %s", key, f->type, |
1319 | 0 | t_typename[t->type]) |
1320 | 0 | tokens->index++; |
1321 | 0 | continue; |
1322 | 0 | } |
1323 | 0 | } |
1324 | 0 | LOG_TRACE ("End of %s\n", section) |
1325 | | // the key |
1326 | 0 | tokens->index--; |
1327 | 0 | return 0; |
1328 | 0 | } |
1329 | | |
1330 | | static int |
1331 | | json_CLASSES (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
1332 | | jsmntokens_t *restrict tokens) |
1333 | 1 | { |
1334 | 1 | const char *section = "CLASSES"; |
1335 | 1 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
1336 | 1 | int size; |
1337 | 1 | if (t->type != JSMN_ARRAY || dwg->num_classes) |
1338 | 0 | { |
1339 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s ARRAY", |
1340 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
1341 | 0 | section); |
1342 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
1343 | 0 | return DWG_ERR_INVALIDTYPE; |
1344 | 0 | } |
1345 | 1 | size = t->size; |
1346 | 1 | LOG_TRACE ("\n%s pos:%d [%d members]\n--------------------\n", section, |
1347 | 1 | tokens->index, size); |
1348 | 1 | tokens->index++; |
1349 | 1 | if (dwg->num_classes == 0) |
1350 | 1 | dwg->dwg_class = (Dwg_Class *)calloc (size, sizeof (Dwg_Class)); |
1351 | 0 | else |
1352 | 0 | dwg->dwg_class = (Dwg_Class *)realloc ( |
1353 | 0 | dwg->dwg_class, (dwg->num_classes + size) * sizeof (Dwg_Class)); |
1354 | 1 | if (!dwg->dwg_class) |
1355 | 0 | { |
1356 | 0 | LOG_ERROR ("Out of memory"); |
1357 | 0 | return DWG_ERR_OUTOFMEM; |
1358 | 0 | } |
1359 | 1 | dwg->num_classes += size; |
1360 | 2 | for (int i = 0; i < size; i++) |
1361 | 2 | { |
1362 | 2 | int keys; |
1363 | 2 | Dwg_Class *klass = &dwg->dwg_class[i]; |
1364 | 2 | memset (klass, 0, sizeof (Dwg_Class)); |
1365 | 2 | if (i > 0) |
1366 | 1 | { |
1367 | 1 | Dwg_Class *oldkl = &dwg->dwg_class[i - 1]; |
1368 | 1 | if (!oldkl->number || !oldkl->dxfname || !oldkl->appname |
1369 | 0 | || !oldkl->cppname || !oldkl->item_class_id) |
1370 | 1 | { |
1371 | 1 | klass = oldkl; |
1372 | 1 | i--; |
1373 | 1 | size--; |
1374 | 1 | dwg->num_classes--; |
1375 | 1 | LOG_ERROR ( |
1376 | 1 | "Illegal CLASS [%d]. Mandatory field missing, skipped", i) |
1377 | 1 | } |
1378 | 1 | } |
1379 | | |
1380 | 2 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1381 | 2 | t = &tokens->tokens[tokens->index]; |
1382 | 2 | if (t->type != JSMN_OBJECT) |
1383 | 1 | { |
1384 | 1 | LOG_ERROR ( |
1385 | 1 | "Unexpected %s at %u of %ld tokens, expected %s OBJECT. %s:%d", |
1386 | 1 | t_typename[t->type], tokens->index, tokens->num_tokens, section, |
1387 | 1 | __FUNCTION__, __LINE__); |
1388 | 1 | json_advance_unknown (dat, tokens, t->type, 0); |
1389 | 1 | return DWG_ERR_INVALIDTYPE; |
1390 | 1 | } |
1391 | 1 | keys = t->size; |
1392 | 1 | tokens->index++; |
1393 | 1 | LOG_HANDLE ("\n-keys: %d\n", keys); |
1394 | 24 | for (int j = 0; j < keys; j++) |
1395 | 23 | { |
1396 | 23 | char key[80]; |
1397 | 23 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1398 | 23 | json_fixed_key (key, dat, tokens); |
1399 | 23 | t = &tokens->tokens[tokens->index]; |
1400 | 23 | if (strEQc (key, "number")) |
1401 | 0 | { |
1402 | 0 | klass->number = (BITCODE_BS)json_long (dat, tokens) & 0xFFFF; |
1403 | 0 | LOG_TRACE ("\nCLASS[%d].number: " FORMAT_BS "\n", i, |
1404 | 0 | klass->number) |
1405 | 0 | if (klass->number != i + 500) |
1406 | 0 | LOG_WARN ("Possibly illegal class number %d, expected %d", |
1407 | 0 | klass->number, i + 500) |
1408 | 0 | } |
1409 | 23 | else if (strEQc (key, "dxfname")) |
1410 | 0 | { |
1411 | 0 | klass->dxfname = json_string (dat, tokens); |
1412 | 0 | if (dwg->header.version >= R_2007) |
1413 | 0 | klass->dxfname_u = bit_utf8_to_TU (klass->dxfname, 0); |
1414 | 0 | LOG_TRACE ("dxfname: \"%s\"\n", klass->dxfname); |
1415 | 0 | } |
1416 | 23 | else if (strEQc (key, "cppname")) |
1417 | 0 | { |
1418 | 0 | LOG_TRACE ("cppname: \"%.*s\"\n", t->end - t->start, |
1419 | 0 | &dat->chain[t->start]) |
1420 | | /*if (dwg->header.version >= R_2007) |
1421 | | klass->cppname = (char*)json_wstring (dat, tokens); |
1422 | | else*/ |
1423 | 0 | klass->cppname = json_string (dat, tokens); |
1424 | 0 | } |
1425 | 23 | else if (strEQc (key, "appname")) |
1426 | 0 | { |
1427 | 0 | LOG_TRACE ("appname \"%.*s\"\n", t->end - t->start, |
1428 | 0 | &dat->chain[t->start]) |
1429 | | /*if (dwg->header.version >= R_2007) |
1430 | | klass->appname = (char*)json_wstring (dat, tokens); |
1431 | | else*/ |
1432 | 0 | klass->appname = json_string (dat, tokens); |
1433 | 0 | } |
1434 | 23 | else if (strEQc (key, "proxyflag")) |
1435 | 0 | { |
1436 | 0 | klass->proxyflag = json_long (dat, tokens); |
1437 | 0 | LOG_TRACE ("proxyflag %u\n", klass->proxyflag) |
1438 | 0 | } |
1439 | 23 | else if (strEQc (key, "num_instances")) |
1440 | 0 | { |
1441 | 0 | klass->num_instances = json_long (dat, tokens); |
1442 | 0 | LOG_TRACE ("num_instances %u\n", klass->num_instances) |
1443 | 0 | } |
1444 | 23 | else if (strEQc (key, "is_zombie")) |
1445 | 0 | { |
1446 | 0 | klass->is_zombie = json_long (dat, tokens); |
1447 | 0 | LOG_TRACE ("is_zombie %d\n", klass->is_zombie) |
1448 | 0 | } |
1449 | 23 | else if (strEQc (key, "item_class_id")) |
1450 | 0 | { |
1451 | 0 | klass->item_class_id = json_long (dat, tokens); |
1452 | 0 | LOG_TRACE ("item_class_id %u\n", klass->item_class_id) |
1453 | 0 | } |
1454 | 23 | else |
1455 | 23 | { |
1456 | 23 | LOG_WARN ("Unknown CLASS key %s %.*s", key, t->end - t->start, |
1457 | 23 | &dat->chain[t->start]) |
1458 | 23 | json_advance_unknown (dat, tokens, t->type, 0); |
1459 | 23 | } |
1460 | 23 | } |
1461 | 1 | } |
1462 | | // also check the last one |
1463 | 0 | if (dwg->num_classes > 0) |
1464 | 0 | { |
1465 | 0 | Dwg_Class *oldkl = &dwg->dwg_class[dwg->num_classes - 1]; |
1466 | 0 | if (!oldkl->number || !oldkl->dxfname || !oldkl->appname |
1467 | 0 | || !oldkl->cppname || !oldkl->item_class_id) |
1468 | 0 | { |
1469 | 0 | dwg->num_classes--; |
1470 | 0 | LOG_ERROR ("Illegal CLASS [%d]. Mandatory field missing, skipped", |
1471 | 0 | dwg->num_classes) |
1472 | 0 | } |
1473 | 0 | } |
1474 | 0 | LOG_TRACE ("End of %s\n", section) |
1475 | 0 | tokens->index--; |
1476 | 0 | return 0; |
1477 | 1 | } |
1478 | | |
1479 | | static bool |
1480 | | eed_need_size (Bit_Chain *restrict dat, Dwg_Eed *restrict eed, |
1481 | | const unsigned int i, const int need, int *havep) |
1482 | 0 | { |
1483 | 0 | if (need > *havep) |
1484 | 0 | { |
1485 | 0 | BITCODE_BS size; |
1486 | 0 | unsigned int isize; |
1487 | 0 | int diff = need - *havep; |
1488 | | // find isize |
1489 | 0 | for (isize = i; !eed[isize].size && isize > 0; isize--) |
1490 | 0 | ; |
1491 | 0 | size = eed[isize].size; |
1492 | 0 | LOG_TRACE (" extend eed[%u].size %u +%d (have: %d, need: %d)\n", isize, |
1493 | 0 | size, diff, *havep, need) |
1494 | 0 | eed[i].data = (Dwg_Eed_Data *)realloc (eed[i].data, size + diff); |
1495 | 0 | eed[isize].size += diff; |
1496 | 0 | *havep = size + diff - need; |
1497 | 0 | return true; |
1498 | 0 | } |
1499 | 0 | *havep -= need; |
1500 | 0 | return false; |
1501 | 0 | } |
1502 | | |
1503 | | static void |
1504 | | json_eed (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
1505 | | jsmntokens_t *restrict tokens, Dwg_Object_Object *restrict obj) |
1506 | 0 | { |
1507 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
1508 | 0 | const char *name = ""; |
1509 | 0 | int isize = -1; |
1510 | 0 | uint32_t size = 0; |
1511 | 0 | obj->eed = (Dwg_Eed *)calloc (t->size, sizeof (Dwg_Eed)); |
1512 | 0 | obj->num_eed = t->size; |
1513 | 0 | LOG_TRACE ("num_eed: " FORMAT_BL " [BL]\n", obj->num_eed); |
1514 | 0 | tokens->index++; // array of objects |
1515 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
1516 | 0 | for (unsigned i = 0; i < obj->num_eed; i++) |
1517 | 0 | { |
1518 | 0 | char key[80]; |
1519 | 0 | int have = 0; |
1520 | 0 | t = &tokens->tokens[tokens->index]; |
1521 | 0 | if (t->type == JSMN_OBJECT) |
1522 | 0 | { |
1523 | 0 | const int osize = t->size; |
1524 | 0 | tokens->index++; // hash of size, handle, code, value |
1525 | 0 | for (int j = 0; j < osize; j++) |
1526 | 0 | { |
1527 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
1528 | 0 | json_fixed_key (key, dat, tokens); |
1529 | 0 | t = &tokens->tokens[tokens->index]; |
1530 | 0 | if (strEQc (key, "size")) |
1531 | 0 | { |
1532 | 0 | size = json_long (dat, tokens); |
1533 | 0 | isize = (int)i; |
1534 | | // see below: if does_cross_unicode_datversion (dat) we need |
1535 | | // to recalc |
1536 | 0 | obj->eed[i].size = (BITCODE_BS)size & 0xFFFF; |
1537 | 0 | LOG_TRACE ("eed[%u].size " FORMAT_BS "\n", i, |
1538 | 0 | obj->eed[i].size); |
1539 | 0 | have = size + 1; // we overallocate by 1 for the ending NUL |
1540 | 0 | obj->eed[i].data = (Dwg_Eed_Data *)calloc (have, 1); |
1541 | 0 | LOG_INSANE (" alloc eed[%u].data: %d\n", i, have) |
1542 | 0 | } |
1543 | 0 | else if (strEQc (key, "handle")) |
1544 | 0 | { |
1545 | 0 | BITCODE_H hdl = json_HANDLE (dat, dwg, tokens, name, |
1546 | 0 | "eed[i].handles", NULL, -1); |
1547 | 0 | memcpy (&obj->eed[i].handle, &hdl->handleref, |
1548 | 0 | sizeof (Dwg_Handle)); |
1549 | 0 | if (isize != (int)i || isize > (int)obj->num_eed) |
1550 | 0 | { |
1551 | 0 | LOG_ERROR ( |
1552 | 0 | "Missing eed[%u].size field %d or overflow at %s", i, |
1553 | 0 | isize, key) |
1554 | 0 | break; |
1555 | 0 | } |
1556 | 0 | } |
1557 | 0 | else if (strEQc (key, "code")) |
1558 | 0 | { |
1559 | 0 | uint32_t code = json_long (dat, tokens); |
1560 | 0 | if (isize != (int)i) |
1561 | 0 | { |
1562 | 0 | if (have > 0) |
1563 | 0 | { |
1564 | 0 | obj->eed[i - 1].data = (Dwg_Eed_Data *)realloc ( |
1565 | 0 | obj->eed[i - 1].data, size - have); |
1566 | 0 | LOG_INSANE (" realloc eed[%u].data: %d\n", i - 1, |
1567 | 0 | (int)(size - have)) |
1568 | 0 | } |
1569 | 0 | have = size - have - 1; |
1570 | 0 | obj->eed[i].data = (Dwg_Eed_Data *)calloc (have, 1); |
1571 | 0 | LOG_INSANE (" alloc eed[%u].data: %d\n", i, have) |
1572 | 0 | } |
1573 | 0 | have--; |
1574 | 0 | obj->eed[i].data->code = (BITCODE_RC)code; |
1575 | 0 | LOG_TRACE ("eed[%u].data.code " FORMAT_RC "\n", i, code); |
1576 | 0 | } |
1577 | 0 | else if (strEQc (key, "value")) |
1578 | 0 | { |
1579 | 0 | Dwg_Eed_Data *data = obj->eed[i].data; |
1580 | 0 | if (!data) |
1581 | 0 | { |
1582 | 0 | LOG_ERROR ("Missing eed[%u].code field", i) |
1583 | 0 | break; |
1584 | 0 | } |
1585 | 0 | switch (data->code) |
1586 | 0 | { |
1587 | 0 | case 0: |
1588 | 0 | { |
1589 | | /*PRE (R_2007a)*/ |
1590 | 0 | { |
1591 | 0 | char *s = json_string (dat, tokens); |
1592 | 0 | BITCODE_RS len = strlen (s) & 0xFFFF; |
1593 | 0 | if (eed_need_size (dat, obj->eed, i, len + 1 + 5, |
1594 | 0 | &have)) |
1595 | 0 | data = obj->eed[i].data; |
1596 | 0 | data->u.eed_0.is_tu = 0; |
1597 | 0 | data->u.eed_0.length = len & 0xFFFF; |
1598 | 0 | data->u.eed_0.codepage = dwg->header.codepage; |
1599 | 0 | if (len) |
1600 | 0 | memcpy (&data->u.eed_0.string, s, |
1601 | 0 | (len + 1) & 0xFFFF); |
1602 | 0 | LOG_TRACE ("eed[%u].data.value \"%s\"\n", i, s); |
1603 | 0 | have++; // ignore the ending NUL |
1604 | 0 | free (s); |
1605 | | // with PRE (R_2007a), the size gets smaller |
1606 | 0 | if (does_cross_unicode_datversion (dat)) |
1607 | 0 | { |
1608 | 0 | int oldsize = (len * 2) + 5; |
1609 | 0 | size = len + 5; |
1610 | 0 | obj->eed[isize].size -= (oldsize - size); |
1611 | 0 | } |
1612 | 0 | } |
1613 | | /* |
1614 | | LATER_VERSIONS |
1615 | | { |
1616 | | BITCODE_TU s = json_wstring (dat, tokens); |
1617 | | int len = bit_wcs2len (s); |
1618 | | if (eed_need_size (dat, obj->eed, i, (len * 2) + 1 + |
1619 | | 2, &have)) data = obj->eed[i].data; |
1620 | | data->u.eed_0_r2007.length = len; |
1621 | | if (len) |
1622 | | memcpy (&data->u.eed_0_r2007.string, s, (len + 1) * |
1623 | | 2); have += 2; // ignore the ending NUL LOG_TRACE |
1624 | | ("eed[%u].data.value \"%.*s\"\n", i, t->end - t->start, |
1625 | | &dat->chain[t->start]); |
1626 | | free (s); |
1627 | | } |
1628 | | */ |
1629 | 0 | } |
1630 | 0 | break; |
1631 | 0 | case 1: |
1632 | 0 | if (eed_need_size (dat, obj->eed, i, 3, &have)) |
1633 | 0 | data = obj->eed[i].data; |
1634 | 0 | data->u.eed_1.appid_index |
1635 | 0 | = (BITCODE_RS)json_long (dat, tokens); |
1636 | 0 | LOG_TRACE ("eed[%u].data.appid_index %d\n", i, |
1637 | 0 | (int)data->u.eed_1.appid_index); |
1638 | 0 | break; |
1639 | 0 | case 2: |
1640 | 0 | if (eed_need_size (dat, obj->eed, i, 1, &have)) |
1641 | 0 | data = obj->eed[i].data; |
1642 | 0 | data->u.eed_2.close |
1643 | 0 | = (BITCODE_RC)json_long (dat, tokens); |
1644 | 0 | LOG_TRACE ("eed[%u].data.close %d\n", i, |
1645 | 0 | data->u.eed_2.close); |
1646 | 0 | break; |
1647 | 0 | case 3: |
1648 | 0 | eed_need_size (dat, obj->eed, i, 4, &have); |
1649 | 0 | data->u.eed_3.layer = json_long (dat, tokens); |
1650 | 0 | LOG_TRACE ("eed[%u].data.layer " FORMAT_RLL "\n", i, |
1651 | 0 | data->u.eed_3.layer); |
1652 | 0 | break; |
1653 | 0 | case 4: |
1654 | 0 | { |
1655 | 0 | size_t len; |
1656 | 0 | unsigned char *s |
1657 | 0 | = json_binary (dat, tokens, "eed", &len); |
1658 | | // FIXME wrong obj with ubsan |
1659 | 0 | if (eed_need_size (dat, obj->eed, i, |
1660 | 0 | (len + 2) & INT_MAX, &have)) |
1661 | 0 | data = obj->eed[i].data; |
1662 | 0 | memcpy (&data->u.eed_4.data, s, len & 0xFF); |
1663 | 0 | data->u.eed_4.length = len & 0xFF; |
1664 | 0 | free (s); |
1665 | 0 | break; |
1666 | 0 | } |
1667 | 0 | case 5: |
1668 | 0 | { |
1669 | 0 | BITCODE_H hdl |
1670 | 0 | = json_HANDLE (dat, dwg, tokens, name, |
1671 | 0 | "eed[i].u.eed_5.entity", NULL, -1); |
1672 | 0 | JSON_TOKENS_CHECK_OVERFLOW_VOID |
1673 | 0 | memcpy (&data->u.eed_5.entity, &hdl->handleref.value, |
1674 | 0 | sizeof (hdl->handleref.value)); |
1675 | 0 | break; |
1676 | 0 | } |
1677 | 0 | case 10: |
1678 | 0 | case 11: |
1679 | 0 | case 12: |
1680 | 0 | case 13: |
1681 | 0 | case 14: |
1682 | 0 | case 15: |
1683 | 0 | { |
1684 | 0 | BITCODE_3BD pt; |
1685 | 0 | json_3DPOINT (dat, tokens, name, "eed", "3RD", &pt); |
1686 | 0 | if (eed_need_size (dat, obj->eed, i, 24, &have)) |
1687 | 0 | data = obj->eed[i].data; |
1688 | 0 | memcpy (&data->u.eed_10.point, &pt, 24); |
1689 | 0 | } |
1690 | 0 | break; |
1691 | 0 | case 40: |
1692 | 0 | case 41: |
1693 | 0 | case 42: |
1694 | 0 | if (eed_need_size (dat, obj->eed, i, 8, &have)) |
1695 | 0 | data = obj->eed[i].data; |
1696 | 0 | data->u.eed_40.real = json_float (dat, tokens); |
1697 | 0 | LOG_TRACE ("eed[%u].data.value %f\n", i, |
1698 | 0 | data->u.eed_40.real); |
1699 | 0 | break; |
1700 | 0 | case 70: |
1701 | 0 | if (eed_need_size (dat, obj->eed, i, 2, &have)) |
1702 | 0 | data = obj->eed[i].data; |
1703 | 0 | data->u.eed_70.rs = (BITCODE_RS)json_long (dat, tokens); |
1704 | 0 | LOG_TRACE ("eed[%u].data.value %d\n", i, |
1705 | 0 | (int)data->u.eed_70.rs); |
1706 | 0 | break; |
1707 | 0 | case 71: |
1708 | 0 | if (eed_need_size (dat, obj->eed, i, 4, &have)) |
1709 | 0 | data = obj->eed[i].data; |
1710 | 0 | data->u.eed_71.rl = json_long (dat, tokens); |
1711 | 0 | LOG_TRACE ("eed[%u].data.value %d\n", i, |
1712 | 0 | (int)data->u.eed_71.rl); |
1713 | 0 | break; |
1714 | 0 | default: |
1715 | 0 | break; |
1716 | 0 | } |
1717 | 0 | } |
1718 | 0 | } |
1719 | 0 | } |
1720 | 0 | } |
1721 | 0 | return; |
1722 | 0 | } |
1723 | | |
1724 | | static int |
1725 | | json_xdata (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
1726 | | jsmntokens_t *restrict tokens, Dwg_Object_XRECORD *restrict obj) |
1727 | 0 | { |
1728 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
1729 | 0 | Dwg_Resbuf *rbuf; |
1730 | 0 | BITCODE_BL size = 0; |
1731 | 0 | const char *name = "XRECORD"; |
1732 | 0 | obj->xdata = (Dwg_Resbuf *)calloc (1, sizeof (Dwg_Resbuf)); |
1733 | 0 | rbuf = obj->xdata; |
1734 | 0 | obj->num_xdata = t->size; |
1735 | 0 | LOG_INSANE ("num_xdata: " FORMAT_BL "\n", obj->num_xdata); |
1736 | 0 | tokens->index++; // array of objects |
1737 | 0 | for (unsigned i = 0; i < obj->num_xdata; i++) |
1738 | 0 | { |
1739 | 0 | char key[80]; |
1740 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1741 | 0 | t = &tokens->tokens[tokens->index]; |
1742 | 0 | if (t->type == JSMN_ARRAY && t->size == 2) // of [ type, value ] |
1743 | 0 | { |
1744 | 0 | Dwg_Resbuf *old = rbuf; |
1745 | 0 | enum RESBUF_VALUE_TYPE vtype; |
1746 | |
|
1747 | 0 | tokens->index++; |
1748 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1749 | 0 | rbuf->type = (BITCODE_RS)json_long (dat, tokens); |
1750 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1751 | 0 | LOG_INSANE ("xdata[%u]: type %d\n", i, rbuf->type); |
1752 | 0 | size += 2; |
1753 | 0 | vtype = dwg_resbuf_value_type (rbuf->type); |
1754 | 0 | switch (vtype) |
1755 | 0 | { |
1756 | 0 | case DWG_VT_STRING: |
1757 | 0 | { |
1758 | 0 | char *s = json_string (dat, tokens); |
1759 | 0 | size_t len = strlen (s); |
1760 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1761 | 0 | if (len > 0xFFFF) |
1762 | 0 | { |
1763 | 0 | LOG_ERROR ("xdata string overflow len=%" PRIuSIZE, len); |
1764 | 0 | return DWG_ERR_INVALIDDWG; |
1765 | 0 | } |
1766 | 0 | rbuf->value.str.size = len & 0xFFFF; |
1767 | | // here the xdata_size gets re-calculated from size |
1768 | 0 | PRE (R_2007a) // from version |
1769 | 0 | { |
1770 | 0 | rbuf->value.str.is_tu = 0; |
1771 | 0 | rbuf->value.str.u.data = s; |
1772 | 0 | rbuf->value.str.codepage = dwg->header.codepage; |
1773 | 0 | LOG_TRACE ("xdata[%u]: \"%s\" [TV %d]\n", i, s, |
1774 | 0 | (int)rbuf->type); |
1775 | 0 | size += (len & 0xFFFF) + 3; |
1776 | 0 | } |
1777 | 0 | LATER_VERSIONS |
1778 | 0 | { |
1779 | 0 | rbuf->value.str.is_tu = 1; |
1780 | 0 | rbuf->value.str.u.wdata = bit_utf8_to_TU (s, 0); |
1781 | 0 | free (s); |
1782 | 0 | LOG_TRACE_TU ("xdata", rbuf->value.str.u.wdata, rbuf->type); |
1783 | 0 | size += ((len * 2) & 0xFFFF) + 2; |
1784 | 0 | } |
1785 | 0 | } |
1786 | 0 | break; |
1787 | 0 | case DWG_VT_BOOL: |
1788 | 0 | case DWG_VT_INT8: |
1789 | 0 | { |
1790 | 0 | uint32_t l = json_long (dat, tokens); |
1791 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1792 | 0 | rbuf->value.i8 = (BITCODE_RC)l; |
1793 | 0 | LOG_TRACE ("xdata[%u]: " FORMAT_RC " [RC %d]\n", i, |
1794 | 0 | rbuf->value.i8, (int)rbuf->type); |
1795 | 0 | size += 1; |
1796 | 0 | } |
1797 | 0 | break; |
1798 | 0 | case DWG_VT_INT16: |
1799 | 0 | { |
1800 | 0 | uint32_t l = json_long (dat, tokens); |
1801 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1802 | 0 | rbuf->value.i16 = (BITCODE_RS)l; |
1803 | 0 | LOG_TRACE ("xdata[%u]: " FORMAT_BS " [RS %d]\n", i, |
1804 | 0 | rbuf->value.i16, (int)rbuf->type); |
1805 | 0 | size += 2; |
1806 | 0 | } |
1807 | 0 | break; |
1808 | 0 | case DWG_VT_INT32: |
1809 | 0 | { |
1810 | 0 | uint32_t l = json_long (dat, tokens); |
1811 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1812 | 0 | rbuf->value.i32 = (BITCODE_RL)l; |
1813 | 0 | LOG_TRACE ("xdata[%u]: " FORMAT_BL " [RL %d]\n", i, l, |
1814 | 0 | (int)rbuf->type); |
1815 | 0 | size += 4; |
1816 | 0 | } |
1817 | 0 | break; |
1818 | 0 | case DWG_VT_INT64: |
1819 | 0 | { |
1820 | 0 | uint64_t l = json_longlong (dat, tokens); |
1821 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1822 | 0 | rbuf->value.i64 = l; |
1823 | 0 | LOG_TRACE ("xdata[%u]: " FORMAT_RLL " [RLL %d]\n", i, l, |
1824 | 0 | (int)rbuf->type); |
1825 | 0 | size += 8; |
1826 | 0 | } |
1827 | 0 | break; |
1828 | 0 | case DWG_VT_REAL: |
1829 | 0 | rbuf->value.dbl = json_float (dat, tokens); |
1830 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1831 | 0 | LOG_TRACE ("xdata[%u]: %f [RD %d]\n", i, rbuf->value.dbl, |
1832 | 0 | (int)rbuf->type); |
1833 | 0 | size += 8; |
1834 | 0 | break; |
1835 | 0 | case DWG_VT_POINT3D: |
1836 | 0 | { |
1837 | 0 | BITCODE_3BD pt; |
1838 | 0 | json_3DPOINT (dat, tokens, name, "xdata", "3RD", &pt); |
1839 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1840 | 0 | memcpy (&rbuf->value.pt, &pt, 24); |
1841 | 0 | size += 24; |
1842 | 0 | } |
1843 | 0 | break; |
1844 | 0 | case DWG_VT_BINARY: |
1845 | 0 | { |
1846 | 0 | size_t len; |
1847 | 0 | unsigned char *s = json_binary (dat, tokens, "xdata", &len); |
1848 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1849 | 0 | rbuf->value.str.u.data = (char *)s; |
1850 | 0 | rbuf->value.str.size = len & 0xFFFF; |
1851 | 0 | size += (len + 1) & 0xFFFF; |
1852 | 0 | break; |
1853 | 0 | } |
1854 | 0 | case DWG_VT_HANDLE: |
1855 | 0 | case DWG_VT_OBJECTID: |
1856 | 0 | { |
1857 | 0 | uint32_t l = json_long (dat, tokens); |
1858 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1859 | 0 | rbuf->value.absref = (BITCODE_RLL)l; |
1860 | 0 | LOG_TRACE ("xdata[%u]: " FORMAT_HV " [H %d]\n", i, |
1861 | 0 | rbuf->value.absref, (int)rbuf->type); |
1862 | 0 | size += 8; |
1863 | 0 | } |
1864 | 0 | break; |
1865 | 0 | case DWG_VT_INVALID: |
1866 | 0 | default: |
1867 | 0 | break; |
1868 | 0 | } |
1869 | 0 | rbuf = (Dwg_Resbuf *)calloc (1, sizeof (Dwg_Resbuf)); |
1870 | 0 | old->nextrb = rbuf; |
1871 | 0 | } |
1872 | 0 | else |
1873 | 0 | { |
1874 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
1875 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1876 | 0 | } |
1877 | 0 | } |
1878 | 0 | if (obj->xdata_size != size) |
1879 | 0 | { |
1880 | 0 | if (!does_cross_unicode_datversion (dat)) |
1881 | 0 | LOG_WARN ("Changed XRECORD.xdata_size from %u to %u", obj->xdata_size, |
1882 | 0 | size) |
1883 | 0 | else |
1884 | 0 | LOG_TRACE ("Changed XRECORD.xdata_size from %u to %u\n", |
1885 | 0 | obj->xdata_size, size) |
1886 | 0 | } |
1887 | 0 | obj->xdata_size = size; |
1888 | 0 | return 0; |
1889 | 0 | } |
1890 | | |
1891 | | static int |
1892 | | json_acis_data (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
1893 | | jsmntokens_t *restrict tokens, const Dwg_Object *restrict obj) |
1894 | 0 | { |
1895 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
1896 | 0 | int len = 0; |
1897 | 0 | int alloc = t->end - t->start; |
1898 | 0 | int size = t->size; |
1899 | 0 | char *s = (char *)calloc (alloc, 1); |
1900 | 0 | Dwg_Entity__3DSOLID *_obj = obj->tio.entity->tio._3DSOLID; |
1901 | 0 | BITCODE_BS acis_version; |
1902 | |
|
1903 | 0 | dwg_dynapi_entity_value (_obj, obj->name, "version", &acis_version, NULL); |
1904 | 0 | LOG_INSANE ("acis lines: %d\n", t->size); |
1905 | 0 | tokens->index++; // array of strings with version 1 |
1906 | 0 | for (int i = 0; i < size; i++) |
1907 | 0 | { |
1908 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
1909 | 0 | t = &tokens->tokens[tokens->index]; |
1910 | 0 | if (t->type == JSMN_STRING) |
1911 | 0 | { |
1912 | 0 | int l = t->end - t->start; |
1913 | | // could be made faster, but those strings are short, and not that |
1914 | | // often. |
1915 | 0 | if (acis_version == 1) |
1916 | 0 | { |
1917 | 0 | len += l + 1; |
1918 | 0 | if (len > alloc) // cannot happen, as we take the length of the |
1919 | | // json source array |
1920 | 0 | { |
1921 | 0 | LOG_WARN ("Internal surprise, acis_data overshoot %d > %d", |
1922 | 0 | len, alloc); |
1923 | 0 | alloc += 60; |
1924 | 0 | s = (char *)realloc (s, alloc); |
1925 | 0 | } |
1926 | 0 | strncat (s, (char *)&dat->chain[t->start], l); |
1927 | 0 | strcat (s, "\n"); |
1928 | 0 | } |
1929 | 0 | else |
1930 | 0 | { |
1931 | 0 | len += l; |
1932 | 0 | if (len > alloc) |
1933 | 0 | { |
1934 | 0 | alloc = len; |
1935 | 0 | s = (char *)realloc (s, alloc); |
1936 | 0 | } |
1937 | 0 | if (i == 0) // first line is plain, second is binary |
1938 | 0 | strncat (s, (char *)&dat->chain[t->start], l); |
1939 | 0 | else |
1940 | 0 | { |
1941 | | // 15 is the length of the first line: "ACIS BinaryFile" |
1942 | 0 | const unsigned blen = l / 2; |
1943 | 0 | unsigned read; |
1944 | 0 | char *pos = (char *)&dat->chain[t->start]; |
1945 | 0 | if ((len - l) != 15 || size != 2) |
1946 | 0 | LOG_ERROR ( |
1947 | 0 | "Invalid %s ACIS %u json format. len %d, size %d", |
1948 | 0 | obj->name, acis_version, len - l, size); |
1949 | 0 | if (!pos) |
1950 | 0 | { |
1951 | 0 | LOG_ERROR ("Invalid %s ACIS %u json format. NULL string", |
1952 | 0 | obj->name, acis_version); |
1953 | 0 | free (s); |
1954 | 0 | return DWG_ERR_INVALIDTYPE; |
1955 | 0 | } |
1956 | 0 | if ((read = in_hex2bin ((unsigned char *)&s[15], pos, blen) |
1957 | 0 | != blen)) |
1958 | 0 | LOG_ERROR ("in_hex2bin with key %s at pos %u of %u", |
1959 | 0 | "acis_data", read, blen); |
1960 | 0 | len = 15 + blen; |
1961 | 0 | } |
1962 | 0 | } |
1963 | 0 | } |
1964 | 0 | tokens->index++; |
1965 | 0 | } |
1966 | 0 | LOG_TRACE ("%s.acis_data: %s\n", obj->name, s); |
1967 | 0 | if (acis_version > 1) |
1968 | 0 | { |
1969 | 0 | BITCODE_BL num_blocks = 1; |
1970 | 0 | BITCODE_BL sab_size = len; |
1971 | 0 | BITCODE_BL *block_size = (BITCODE_BL *)calloc (2, sizeof (BITCODE_BL)); |
1972 | 0 | block_size[0] = len; |
1973 | 0 | block_size[1] = 0; |
1974 | 0 | LOG_TRACE (" num_blocks: " FORMAT_BL " [BL]\n", num_blocks); |
1975 | 0 | LOG_TRACE (" sab_size: " FORMAT_BL " [BL]\n", sab_size); |
1976 | 0 | LOG_TRACE (" block_size[0]: %d [BL]\n", block_size[0]); |
1977 | 0 | dwg_dynapi_entity_set_value (_obj, obj->name, "num_blocks", &num_blocks, |
1978 | 0 | true); |
1979 | 0 | dwg_dynapi_entity_set_value (_obj, obj->name, "block_size", &block_size, |
1980 | 0 | true); |
1981 | 0 | dwg_dynapi_entity_set_value (_obj, obj->name, "sab_size", &sab_size, |
1982 | 0 | true); |
1983 | 0 | } |
1984 | | // just keep this s ptr, no utf8 |
1985 | 0 | return dwg_dynapi_entity_set_value (obj->tio.entity->tio._3DSOLID, obj->name, |
1986 | 0 | "acis_data", &s, false) |
1987 | 0 | ? 0 |
1988 | 0 | : DWG_ERR_INVALIDTYPE; |
1989 | 0 | } |
1990 | | |
1991 | | static const Dwg_DYNAPI_field * |
1992 | | find_sizefield (const Dwg_DYNAPI_field *restrict fields, |
1993 | | const char *restrict key) |
1994 | 0 | { |
1995 | 0 | const Dwg_DYNAPI_field *f; |
1996 | 0 | char *s = (char *)malloc (strlen (key) + 12); |
1997 | 0 | strcpy (s, key); |
1998 | 0 | strcat (s, "_size"); |
1999 | 0 | for (f = &fields[0]; f->name; f++) |
2000 | 0 | { |
2001 | 0 | if (strEQ (s, f->name)) |
2002 | 0 | { |
2003 | 0 | long size = 0; |
2004 | 0 | free (s); |
2005 | 0 | return f; |
2006 | 0 | } |
2007 | 0 | } |
2008 | 0 | free (s); |
2009 | 0 | return NULL; |
2010 | 0 | } |
2011 | | |
2012 | | #define FIXUP_NUMFIELD(type) \ |
2013 | 0 | { \ |
2014 | 0 | BITCODE_##type num; \ |
2015 | 0 | BITCODE_##type _size = (BITCODE_##type)size; \ |
2016 | 0 | LOG_TRACE ("%s = " FORMAT_##type "\n", f->name, _size); \ |
2017 | 0 | memcpy (&((char *)_obj)[f->offset], &_size, f->size); \ |
2018 | 0 | } \ |
2019 | 0 | break; |
2020 | | |
2021 | | static void |
2022 | | json_set_numfield (void *restrict _obj, |
2023 | | const Dwg_DYNAPI_field *restrict fields, |
2024 | | const char *restrict key, const long size) |
2025 | 0 | { |
2026 | 0 | const Dwg_DYNAPI_field *f = find_numfield (fields, key); |
2027 | 0 | if (f) |
2028 | 0 | { |
2029 | 0 | switch (f->size) |
2030 | 0 | { |
2031 | 0 | case 1: |
2032 | 0 | FIXUP_NUMFIELD (B) |
2033 | 0 | case 2: |
2034 | 0 | FIXUP_NUMFIELD (BS) |
2035 | 0 | case 4: |
2036 | 0 | FIXUP_NUMFIELD (BL) |
2037 | 0 | case 8: |
2038 | 0 | FIXUP_NUMFIELD (BLL) |
2039 | 0 | default: |
2040 | 0 | LOG_ERROR ("Unknown %s dynapi size %d", key, f->size); |
2041 | 0 | } |
2042 | 0 | } |
2043 | 0 | else if (strEQc (key, "transmatrix")) |
2044 | 0 | ; // ignore |
2045 | 0 | else if (strEQc (key, "ref")) |
2046 | 0 | { |
2047 | 0 | if (size != 4) // fixed size |
2048 | 0 | LOG_WARN ("Need 4 ref array elements, have %ld", size) |
2049 | 0 | else |
2050 | 0 | LOG_TRACE ("Check ref[] 4 ok\n") |
2051 | 0 | } |
2052 | 0 | else |
2053 | 0 | LOG_ERROR ("Unknown num_%s field", key); |
2054 | 0 | } |
2055 | | #undef FIXUP_NUMFIELD |
2056 | | |
2057 | | #define FIXUP_SIZEFIELD(type) \ |
2058 | 0 | { \ |
2059 | 0 | const BITCODE_##type _size = (BITCODE_##type)len; \ |
2060 | 0 | LOG_TRACE ("%s = " FORMAT_##type "\n", f->name, _size); \ |
2061 | 0 | memcpy (&((char *)_obj)[f->offset], &_size, f->size); \ |
2062 | 0 | } \ |
2063 | 0 | break; |
2064 | | |
2065 | | static void |
2066 | | json_fixup_JUMP (Dwg_Entity_JUMP *_obj) |
2067 | 0 | { |
2068 | 0 | if (_obj->jump_address_raw > 0xffffff) |
2069 | 0 | { |
2070 | 0 | _obj->jump_address &= 0xffffff; |
2071 | 0 | LOG_TRACE ("jump_address => " FORMAT_BLx "\n", _obj->jump_address); |
2072 | 0 | switch ((_obj->jump_address_raw & 0xff000000) >> 24) |
2073 | 0 | { |
2074 | 0 | case 0: |
2075 | 0 | LOG_TRACE ("jump_entity_section => DWG_ENTITIES_SECTION\n"); |
2076 | 0 | break; |
2077 | 0 | case 0x40: |
2078 | 0 | _obj->jump_entity_section = DWG_BLOCKS_SECTION; |
2079 | 0 | LOG_TRACE ("jump_entity_section => DWG_BLOCKS_SECTION\n"); |
2080 | 0 | break; |
2081 | 0 | case 0x80: |
2082 | 0 | _obj->jump_entity_section = DWG_EXTRA_SECTION; |
2083 | 0 | LOG_TRACE ("jump_entity_section => DWG_EXTRA_SECTION\n"); |
2084 | 0 | break; |
2085 | 0 | default: |
2086 | 0 | LOG_ERROR ("Invalid jump_entity_section %x ignored", |
2087 | 0 | (_obj->jump_address_raw & 0xff000000) >> 24) |
2088 | 0 | } |
2089 | 0 | } |
2090 | 0 | else |
2091 | 0 | LOG_TRACE ("jump_entity_section => DWG_ENTITIES_SECTION\n"); |
2092 | 0 | } |
2093 | | |
2094 | | // e.g. for TF strings: preview + preview_size. |
2095 | | static void |
2096 | | json_set_sizefield (void *restrict _obj, |
2097 | | const Dwg_DYNAPI_field *restrict fields, |
2098 | | const char *restrict key, const size_t len) |
2099 | 0 | { |
2100 | 0 | const Dwg_DYNAPI_field *f = find_sizefield (fields, key); |
2101 | 0 | if (f) |
2102 | 0 | { |
2103 | 0 | switch (f->size) |
2104 | 0 | { |
2105 | 0 | case 1: |
2106 | 0 | FIXUP_SIZEFIELD (B) |
2107 | 0 | case 2: |
2108 | 0 | FIXUP_SIZEFIELD (BS) |
2109 | 0 | case 4: |
2110 | 0 | FIXUP_SIZEFIELD (BL) |
2111 | 0 | case 8: |
2112 | 0 | FIXUP_SIZEFIELD (BLL) |
2113 | 0 | default: |
2114 | 0 | LOG_ERROR ("Unknown %s dynapi size %d", key, f->size); |
2115 | 0 | } |
2116 | 0 | } |
2117 | 0 | else |
2118 | 0 | { |
2119 | 0 | LOG_ERROR ("Unknown %s size field", key); |
2120 | 0 | } |
2121 | 0 | } |
2122 | | #undef FIXUP_SIZE |
2123 | | |
2124 | | // needs to be recursive, for search in subclasses |
2125 | | static int |
2126 | | _set_struct_field (Bit_Chain *restrict dat, const Dwg_Object *restrict obj, |
2127 | | jsmntokens_t *restrict tokens, void *restrict _obj, |
2128 | | const char *restrict name, const char *restrict key, |
2129 | | const Dwg_DYNAPI_field *restrict fields) |
2130 | 0 | { |
2131 | 0 | Dwg_Data *restrict dwg = obj->parent; |
2132 | 0 | const Dwg_DYNAPI_field *f = (Dwg_DYNAPI_field *)fields; |
2133 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
2134 | 0 | int error = 0; |
2135 | 0 | LOG_INSANE ("-search %s key %s: %s %.*s\n", name, key, t_typename[t->type], |
2136 | 0 | t->end - t->start, &dat->chain[t->start]); |
2137 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR; |
2138 | 0 | for (; f->name; f++) |
2139 | 0 | { |
2140 | 0 | if (strEQ (f->name, key)) |
2141 | 0 | break; |
2142 | 0 | } |
2143 | | // Found common, subclass or entity key, check types |
2144 | 0 | if (f && f->name) |
2145 | 0 | { |
2146 | 0 | LOG_INSANE ("-found %s [%s] %s\n", f->name, f->type, |
2147 | 0 | t_typename[t->type]); |
2148 | 0 | if (t->type == JSMN_PRIMITIVE |
2149 | 0 | && (strEQc (f->type, "BD") || strEQc (f->type, "RD") |
2150 | 0 | || strEQc (f->type, "BT"))) |
2151 | 0 | { |
2152 | 0 | double num = json_float (dat, tokens); |
2153 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR; |
2154 | 0 | LOG_TRACE ("%s.%s: %f [%s]\n", name, key, num, f->type); |
2155 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &num, 0); |
2156 | 0 | } |
2157 | | // all numfields are calculated from actual array sizes |
2158 | | // for easier adding or deleting entries. |
2159 | 0 | else if (t->type == JSMN_PRIMITIVE && memBEGINc (key, "num_")) |
2160 | 0 | { |
2161 | 0 | tokens->index++; |
2162 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR; |
2163 | 0 | LOG_TRACE ("%s.%s: %.*s (ignored)\n", name, key, t->end - t->start, |
2164 | 0 | &dat->chain[t->start]); |
2165 | 0 | } |
2166 | 0 | else if (t->type == JSMN_PRIMITIVE |
2167 | 0 | && (strEQc (f->type, "RC") || strEQc (f->type, "B") |
2168 | 0 | || strEQc (f->type, "BB") || strEQc (f->type, "RS") |
2169 | 0 | || strEQc (f->type, "BS") || strEQc (f->type, "RL") |
2170 | 0 | || strEQc (f->type, "BL") || strEQc (f->type, "BLd") |
2171 | 0 | || strEQc (f->type, "BSd") || strEQc (f->type, "RCd") |
2172 | 0 | || strEQc (f->type, "RSd") || strEQc (f->type, "4BITS"))) |
2173 | 0 | { |
2174 | 0 | uint32_t num = json_long (dat, tokens); |
2175 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2176 | 0 | LOG_TRACE ("%s.%s: " FORMAT_BL " [%s]\n", name, key, num, f->type); |
2177 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &num, 0); |
2178 | 0 | if (strEQc (name, "JUMP") && strEQc (key, "jump_address_raw")) |
2179 | 0 | { |
2180 | 0 | json_fixup_JUMP ((Dwg_Entity_JUMP *)_obj); |
2181 | 0 | LOG_TRACE ("%s.%s: " FORMAT_BLx " [RLx]\n", name, key, num); |
2182 | 0 | } |
2183 | 0 | } |
2184 | 0 | else if (t->type == JSMN_PRIMITIVE |
2185 | 0 | && (strEQc (f->type, "RLL") || strEQc (f->type, "BLL"))) |
2186 | 0 | { |
2187 | 0 | uint64_t num = json_longlong (dat, tokens); |
2188 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2189 | 0 | LOG_TRACE ("%s.%s: " FORMAT_RLL " [%s]\n", name, key, num, f->type); |
2190 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &num, 0); |
2191 | 0 | } |
2192 | | // TFF not yet in dynapi.c |
2193 | 0 | else if (t->type == JSMN_STRING |
2194 | 0 | && (strEQc (f->type, "TV") || strEQc (f->type, "T") |
2195 | 0 | || strEQc (f->type, "TF") || strEQc (f->type, "TU"))) |
2196 | 0 | { |
2197 | 0 | char *str = json_string (dat, tokens); |
2198 | 0 | size_t len = strlen (str); |
2199 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2200 | 0 | if (f->dxf == 310) // is BINARY. TODO: TABLE/FIELD *.data_date |
2201 | 0 | { |
2202 | | // convert from hex |
2203 | 0 | size_t blen = len / 2; |
2204 | 0 | size_t read; |
2205 | 0 | unsigned char *buf |
2206 | 0 | = len ? (unsigned char *)malloc (blen + 1) : NULL; |
2207 | 0 | char *pos = str; |
2208 | 0 | char *old; |
2209 | 0 | if (buf && pos) |
2210 | 0 | { |
2211 | 0 | if ((read = in_hex2bin (buf, pos, blen) != blen)) |
2212 | 0 | LOG_ERROR ("in_hex2bin with key %s at pos %" PRIuSIZE |
2213 | 0 | " of %" PRIuSIZE, |
2214 | 0 | key, read, blen); |
2215 | 0 | buf[blen] = '\0'; |
2216 | 0 | LOG_TRACE ("%s.%s: '%.*s'... [BINARY %" PRIuSIZE "]\n", name, |
2217 | 0 | key, MIN ((int)len, 60), str, len); |
2218 | 0 | } |
2219 | 0 | free (str); |
2220 | 0 | json_set_sizefield (_obj, fields, key, blen); |
2221 | | // set the ptr directly, no alloc, no conversion. |
2222 | 0 | old = &((char *)_obj)[f->offset]; |
2223 | 0 | memcpy (old, &buf, f->size); |
2224 | 0 | } |
2225 | | // is r11 fixed size string? (tables and controls, |
2226 | | // marked as TV, not TF) |
2227 | 0 | else if (dwg->header.from_version <= R_12 |
2228 | 0 | && (dwg_obj_is_table (obj) || dwg_obj_is_control (obj))) |
2229 | 0 | { |
2230 | 0 | char *old; |
2231 | | // sizes: |
2232 | | // 16: DIMSTYLE.DIM* |
2233 | | // 32: *.name |
2234 | | // 48: LTYPE.description |
2235 | | // 64: STYLE.font_file, bigfont_file |
2236 | | // 66: DIMSTYLE.DIMBLK2_T |
2237 | 0 | const int k = strEQc (key, "name") ? 32 |
2238 | 0 | : obj->fixedtype == DWG_TYPE_LTYPE ? 48 |
2239 | 0 | : obj->fixedtype == DWG_TYPE_DIMSTYLE |
2240 | 0 | && strEQc (key, "DIMBLK2_T") |
2241 | 0 | ? 66 |
2242 | 0 | : obj->fixedtype == DWG_TYPE_DIMSTYLE ? 16 |
2243 | 0 | : 64; |
2244 | 0 | tokens->index--; |
2245 | 0 | free (str); |
2246 | 0 | str = json_fixed_string (dat, k, tokens); |
2247 | 0 | LOG_TRACE ("%s.%s: \"%s\" [TF %d %d]\n", name, key, str, k, |
2248 | 0 | f->dxf); |
2249 | 0 | old = &((char *)_obj)[f->offset]; |
2250 | 0 | memcpy (old, &str, sizeof (char *)); |
2251 | 0 | } |
2252 | 0 | else if (strEQc (f->type, "TF")) // oleclient, strings_area, ... |
2253 | | // fixup size field |
2254 | 0 | { |
2255 | 0 | char *old; |
2256 | 0 | if (strEQc (key, "strings_area")) |
2257 | 0 | { |
2258 | 0 | const size_t k |
2259 | 0 | = dwg->header.from_version > R_2004 ? 512 : 256; |
2260 | 0 | const size_t blen = len / 2; |
2261 | | // binary hexstring |
2262 | 0 | BITCODE_TF buf = (BITCODE_TF)malloc (blen); |
2263 | 0 | len = in_hex2bin (buf, str, blen); |
2264 | 0 | if (len != blen) |
2265 | 0 | LOG_ERROR ("in_hex2bin with key %s at pos %" PRIuSIZE |
2266 | 0 | " of %" PRIuSIZE, |
2267 | 0 | key, len, blen); |
2268 | 0 | memcpy (str, buf, len); |
2269 | 0 | free (buf); |
2270 | 0 | if (len > k) |
2271 | 0 | { |
2272 | 0 | LOG_ERROR ("Illegal %s.%s length %" PRIuSIZE |
2273 | 0 | " > %" PRIuSIZE ", stripped", |
2274 | 0 | name, key, len, k); |
2275 | 0 | len = k; |
2276 | 0 | } |
2277 | 0 | else if (len != k) |
2278 | 0 | { |
2279 | 0 | str = (char *)realloc (str, k); |
2280 | 0 | memset (&str[len + 1], 0, k - len - 1); |
2281 | 0 | } |
2282 | 0 | } |
2283 | 0 | else if (f->size > sizeof (char *)) |
2284 | 0 | { |
2285 | 0 | str = (char *)realloc (str, f->size); |
2286 | 0 | memset (&str[len + 1], 0, f->size - len - 1); |
2287 | 0 | } |
2288 | 0 | LOG_TRACE ("%s.%s: \"%s\" [%s %d]\n", name, key, str, f->type, |
2289 | 0 | f->size); |
2290 | 0 | if (strNE (key, "strings_area")) |
2291 | 0 | json_set_sizefield (_obj, fields, key, len); |
2292 | 0 | old = &((char *)_obj)[f->offset]; |
2293 | 0 | memcpy (old, &str, sizeof (char *)); |
2294 | | // dwg_dynapi_field_set_value (dwg, _obj, f, &str, 1); |
2295 | 0 | } |
2296 | 0 | else |
2297 | 0 | { |
2298 | 0 | LOG_TRACE ("%s.%s: \"%s\" [%s] len=%d\n", name, key, str, |
2299 | 0 | f->type, (int)len); |
2300 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &str, 1); |
2301 | 0 | free (str); |
2302 | 0 | } |
2303 | 0 | } |
2304 | | // arrays |
2305 | 0 | else if (t->type == JSMN_ARRAY |
2306 | 0 | && (strEQc (f->type, "3BD") || strEQc (f->type, "3RD") |
2307 | 0 | || strEQc (f->type, "3DPOINT") || strEQc (f->type, "BE") |
2308 | 0 | || strEQc (f->type, "3BD_1"))) |
2309 | 0 | { |
2310 | 0 | BITCODE_3DPOINT pt; |
2311 | 0 | json_3DPOINT (dat, tokens, name, key, f->type, &pt); |
2312 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2313 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &pt, 1); |
2314 | 0 | } |
2315 | 0 | else if (t->type == JSMN_ARRAY |
2316 | 0 | && (strEQc (f->type, "2BD") || strEQc (f->type, "2RD") |
2317 | 0 | || strEQc (f->type, "2DPOINT") |
2318 | 0 | || strEQc (f->type, "2BD_1"))) |
2319 | 0 | { |
2320 | 0 | BITCODE_2DPOINT pt; |
2321 | 0 | json_2DPOINT (dat, tokens, name, key, f->type, &pt); |
2322 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2323 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &pt, 1); |
2324 | 0 | } |
2325 | 0 | else if (strEQc (f->type, "TIMEBLL") || strEQc (f->type, "TIMERLL")) |
2326 | 0 | { |
2327 | 0 | static BITCODE_TIMEBLL date = { 0, 0, 0 }; |
2328 | 0 | json_TIMEBLL (dat, tokens, key, &date); |
2329 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2330 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &date, 1); |
2331 | 0 | } |
2332 | 0 | else if (strEQc (f->type, "CMC")) |
2333 | 0 | { |
2334 | 0 | BITCODE_CMC color = { 0, 0, 0, 0, 0, NULL, NULL, NULL, 0, 0, 0 }; |
2335 | 0 | json_CMC (dat, dwg, tokens, name, key, &color); |
2336 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2337 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &color, 1); |
2338 | 0 | } |
2339 | 0 | else if (t->type == JSMN_ARRAY && strEQc (f->type, "H")) |
2340 | 0 | { |
2341 | 0 | BITCODE_H hdl; |
2342 | 0 | hdl = json_HANDLE (dat, dwg, tokens, name, key, obj, -1); |
2343 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2344 | 0 | if (hdl) |
2345 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &hdl, 1); |
2346 | 0 | } |
2347 | 0 | else if (t->type == JSMN_ARRAY && strEQc (f->type, "H*")) |
2348 | 0 | { |
2349 | 0 | BITCODE_BL size1 = t->size; |
2350 | 0 | BITCODE_H *hdls; |
2351 | 0 | if (memBEGINc (name, "DICTIONARY") && strEQc (key, "itemhandles")) |
2352 | 0 | { |
2353 | 0 | LOG_ERROR ("Illegal old json format"); |
2354 | 0 | return DWG_ERR_INVALIDDWG; |
2355 | 0 | } |
2356 | 0 | hdls |
2357 | 0 | = size1 ? (BITCODE_H *)calloc (size1, sizeof (BITCODE_H)) : NULL; |
2358 | 0 | json_set_numfield (_obj, fields, key, (long)size1); |
2359 | 0 | tokens->index++; |
2360 | 0 | for (int k = 0; k < t->size; k++) |
2361 | 0 | { |
2362 | 0 | BITCODE_H hdl; |
2363 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2364 | 0 | hdl = json_HANDLE (dat, dwg, tokens, name, key, obj, k); |
2365 | 0 | if (k < (int)size1) |
2366 | 0 | { |
2367 | 0 | if (hdl) |
2368 | 0 | hdls[k] = hdl; |
2369 | 0 | else |
2370 | 0 | hdls[k] = dwg_add_handleref (dwg, 0, 0, NULL); |
2371 | 0 | } |
2372 | 0 | else |
2373 | 0 | LOG_WARN ("ignored"); |
2374 | 0 | } |
2375 | 0 | if (!size1) |
2376 | 0 | LOG_TRACE ("%s.%s: [%s] empty\n", name, key, f->type); |
2377 | | // memcpy (&((char *)_obj)[f->offset], &hdls, sizeof (hdls)); |
2378 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &hdls, 1); |
2379 | 0 | } |
2380 | 0 | else if (t->type == JSMN_ARRAY |
2381 | 0 | && (strEQc (f->type, "T*") || strEQc (f->type, "TV*"))) |
2382 | 0 | { |
2383 | 0 | int skip = 0; |
2384 | 0 | BITCODE_BL size1 = t->size; |
2385 | 0 | BITCODE_T *elems; |
2386 | 0 | if (memBEGINc (name, "DICTIONARY") && strEQc (key, "texts")) |
2387 | 0 | { |
2388 | 0 | LOG_ERROR ("Illegal old json format"); |
2389 | 0 | return DWG_ERR_INVALIDDWG; |
2390 | 0 | } |
2391 | 0 | elems |
2392 | 0 | = size1 ? (BITCODE_T *)calloc (size1, sizeof (BITCODE_T)) : NULL; |
2393 | 0 | json_set_numfield (_obj, fields, key, (long)size1); |
2394 | 0 | tokens->index++; |
2395 | 0 | for (int k = 0; k < t->size; k++) |
2396 | 0 | { |
2397 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2398 | 0 | if (k < (int)size1) |
2399 | 0 | { |
2400 | 0 | elems[k] = json_string (dat, tokens); |
2401 | 0 | LOG_TRACE ("%s.%s[%d]: \"%s\" [%s]\n", name, key, k, |
2402 | 0 | elems[k], f->type); |
2403 | 0 | } |
2404 | 0 | else |
2405 | 0 | { |
2406 | 0 | tokens->index++; |
2407 | 0 | t = &tokens->tokens[tokens->index]; |
2408 | 0 | LOG_WARN ("%s.%s[%d]: \"%.*s\" [%s] ignored", name, key, k, |
2409 | 0 | t->end - t->start, &dat->chain[t->start], f->type); |
2410 | 0 | } |
2411 | 0 | } |
2412 | 0 | if (!t->size) |
2413 | 0 | LOG_TRACE ("%s.%s: [%s] empty\n", name, key, f->type); |
2414 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &elems, 1); |
2415 | 0 | } |
2416 | 0 | else if (t->type == JSMN_ARRAY |
2417 | 0 | && (strEQc (f->type, "3DPOINT*") || strEQc (f->type, "3BD*"))) |
2418 | 0 | { |
2419 | 0 | int size1 = t->size; |
2420 | 0 | BITCODE_3DPOINT *pts |
2421 | 0 | = size1 ? (BITCODE_3BD *)calloc (size1, sizeof (BITCODE_3BD)) |
2422 | 0 | : NULL; |
2423 | 0 | json_set_numfield (_obj, fields, key, size1); |
2424 | 0 | tokens->index++; |
2425 | 0 | for (int k = 0; k < size1; k++) |
2426 | 0 | { |
2427 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR; |
2428 | 0 | json_3DPOINT (dat, tokens, name, key, f->type, &pts[k]); |
2429 | 0 | } |
2430 | 0 | if (!size1) |
2431 | 0 | LOG_TRACE ("%s.%s: [%s] empty\n", name, key, f->type); |
2432 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &pts, 1); |
2433 | 0 | } |
2434 | 0 | else if (t->type == JSMN_ARRAY && strEQc (f->type, "2RD*")) |
2435 | 0 | { |
2436 | 0 | const int size1 = t->size; |
2437 | 0 | BITCODE_2DPOINT *pts = size1 ? (BITCODE_2DPOINT *)calloc ( |
2438 | 0 | size1, sizeof (BITCODE_2DPOINT)) |
2439 | 0 | : NULL; |
2440 | 0 | json_set_numfield (_obj, fields, key, size1); |
2441 | 0 | tokens->index++; |
2442 | 0 | for (int k = 0; k < size1; k++) |
2443 | 0 | { |
2444 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR; |
2445 | 0 | json_2DPOINT (dat, tokens, name, key, f->type, &pts[k]); |
2446 | 0 | } |
2447 | 0 | if (!size1) |
2448 | 0 | LOG_TRACE ("%s.%s: [%s] empty\n", name, key, f->type); |
2449 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &pts, 1); |
2450 | 0 | } |
2451 | 0 | else if (t->type == JSMN_ARRAY |
2452 | 0 | && (strEQc (f->type, "BD*") || strEQc (f->type, "RD"))) |
2453 | 0 | { |
2454 | 0 | const int size1 = t->size; |
2455 | 0 | const int max_k |
2456 | 0 | = !f->is_malloc ? (int)(f->size / sizeof (BITCODE_BD)) : size1; |
2457 | 0 | BITCODE_BD *nums; |
2458 | | // fail if not malloced or inlined array (but json has an array) |
2459 | 0 | if (f->size <= 8 && size1 > 1 && !f->is_malloc) |
2460 | 0 | { |
2461 | 0 | LOG_ERROR ("Invalid JSON: %s.%s array where primitive expected", |
2462 | 0 | name, f->name); |
2463 | 0 | tokens->index += size1; |
2464 | 0 | return 0; |
2465 | 0 | } |
2466 | 0 | if (f->is_malloc) |
2467 | 0 | { |
2468 | 0 | nums = size1 ? (BITCODE_BD *)calloc (size1, sizeof (BITCODE_BD)) |
2469 | 0 | : NULL; |
2470 | 0 | json_set_numfield (_obj, fields, key, size1); |
2471 | 0 | } |
2472 | 0 | else |
2473 | 0 | { |
2474 | 0 | nums = (BITCODE_BD *)calloc (f->size, 1); |
2475 | 0 | } |
2476 | 0 | tokens->index++; |
2477 | 0 | for (int k = 0; k < size1; k++) |
2478 | 0 | { |
2479 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2480 | 0 | if (k < max_k) |
2481 | 0 | { |
2482 | 0 | nums[k] = json_float (dat, tokens); |
2483 | 0 | LOG_TRACE ("%s.%s[%d]: %f [%s]\n", name, key, k, nums[k], |
2484 | 0 | f->type); |
2485 | 0 | } |
2486 | 0 | else |
2487 | 0 | { |
2488 | 0 | LOG_WARN ("Ignored %s.%s[%d]: %f [%s]", name, key, k, |
2489 | 0 | json_float (dat, tokens), f->type); |
2490 | 0 | } |
2491 | 0 | } |
2492 | 0 | if (!size1) |
2493 | 0 | { |
2494 | 0 | LOG_TRACE ("%s.%s: [%s] empty\n", name, key, f->type); |
2495 | 0 | } |
2496 | 0 | else |
2497 | 0 | { |
2498 | 0 | if (f->is_malloc) // BD*, just copy the pointer |
2499 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &nums, 1); |
2500 | 0 | else |
2501 | 0 | { // copy all values |
2502 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, nums, 1); |
2503 | 0 | free (nums); |
2504 | 0 | } |
2505 | 0 | } |
2506 | 0 | } |
2507 | 0 | else if (t->type == JSMN_ARRAY |
2508 | 0 | && (strEQc (f->type, "BL*") || strEQc (f->type, "BLd"))) |
2509 | 0 | { |
2510 | 0 | const int size1 = t->size; |
2511 | 0 | const int max_k |
2512 | 0 | = !f->is_malloc ? (int)(f->size / sizeof (BITCODE_BL)) : size1; |
2513 | 0 | BITCODE_BL *nums; |
2514 | | // fail if not malloced or inlined array (but json has an array) |
2515 | 0 | if (f->size <= 4 && size1 > 1) |
2516 | 0 | { |
2517 | 0 | LOG_ERROR ("Invalid JSON: %s.%s array where primitive expected", |
2518 | 0 | name, f->name); |
2519 | 0 | tokens->index += size1; |
2520 | 0 | return 0; |
2521 | 0 | } |
2522 | 0 | if (f->is_malloc) |
2523 | 0 | { |
2524 | 0 | nums = size1 ? (BITCODE_BL *)calloc (size1, sizeof (BITCODE_BL)) |
2525 | 0 | : NULL; |
2526 | 0 | json_set_numfield (_obj, fields, key, size1); |
2527 | 0 | } |
2528 | 0 | else |
2529 | 0 | nums = (BITCODE_BL *)calloc (f->size, 1); |
2530 | 0 | tokens->index++; |
2531 | 0 | for (int k = 0; k < size1; k++) |
2532 | 0 | { |
2533 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2534 | 0 | if (k < max_k) |
2535 | 0 | { |
2536 | 0 | nums[k] = json_long (dat, tokens); |
2537 | 0 | if (strEQc (f->type, "BL*")) |
2538 | 0 | { |
2539 | 0 | LOG_TRACE ("%s.%s[%d]: " FORMAT_BL " [%s]\n", name, key, |
2540 | 0 | k, nums[k], f->type); |
2541 | 0 | } |
2542 | 0 | else |
2543 | 0 | { |
2544 | 0 | LOG_TRACE ("%s.%s[%d]: " FORMAT_BLd " [%s]\n", name, key, |
2545 | 0 | k, nums[k], f->type); |
2546 | 0 | } |
2547 | 0 | } |
2548 | 0 | else |
2549 | 0 | { |
2550 | 0 | tokens->index++; |
2551 | 0 | LOG_TRACE ("%s.%s[%d]: [%s] ignored\n", name, key, k, |
2552 | 0 | f->type); |
2553 | 0 | } |
2554 | 0 | } |
2555 | 0 | if (!size1) |
2556 | 0 | { |
2557 | 0 | LOG_TRACE ("%s.%s: [%s] empty\n", name, key, f->type); |
2558 | 0 | } |
2559 | 0 | else |
2560 | 0 | { |
2561 | 0 | if (f->is_malloc) // BL* |
2562 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &nums, 1); |
2563 | 0 | else |
2564 | 0 | { |
2565 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, nums, 1); |
2566 | 0 | free (nums); |
2567 | 0 | } |
2568 | 0 | } |
2569 | 0 | } |
2570 | 0 | else if (t->type == JSMN_ARRAY |
2571 | 0 | && (strEQc (f->type, "BS") || strEQc (f->type, "BS*") |
2572 | 0 | || strEQc (f->type, "RS"))) |
2573 | 0 | { |
2574 | 0 | const int size1 = t->size; |
2575 | 0 | const int max_k |
2576 | 0 | = !f->is_malloc ? (int)(f->size / sizeof (BITCODE_BS)) : size1; |
2577 | 0 | BITCODE_BS *nums; |
2578 | | // fail if not malloced or inlined array (but json has an array) |
2579 | 0 | if (f->size <= 2 && size1 > 1) |
2580 | 0 | { |
2581 | 0 | LOG_ERROR ("Invalid JSON: %s.%s array where primitive expected", |
2582 | 0 | name, f->name); |
2583 | 0 | tokens->index += size1; |
2584 | 0 | return 0; |
2585 | 0 | } |
2586 | 0 | if (f->is_malloc) |
2587 | 0 | { |
2588 | 0 | nums = size1 ? (BITCODE_BS *)calloc (size1, sizeof (BITCODE_BS)) |
2589 | 0 | : NULL; |
2590 | 0 | json_set_numfield (_obj, fields, key, size1); |
2591 | 0 | } |
2592 | 0 | else |
2593 | 0 | nums = (BITCODE_BS *)calloc (f->size, 1); |
2594 | 0 | tokens->index++; |
2595 | 0 | for (int k = 0; k < size1; k++) |
2596 | 0 | { |
2597 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2598 | 0 | if (k < max_k) |
2599 | 0 | { |
2600 | 0 | nums[k] = (BITCODE_BS)json_long (dat, tokens); |
2601 | 0 | LOG_TRACE ("%s.%s[%d]: " FORMAT_BS " [%s]\n", name, key, k, |
2602 | 0 | nums[k], f->type); |
2603 | 0 | } |
2604 | 0 | else |
2605 | 0 | { |
2606 | 0 | tokens->index++; |
2607 | 0 | LOG_TRACE ("%s.%s[%d]: [%s] ignored\n", name, key, k, |
2608 | 0 | f->type); |
2609 | 0 | } |
2610 | 0 | } |
2611 | 0 | if (!size1) |
2612 | 0 | { |
2613 | 0 | LOG_TRACE ("%s.%s: [%s] empty\n", name, key, f->type); |
2614 | 0 | } |
2615 | 0 | else |
2616 | 0 | { |
2617 | 0 | if (f->is_malloc) // BS* |
2618 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &nums, 1); |
2619 | 0 | else |
2620 | 0 | { |
2621 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, nums, 1); |
2622 | 0 | free (nums); |
2623 | 0 | } |
2624 | 0 | } |
2625 | 0 | } |
2626 | 0 | else if (t->type == JSMN_ARRAY && strEQc (key, "xdata") |
2627 | 0 | && strEQc (name, "XRECORD")) |
2628 | 0 | { |
2629 | 0 | error |= json_xdata (dat, dwg, tokens, (Dwg_Object_XRECORD *)_obj); |
2630 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2631 | 0 | } |
2632 | 0 | else if (t->type == JSMN_ARRAY && strEQc (key, "acis_data") |
2633 | 0 | && strEQc (f->type, "RC*")) |
2634 | 0 | { |
2635 | 0 | error |= json_acis_data (dat, dwg, tokens, obj); |
2636 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR; |
2637 | 0 | } |
2638 | 0 | else if (t->type == JSMN_ARRAY && strEQc (key, "encr_sat_data") |
2639 | 0 | && strEQc (f->type, "char **")) |
2640 | 0 | { |
2641 | 0 | BITCODE_BL num_blocks = t->size; |
2642 | 0 | BITCODE_BL *block_size |
2643 | 0 | = (BITCODE_BL *)calloc (num_blocks + 1, sizeof (BITCODE_BL)); |
2644 | 0 | unsigned char **data = (unsigned char **)calloc ( |
2645 | 0 | num_blocks + 1, sizeof (unsigned char *)); |
2646 | 0 | tokens->index++; |
2647 | 0 | LOG_TRACE ("num_blocks: " FORMAT_BL " [BL]\n", num_blocks); |
2648 | 0 | for (BITCODE_BL k = 0; k < num_blocks; k++) |
2649 | 0 | { |
2650 | 0 | size_t len; |
2651 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2652 | 0 | data[k] = json_binary (dat, tokens, "encr_sat_data", &len); |
2653 | 0 | block_size[k] = (BITCODE_BL)len; |
2654 | 0 | LOG_TRACE ("block_size[%d]: %" PRIuSIZE " [BL]\n", k, len); |
2655 | 0 | } |
2656 | 0 | block_size[num_blocks] = 0; |
2657 | 0 | LOG_TRACE ("block_size[%d]: 0 [BL]\n", num_blocks); |
2658 | 0 | dwg_dynapi_entity_set_value (_obj, obj->name, "num_blocks", |
2659 | 0 | &num_blocks, true); |
2660 | 0 | dwg_dynapi_entity_set_value (_obj, obj->name, "block_size", |
2661 | 0 | &block_size, true); |
2662 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &data, true); |
2663 | 0 | } |
2664 | | // TFFx (binary) |
2665 | 0 | else if (t->type == JSMN_STRING && strEQc (key, "revision_bytes")) |
2666 | 0 | { |
2667 | 0 | size_t len; |
2668 | 0 | unsigned char *s = json_binary (dat, tokens, "revision_bytes", &len); |
2669 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2670 | 0 | f = dwg_dynapi_entity_field (name, "revision_bytes"); |
2671 | 0 | if (f && len == 8) |
2672 | 0 | { |
2673 | 0 | LOG_TRACE ("%s.%s: [%s]\n", name, key, s); |
2674 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, s, true); |
2675 | 0 | } |
2676 | 0 | free (s); |
2677 | 0 | } |
2678 | | // subclass arrays: |
2679 | 0 | else if (t->type == JSMN_ARRAY && memBEGINc (f->type, "Dwg_")) |
2680 | 0 | { |
2681 | 0 | int num_elems = t->size; |
2682 | 0 | int size_elem; |
2683 | 0 | char *elems; |
2684 | 0 | const Dwg_DYNAPI_field *sfields; |
2685 | | // strip off Dwg_ and final * |
2686 | | // e.g. 'Dwg_MLINESTYLE_line*' => 'MLINESTYLE_line' |
2687 | 0 | char *subclass = dwg_dynapi_subclass_name (f->type); |
2688 | 0 | if (!subclass) |
2689 | 0 | { |
2690 | 0 | LOG_ERROR ("Unknown subclass type %s", f->type); |
2691 | 0 | goto unknown_ent; |
2692 | 0 | } |
2693 | 0 | size_elem = dwg_dynapi_fields_size (subclass); |
2694 | 0 | sfields = dwg_dynapi_subclass_fields (subclass); |
2695 | 0 | if (!size_elem || !sfields) |
2696 | 0 | { |
2697 | 0 | LOG_ERROR ("Unknown subclass name %s", subclass); |
2698 | 0 | free (subclass); |
2699 | 0 | goto unknown_ent; |
2700 | 0 | } |
2701 | 0 | LOG_TRACE ("new subclass %s %s [%d elems with size %d]\n", name, |
2702 | 0 | subclass, num_elems, size_elem); |
2703 | 0 | json_set_numfield (_obj, fields, key, num_elems); |
2704 | 0 | if (strEQc (subclass, "MLINE_line") && num_elems) |
2705 | 0 | { |
2706 | 0 | Dwg_Entity_MLINE *o = obj->tio.entity->tio.MLINE; |
2707 | 0 | o->num_lines = num_elems; |
2708 | 0 | LOG_TRACE ("MLINE.num_lines = %d\n", num_elems); |
2709 | 0 | } |
2710 | 0 | if (strEQc (subclass, "DIMASSOC_Ref") && num_elems != 4) |
2711 | 0 | { |
2712 | 0 | elems = (char *)calloc (MAX (4, num_elems), size_elem); |
2713 | 0 | LOG_TRACE ("DIMASSOC num_refs = 4\n"); |
2714 | 0 | } |
2715 | 0 | else |
2716 | 0 | elems = num_elems ? (char *)calloc (num_elems, size_elem) : NULL; |
2717 | 0 | dwg_dynapi_field_set_value (dwg, _obj, f, &elems, 1); |
2718 | 0 | tokens->index++; |
2719 | | // array of structs |
2720 | 0 | if (!num_elems) |
2721 | 0 | LOG_TRACE ("%s: [%s] empty\n", key, f->type); |
2722 | 0 | for (int k = 0; k < num_elems; k++) |
2723 | 0 | { |
2724 | 0 | int keys; |
2725 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2726 | 0 | t = &tokens->tokens[tokens->index]; |
2727 | 0 | if (t->type != JSMN_OBJECT) |
2728 | 0 | { |
2729 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected " |
2730 | 0 | "%s OBJECT. %s:%d", |
2731 | 0 | t_typename[t->type], tokens->index, |
2732 | 0 | tokens->num_tokens, subclass, __FUNCTION__, |
2733 | 0 | __LINE__); |
2734 | 0 | free (subclass); |
2735 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
2736 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2737 | 0 | return DWG_ERR_INVALIDTYPE; |
2738 | 0 | } |
2739 | 0 | LOG_TRACE ("%s.%s[%d]:\n", name, key, k); |
2740 | 0 | keys = t->size; |
2741 | 0 | tokens->index++; |
2742 | 0 | for (int ki = 0; ki < keys; ki++) |
2743 | 0 | { |
2744 | | // separate subclass type loop |
2745 | 0 | const Dwg_DYNAPI_field *f1; |
2746 | 0 | char key1[80]; |
2747 | 0 | char *rest; |
2748 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2749 | 0 | json_fixed_key (key1, dat, tokens); |
2750 | 0 | LOG_INSANE ("-search %s key: %s\n", subclass, key1); |
2751 | 0 | f1 = dwg_dynapi_subclass_field (subclass, key1); |
2752 | 0 | if (f1) |
2753 | 0 | { |
2754 | 0 | LOG_INSANE ("-found %s [%s]\n", f1->name, f1->type); |
2755 | 0 | if (!_set_struct_field (dat, obj, tokens, |
2756 | 0 | &elems[k * size_elem], subclass, |
2757 | 0 | key1, sfields)) |
2758 | 0 | ++tokens->index; |
2759 | 0 | } |
2760 | 0 | else if ((rest = strchr (key1, '.'))) // embedded struct |
2761 | 0 | { |
2762 | 0 | *rest = '\0'; |
2763 | 0 | rest++; |
2764 | 0 | f1 = dwg_dynapi_subclass_field (subclass, key1); |
2765 | 0 | if (f1 && *rest) |
2766 | 0 | { |
2767 | 0 | char *sb1 = dwg_dynapi_subclass_name (f1->type); |
2768 | 0 | const Dwg_DYNAPI_field *sfields1 |
2769 | 0 | = sb1 ? dwg_dynapi_subclass_fields (sb1) : NULL; |
2770 | 0 | if (!sfields1 |
2771 | 0 | || !_set_struct_field ( |
2772 | 0 | dat, obj, tokens, |
2773 | 0 | &elems[(k * size_elem) + f1->offset], sb1, |
2774 | 0 | rest, sfields1)) |
2775 | 0 | ++tokens->index; |
2776 | 0 | free (sb1); |
2777 | 0 | } |
2778 | 0 | } |
2779 | 0 | if (!f1 || !f1->name) // not found |
2780 | 0 | { |
2781 | 0 | LOG_ERROR ("Unknown subclass field %s.%s", subclass, |
2782 | 0 | key1); |
2783 | 0 | ++tokens->index; |
2784 | 0 | } |
2785 | 0 | } |
2786 | 0 | } |
2787 | 0 | if (dwg_dynapi_field_set_value (dwg, _obj, f, &elems, 1)) |
2788 | 0 | LOG_TRACE ("subclass %s.%s done\n", name, key); |
2789 | 0 | free (subclass); |
2790 | 0 | } |
2791 | | // subclass structs (embedded): |
2792 | 0 | else if (t->type == JSMN_OBJECT && memBEGINc (f->type, "Dwg_")) |
2793 | 0 | { |
2794 | 0 | int num_keys = t->size; // div by 2 really |
2795 | | // int size_struct; |
2796 | 0 | const Dwg_DYNAPI_field *sfields; |
2797 | 0 | char *subclass = dwg_dynapi_subclass_name (f->type); |
2798 | 0 | if (!subclass) |
2799 | 0 | { |
2800 | 0 | LOG_ERROR ("Unknown subclass type %s", f->type); |
2801 | 0 | goto unknown_ent; |
2802 | 0 | } |
2803 | | // size_struct = dwg_dynapi_fields_size (subclass); |
2804 | 0 | sfields = dwg_dynapi_subclass_fields (subclass); |
2805 | 0 | if (!sfields) |
2806 | 0 | { |
2807 | 0 | LOG_ERROR ("Unknown subclass name %s", subclass); |
2808 | 0 | free (subclass); |
2809 | 0 | goto unknown_ent; |
2810 | 0 | } |
2811 | 0 | LOG_TRACE ("embedded struct %s %s [%d keys]\n", subclass, key, |
2812 | 0 | num_keys / 2); |
2813 | 0 | tokens->index++; |
2814 | | // a single struct |
2815 | 0 | if (!num_keys) |
2816 | 0 | LOG_TRACE ("%s: [%s] empty\n", key, f->type); |
2817 | 0 | for (int k = 0; k < num_keys; k++) |
2818 | 0 | { |
2819 | 0 | const Dwg_DYNAPI_field *f1; |
2820 | 0 | char key1[80]; |
2821 | 0 | char *rest; |
2822 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2823 | 0 | json_fixed_key (key1, dat, tokens); |
2824 | 0 | LOG_INSANE ("-search %s key %s\n", subclass, key1); |
2825 | 0 | f1 = dwg_dynapi_subclass_field (subclass, key1); |
2826 | 0 | if (f1) |
2827 | 0 | { |
2828 | | // subclass offset for _obj |
2829 | 0 | void *off = &((char *)_obj)[f->offset + f1->offset]; |
2830 | 0 | if (!_set_struct_field (dat, obj, tokens, off, subclass, |
2831 | 0 | key1, sfields)) |
2832 | 0 | ++tokens->index; |
2833 | 0 | } |
2834 | 0 | else if ((rest = strchr (key1, '.'))) // embedded struct |
2835 | 0 | { |
2836 | 0 | *rest = '\0'; |
2837 | 0 | rest++; |
2838 | 0 | f1 = dwg_dynapi_subclass_field (subclass, key1); |
2839 | 0 | if (f1 && *rest) |
2840 | 0 | { |
2841 | 0 | void *off = &((char *)_obj)[f->offset + f1->offset]; |
2842 | 0 | char *subclass1 = dwg_dynapi_subclass_name (f1->type); |
2843 | 0 | const Dwg_DYNAPI_field *sfields1 |
2844 | 0 | = subclass1 ? dwg_dynapi_subclass_fields (subclass1) |
2845 | 0 | : NULL; |
2846 | 0 | if (!sfields1 |
2847 | 0 | || !_set_struct_field (dat, obj, tokens, off, |
2848 | 0 | subclass1, rest, sfields1)) |
2849 | 0 | ++tokens->index; |
2850 | 0 | free (subclass1); |
2851 | 0 | } |
2852 | 0 | } |
2853 | 0 | if (!f1 || !f1->name) // not found |
2854 | 0 | { |
2855 | 0 | LOG_ERROR ("Unknown subclass field %s.%s", subclass, key1); |
2856 | 0 | ++tokens->index; |
2857 | 0 | } |
2858 | 0 | } |
2859 | 0 | free (subclass); |
2860 | 0 | } |
2861 | 0 | else |
2862 | 0 | { |
2863 | 0 | unknown_ent: |
2864 | 0 | LOG_ERROR ("Unknown type for %s.%s %s with %s", name, key, f->type, |
2865 | 0 | t_typename[t->type]); |
2866 | 0 | ++tokens->index; |
2867 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
2868 | 0 | } |
2869 | 0 | return error | (f->name ? 1 : 0); // found or not |
2870 | 0 | } |
2871 | 0 | else // not found |
2872 | 0 | { // maybe it's an embedded subclass. look for the dot(s) |
2873 | 0 | int found = 0; |
2874 | 0 | char *rest = strchr ((char *)key, '.'); |
2875 | 0 | while (rest) |
2876 | 0 | { |
2877 | | // Currently we have 3 known static arrays, and a few embedded |
2878 | | // subclasses. Color e.g. |
2879 | 0 | const Dwg_DYNAPI_field *f1; |
2880 | 0 | const char *subclass = NULL; |
2881 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR; |
2882 | 0 | *rest = '\0'; |
2883 | 0 | rest++; |
2884 | 0 | f1 = dwg_dynapi_entity_field (name, key); |
2885 | 0 | if (f1 && *rest) |
2886 | 0 | { |
2887 | 0 | void *off = &((char *)_obj)[f1->offset]; |
2888 | 0 | const char *subclass1 = dwg_dynapi_subclass_name (f1->type); |
2889 | 0 | const Dwg_DYNAPI_field *sfields1 |
2890 | 0 | = subclass1 ? dwg_dynapi_subclass_fields (subclass1) : NULL; |
2891 | 0 | if (!sfields1 && subclass1) |
2892 | 0 | sfields1 = dwg_dynapi_entity_fields (subclass1); |
2893 | 0 | if (!sfields1 |
2894 | 0 | || !_set_struct_field (dat, obj, tokens, off, subclass1, |
2895 | 0 | rest, sfields1)) |
2896 | 0 | ++tokens->index; |
2897 | 0 | free ((char *)subclass1); |
2898 | 0 | return error | (f1->name ? 1 : 0); // found or not |
2899 | 0 | } |
2900 | 0 | f1 = dwg_dynapi_subclass_field (name, key); |
2901 | 0 | if (f1 && *rest) |
2902 | 0 | { |
2903 | 0 | void *off = &((char *)_obj)[f1->offset]; |
2904 | 0 | const char *subclass1 = dwg_dynapi_subclass_name (f1->type); |
2905 | 0 | const Dwg_DYNAPI_field *sfields1 |
2906 | 0 | = subclass1 ? dwg_dynapi_subclass_fields (subclass1) : NULL; |
2907 | 0 | if (!sfields1 && subclass1) |
2908 | 0 | sfields1 = dwg_dynapi_entity_fields (subclass1); |
2909 | 0 | if (!sfields1 |
2910 | 0 | || !_set_struct_field (dat, obj, tokens, off, subclass1, |
2911 | 0 | rest, sfields1)) |
2912 | 0 | ++tokens->index; |
2913 | 0 | free ((char *)subclass1); |
2914 | 0 | return error | (f1->name ? 1 : 0); // found or not |
2915 | 0 | } |
2916 | 0 | else |
2917 | 0 | { |
2918 | | // failed_key.rest.nextfieldatteept |
2919 | 0 | *(rest - 1) = '.'; // unsuccessful search, set the dot back |
2920 | 0 | rest = strchr (rest, '.'); |
2921 | 0 | if (rest) |
2922 | 0 | { |
2923 | 0 | LOG_HANDLE ("Try next embedded struct with %s.%s\n", key, |
2924 | 0 | rest); |
2925 | 0 | } |
2926 | 0 | else |
2927 | 0 | { |
2928 | 0 | LOG_HANDLE ("No embedded struct with %s\n", key); |
2929 | 0 | } |
2930 | 0 | } |
2931 | 0 | } |
2932 | 0 | } |
2933 | 0 | return error; |
2934 | 0 | } |
2935 | | |
2936 | | /* |
2937 | | // check both texts[] and itemhandles[] |
2938 | | static void |
2939 | | in_postprocess_DICTIONARY (Dwg_Object *obj) |
2940 | | { |
2941 | | Dwg_Object_DICTIONARY *_obj = obj->tio.object->tio.DICTIONARY; |
2942 | | int do_free = 0; |
2943 | | if (_obj->numitems == (BITCODE_BL)-1) |
2944 | | { |
2945 | | _obj->numitems = 0; |
2946 | | do_free = 1; |
2947 | | LOG_ERROR ("reset DICTIONARY, no numitems"); |
2948 | | } |
2949 | | if ((_obj->numitems || do_free) && !_obj->texts) |
2950 | | { |
2951 | | LOG_ERROR ("reset DICTIONARY, no texts"); |
2952 | | // need to leave the handles, just free H* |
2953 | | free (_obj->itemhandles); |
2954 | | _obj->itemhandles = NULL; |
2955 | | _obj->numitems = 0; |
2956 | | } |
2957 | | if ((_obj->numitems || do_free) && !_obj->itemhandles) |
2958 | | { |
2959 | | LOG_ERROR ("reset DICTIONARY, no itemhandles"); |
2960 | | for (BITCODE_BL i = 0; i < _obj->numitems; i++) |
2961 | | free (_obj->texts[i]); |
2962 | | free (_obj->texts); |
2963 | | _obj->texts = NULL; |
2964 | | _obj->numitems = 0; |
2965 | | } |
2966 | | } |
2967 | | // check both texts[] and itemhandles[] |
2968 | | static void |
2969 | | in_postprocess_DICTIONARYWDFLT (Dwg_Object *obj) |
2970 | | { |
2971 | | Dwg_Object_DICTIONARYWDFLT *_obj = obj->tio.object->tio.DICTIONARYWDFLT; |
2972 | | int do_free = 0; |
2973 | | if (_obj->numitems == (BITCODE_BL)-1) |
2974 | | { |
2975 | | _obj->numitems = 0; |
2976 | | do_free = 1; |
2977 | | LOG_ERROR ("reset DICTIONARYWDFLT, no numitems"); |
2978 | | } |
2979 | | if ((_obj->numitems || do_free) && !_obj->texts) |
2980 | | { |
2981 | | LOG_ERROR ("reset DICTIONARYWDFLT, no texts"); |
2982 | | // need to leave the handles, just free H* |
2983 | | free (_obj->itemhandles); |
2984 | | _obj->itemhandles = NULL; |
2985 | | _obj->numitems = 0; |
2986 | | } |
2987 | | if ((_obj->numitems || do_free) && !_obj->itemhandles) |
2988 | | { |
2989 | | LOG_ERROR ("reset DICTIONARYWDFLT, no itemhandles"); |
2990 | | for (BITCODE_BL i = 0; i < _obj->numitems; i++) |
2991 | | free (_obj->texts[i]); |
2992 | | free (_obj->texts); |
2993 | | _obj->texts = NULL; |
2994 | | _obj->numitems = 0; |
2995 | | } |
2996 | | } |
2997 | | */ |
2998 | | |
2999 | | static int |
3000 | | json_OBJECTS (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
3001 | | jsmntokens_t *restrict tokens) |
3002 | 2 | { |
3003 | 2 | const char *section = "OBJECTS"; |
3004 | 2 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
3005 | 2 | int i, size; |
3006 | 2 | if (t->type != JSMN_ARRAY || dwg->num_objects) |
3007 | 0 | { |
3008 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s ARRAY", |
3009 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
3010 | 0 | section); |
3011 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3012 | 0 | return DWG_ERR_INVALIDTYPE; |
3013 | 0 | } |
3014 | 2 | size = t->size; |
3015 | 2 | LOG_TRACE ("\n%s pos:%d [%d members]\n--------------------\n", section, |
3016 | 2 | tokens->index, size); |
3017 | 2 | tokens->index++; |
3018 | 2 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3019 | 2 | if (dwg->num_objects == 0) |
3020 | 2 | { |
3021 | | // faster version of dwg_add_object() |
3022 | | // round up to next REFS_PER_REALLOC |
3023 | 2 | int rounded = size; |
3024 | 2 | if (rounded % REFS_PER_REALLOC) |
3025 | 2 | rounded += REFS_PER_REALLOC - (rounded % REFS_PER_REALLOC); |
3026 | 2 | dwg->object = (Dwg_Object *)calloc (rounded, sizeof (Dwg_Object)); |
3027 | 2 | } |
3028 | 0 | else |
3029 | 0 | dwg_add_object (dwg); |
3030 | 2 | if (!dwg->object) |
3031 | 0 | { |
3032 | 0 | LOG_ERROR ("Out of memory"); |
3033 | 0 | return DWG_ERR_OUTOFMEM; |
3034 | 0 | } |
3035 | 2 | if (dwg->header.from_version < R_13b1) |
3036 | 2 | { |
3037 | 2 | dwg->header.section |
3038 | 2 | = (Dwg_Section *)calloc (SECTION_VX + 1, sizeof (Dwg_Section)); |
3039 | 2 | } |
3040 | 2 | dwg->num_objects += size; |
3041 | 2 | for (i = 0; i < size; i++) |
3042 | 2 | { |
3043 | 2 | char name[80]; |
3044 | 2 | int keys; |
3045 | 2 | int is_entity = 0; |
3046 | 2 | Dwg_Object *obj = &dwg->object[i]; |
3047 | 2 | Dwg_Object_APPID *_obj = NULL; |
3048 | 2 | const Dwg_DYNAPI_field *fields = NULL, *cfields; |
3049 | 2 | const Dwg_DYNAPI_field *f; |
3050 | | |
3051 | 2 | memset (name, 0, sizeof (name)); |
3052 | 2 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3053 | 2 | if (i > 0) |
3054 | 0 | { |
3055 | 0 | Dwg_Object *oldobj = &dwg->object[i - 1]; |
3056 | 0 | if (dwg->header.from_version >= R_13b1 && !oldobj->handle.value) |
3057 | 0 | { |
3058 | 0 | LOG_ERROR ("Required %s.handle missing, skipped", oldobj->name) |
3059 | 0 | dwg_free_object (oldobj); |
3060 | 0 | obj = oldobj; |
3061 | 0 | i--; |
3062 | 0 | } |
3063 | 0 | else if (!oldobj->type) |
3064 | 0 | { |
3065 | 0 | if (dwg->header.from_version >= R_13b1 |
3066 | 0 | || (oldobj->fixedtype != DWG_TYPE_BLOCK |
3067 | 0 | && oldobj->fixedtype != DWG_TYPE_ENDBLK)) |
3068 | 0 | LOG_ERROR ("Required %s.type missing, skipped", oldobj->name) |
3069 | 0 | if (!oldobj->parent) |
3070 | 0 | oldobj->parent = dwg; |
3071 | 0 | dwg_free_object (oldobj); |
3072 | 0 | obj = oldobj; |
3073 | 0 | i--; |
3074 | 0 | size--; |
3075 | 0 | } |
3076 | 0 | else if (oldobj->fixedtype == DWG_TYPE_UNUSED) |
3077 | 0 | { |
3078 | 0 | LOG_ERROR ("Required %s.fixedtype missing, skipped", |
3079 | 0 | oldobj->name); |
3080 | 0 | if (!oldobj->parent) |
3081 | 0 | oldobj->parent = dwg; |
3082 | 0 | dwg_free_object (oldobj); |
3083 | 0 | obj = oldobj; |
3084 | 0 | i--; |
3085 | 0 | } |
3086 | 0 | if (oldobj->fixedtype == DWG_TYPE_SEQEND) |
3087 | 0 | { |
3088 | 0 | in_postprocess_SEQEND (oldobj, 0, NULL); |
3089 | 0 | } |
3090 | | /* |
3091 | | else if (oldobj->fixedtype == DWG_TYPE_DICTIONARY) |
3092 | | { |
3093 | | in_postprocess_DICTIONARY (oldobj); |
3094 | | } |
3095 | | else if (oldobj->fixedtype == DWG_TYPE_DICTIONARYWDFLT) |
3096 | | { |
3097 | | in_postprocess_DICTIONARYWDFLT (oldobj); |
3098 | | } |
3099 | | */ |
3100 | 0 | } |
3101 | | |
3102 | 2 | memset (obj, 0, sizeof (Dwg_Object)); |
3103 | 2 | t = &tokens->tokens[tokens->index]; |
3104 | 2 | if (t->type != JSMN_OBJECT) |
3105 | 0 | { |
3106 | 0 | LOG_ERROR ( |
3107 | 0 | "Unexpected %s at %u of %ld tokens, expected %s OBJECT. %s:%d", |
3108 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, section, |
3109 | 0 | __FUNCTION__, __LINE__); |
3110 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3111 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto typeerr) |
3112 | 0 | } |
3113 | 2 | keys = t->size; |
3114 | 2 | LOG_HANDLE ("\n-keys: %d, object %d of %d\n", keys, i, size); |
3115 | | |
3116 | 2 | tokens->index++; |
3117 | 2 | for (int j = 0; j < keys; j++) |
3118 | 2 | { |
3119 | 2 | bool saw_dxfname = false; |
3120 | 2 | char key[80]; |
3121 | 2 | memset (key, 0, sizeof (key)); |
3122 | 2 | LOG_INSANE ("[%d] ", j); |
3123 | 2 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3124 | 2 | json_fixed_key (key, dat, tokens); |
3125 | 2 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3126 | 2 | t = &tokens->tokens[tokens->index]; |
3127 | 2 | if (strEQc (key, "object") && t->type == JSMN_STRING |
3128 | 2 | && i < (int)dwg->num_objects && !dwg->object[i].type) |
3129 | 2 | { |
3130 | 2 | int len = t->end - t->start; |
3131 | 2 | int objsize = 16; |
3132 | 2 | obj->supertype = DWG_SUPERTYPE_OBJECT; |
3133 | 2 | obj->parent = dwg; |
3134 | 2 | obj->index = i; |
3135 | | |
3136 | 2 | if (len >= 80) |
3137 | 2 | { |
3138 | 2 | LOG_ERROR ("Illegal %s name %.*s", key, len, |
3139 | 2 | &dat->chain[t->start]) |
3140 | 2 | obj->type = obj->fixedtype = DWG_TYPE_DUMMY; |
3141 | | // exhaust the rest |
3142 | 2 | for (; j < keys; j++) |
3143 | 2 | { |
3144 | 2 | json_advance_unknown (dat, tokens, t->type, 0); // value |
3145 | 2 | tokens->index++; // next key |
3146 | 2 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3147 | 2 | } |
3148 | 0 | tokens->index--; |
3149 | 0 | break; |
3150 | 2 | } |
3151 | 0 | memcpy (name, &dat->chain[t->start], len); |
3152 | 0 | name[len] = '\0'; |
3153 | 0 | is_entity = 0; |
3154 | 0 | fields = dwg_dynapi_entity_fields (name); |
3155 | 0 | objsize = dwg_dynapi_fields_size (name); |
3156 | 0 | if (!fields || !objsize || !is_dwg_object (name)) |
3157 | 0 | { |
3158 | 0 | LOG_ERROR ("Unknown object %s (no fields)", name); |
3159 | | // skip_object: |
3160 | 0 | obj->type = obj->fixedtype = DWG_TYPE_DUMMY; |
3161 | | // exhaust the rest |
3162 | 0 | for (; j < keys; j++) |
3163 | 0 | { |
3164 | 0 | json_advance_unknown (dat, tokens, t->type, 0); // value |
3165 | 0 | tokens->index++; // next key |
3166 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3167 | 0 | } |
3168 | 0 | tokens->index--; |
3169 | 0 | break; |
3170 | 0 | } |
3171 | | // crashing acad import, but dxfin might be okay |
3172 | | /* |
3173 | | if (is_class_unstable (name) && |
3174 | | (strEQc (name, "TABLEGEOMETRY") || |
3175 | | strEQc (name, "WIPEOUT"))) |
3176 | | { |
3177 | | LOG_ERROR ("Unhandled object %s", name); |
3178 | | goto skip_object; |
3179 | | } |
3180 | | */ |
3181 | 0 | LOG_TRACE ("\nnew object %s [%d] (size: %d)\n", name, i, |
3182 | 0 | objsize); |
3183 | 0 | obj->tio.object = (Dwg_Object_Object *)calloc ( |
3184 | 0 | 1, sizeof (Dwg_Object_Object)); |
3185 | 0 | obj->tio.object->dwg = dwg; |
3186 | 0 | obj->tio.object->objid = i; |
3187 | | // NEW_OBJECT (dwg, obj) |
3188 | | // ADD_OBJECT loop? |
3189 | 0 | _obj = (Dwg_Object_APPID *)calloc (1, objsize); |
3190 | 0 | obj->tio.object->tio.APPID = _obj; |
3191 | 0 | obj->tio.object->tio.APPID->parent = obj->tio.object; |
3192 | 0 | free (obj->name); |
3193 | 0 | obj->name = strdup (name); |
3194 | | // TODO alias |
3195 | 0 | free (obj->dxfname); |
3196 | 0 | obj->dxfname = strdup (name); |
3197 | 0 | tokens->index++; |
3198 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3199 | 0 | } |
3200 | 0 | else if (strEQc (key, "entity") && t->type == JSMN_STRING |
3201 | 0 | && i < (int)dwg->num_objects && !dwg->object[i].type) |
3202 | 0 | { |
3203 | 0 | int len = t->end - t->start; |
3204 | 0 | int objsize; |
3205 | 0 | obj->supertype = DWG_SUPERTYPE_ENTITY; |
3206 | 0 | obj->parent = dwg; |
3207 | 0 | obj->index = i; |
3208 | |
|
3209 | 0 | if (len >= 80) |
3210 | 0 | { |
3211 | 0 | LOG_ERROR ("Illegal %s name %.*s", key, len, |
3212 | 0 | &dat->chain[t->start]) |
3213 | 0 | obj->type = obj->fixedtype = DWG_TYPE_DUMMY; |
3214 | | // exhaust the rest |
3215 | 0 | for (; j < keys; j++) |
3216 | 0 | { |
3217 | 0 | json_advance_unknown (dat, tokens, t->type, 0); // value |
3218 | 0 | tokens->index++; // next key |
3219 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3220 | 0 | } |
3221 | 0 | tokens->index--; |
3222 | 0 | break; |
3223 | 0 | } |
3224 | 0 | memcpy (name, &dat->chain[t->start], len); |
3225 | 0 | name[len] = '\0'; |
3226 | 0 | is_entity = 1; |
3227 | 0 | fields = dwg_dynapi_entity_fields (name); |
3228 | 0 | objsize = dwg_dynapi_fields_size (name); |
3229 | 0 | if (!fields || !objsize || !is_dwg_entity (name)) |
3230 | 0 | { |
3231 | 0 | LOG_ERROR ("Unknown entity %s (no fields)", name); |
3232 | 0 | obj->type = obj->fixedtype = DWG_TYPE_DUMMY; |
3233 | | // exhaust the rest |
3234 | 0 | for (; j < keys; j++) |
3235 | 0 | { |
3236 | 0 | json_advance_unknown (dat, tokens, t->type, 0); // value |
3237 | 0 | tokens->index++; // next key |
3238 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3239 | 0 | } |
3240 | 0 | tokens->index--; |
3241 | 0 | break; |
3242 | 0 | } |
3243 | 0 | LOG_TRACE ("\nnew entity %s [%d] (size: %d)\n", name, i, |
3244 | 0 | objsize); |
3245 | 0 | obj->tio.entity = (Dwg_Object_Entity *)calloc ( |
3246 | 0 | 1, sizeof (Dwg_Object_Entity)); |
3247 | 0 | obj->tio.entity->dwg = dwg; |
3248 | 0 | obj->tio.entity->objid = i; |
3249 | | // NEW_ENTITY (dwg, obj) |
3250 | | // ADD_ENTITY loop? |
3251 | 0 | _obj = (Dwg_Object_APPID *)calloc (1, objsize); |
3252 | 0 | obj->tio.entity->tio.POINT = (Dwg_Entity_POINT *)_obj; |
3253 | 0 | obj->tio.entity->tio.POINT->parent = obj->tio.entity; |
3254 | 0 | free (obj->name); |
3255 | 0 | obj->name = strdup (name); |
3256 | | // if different, the alias is done via extra dxfname key (below) |
3257 | 0 | free (obj->dxfname); |
3258 | 0 | obj->dxfname = strdup (name); |
3259 | 0 | tokens->index++; |
3260 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3261 | 0 | } |
3262 | 0 | else if (!obj || !fields) |
3263 | 0 | { |
3264 | 0 | LOG_ERROR ("Required object or entity key missing"); |
3265 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3266 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3267 | 0 | } |
3268 | 0 | else if (strEQc (key, "dxfname")) |
3269 | 0 | { |
3270 | 0 | free (obj->dxfname); |
3271 | 0 | saw_dxfname = true; |
3272 | 0 | obj->dxfname = json_string (dat, tokens); |
3273 | 0 | LOG_TRACE ("dxfname: %s\n", obj->dxfname) |
3274 | 0 | if (!obj->dxfname) |
3275 | 0 | obj->dxfname = strdup (name); |
3276 | | |
3277 | | // Some objects have various subtypes under one name. |
3278 | | // TODO OBJECTCONTEXTDATA, ... |
3279 | 0 | } |
3280 | 0 | else if (strEQc (key, "index") |
3281 | 0 | && strNE (name, "TableCellContent_Attr")) |
3282 | 0 | { |
3283 | 0 | BITCODE_RL index = json_long (dat, tokens); |
3284 | 0 | if (dat->from_version < R_13b1) |
3285 | 0 | { |
3286 | 0 | if (index > 5) |
3287 | 0 | index = obj->index; // we added 2 mspace blocks (type 0) |
3288 | | // in-between |
3289 | 0 | } |
3290 | 0 | if (obj->index != index) |
3291 | 0 | LOG_WARN ("Ignore wrong %s.index %d, expected %d", name, index, |
3292 | 0 | obj->index) |
3293 | 0 | LOG_TRACE ("index: %d\n", obj->index) |
3294 | 0 | } |
3295 | 0 | else if (strEQc (key, "type") && !obj->type) |
3296 | 0 | { |
3297 | 0 | int isent; |
3298 | 0 | const char *dxfname; |
3299 | 0 | obj->type = (BITCODE_BS)json_long (dat, tokens); |
3300 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3301 | | |
3302 | 0 | if (!dwg_object_name (name, &dxfname, &obj->fixedtype, &isent, |
3303 | 0 | NULL)) |
3304 | 0 | { |
3305 | 0 | LOG_ERROR ("Unknown object %s failed dwg_object_name()", |
3306 | 0 | name); |
3307 | | // exhaust the rest |
3308 | 0 | for (; j < keys; j++) |
3309 | 0 | { |
3310 | 0 | json_advance_unknown (dat, tokens, t->type, 0); // value |
3311 | 0 | tokens->index++; // next key |
3312 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3313 | 0 | } |
3314 | 0 | tokens->index--; |
3315 | 0 | break; |
3316 | 0 | } |
3317 | 0 | else |
3318 | 0 | { |
3319 | 0 | if (obj->dxfname && strNE (obj->dxfname, dxfname)) |
3320 | 0 | { |
3321 | 0 | if (memBEGINc (dxfname, "UNKNOWN_") || !saw_dxfname) |
3322 | 0 | LOG_TRACE ("Changed dxfname %s => %s\n", obj->dxfname, |
3323 | 0 | dxfname) |
3324 | 0 | else |
3325 | 0 | LOG_WARN ("Changed wrong dxfname %s => %s", |
3326 | 0 | obj->dxfname, dxfname) |
3327 | 0 | } |
3328 | 0 | free (obj->dxfname); |
3329 | 0 | obj->dxfname = strdup (dxfname); |
3330 | 0 | if (obj->type <= DWG_TYPE_LAYOUT |
3331 | 0 | && obj->fixedtype != obj->type |
3332 | 0 | && dwg->header.from_version >= R_13b1) |
3333 | 0 | { |
3334 | 0 | LOG_WARN ("Changed wrong type %d => %d", obj->type, |
3335 | 0 | obj->fixedtype) |
3336 | 0 | obj->type = obj->fixedtype; |
3337 | 0 | } |
3338 | 0 | if ((obj->supertype == DWG_SUPERTYPE_ENTITY && !isent) |
3339 | 0 | || (obj->supertype == DWG_SUPERTYPE_OBJECT && isent)) |
3340 | 0 | { |
3341 | 0 | LOG_ERROR ("Illegal object supertype for %s", name); |
3342 | | // exhaust the rest |
3343 | 0 | for (; j < keys; j++) |
3344 | 0 | { |
3345 | 0 | json_advance_unknown (dat, tokens, t->type, |
3346 | 0 | 0); // value |
3347 | 0 | tokens->index++; // next key |
3348 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr); |
3349 | 0 | } |
3350 | 0 | tokens->index--; |
3351 | 0 | break; |
3352 | 0 | } |
3353 | 0 | } |
3354 | 0 | LOG_TRACE ("type: %d,\tfixedtype: %d\n", obj->type, |
3355 | 0 | obj->fixedtype); |
3356 | 0 | if (dwg->header.from_version < R_13b1 && dwg_obj_is_table (obj)) |
3357 | 0 | { |
3358 | 0 | Dwg_Section_Type_r11 id = SECTION_HEADER_R11; |
3359 | 0 | switch (obj->fixedtype) |
3360 | 0 | { |
3361 | 0 | case DWG_TYPE_BLOCK_HEADER: |
3362 | 0 | id = SECTION_BLOCK; |
3363 | 0 | break; |
3364 | 0 | case DWG_TYPE_LAYER: |
3365 | 0 | id = SECTION_LAYER; |
3366 | 0 | break; |
3367 | 0 | case DWG_TYPE_STYLE: |
3368 | 0 | id = SECTION_STYLE; |
3369 | 0 | break; |
3370 | 0 | case DWG_TYPE_LTYPE: |
3371 | 0 | id = SECTION_LTYPE; |
3372 | 0 | break; |
3373 | 0 | case DWG_TYPE_VIEW: |
3374 | 0 | id = SECTION_VIEW; |
3375 | 0 | break; |
3376 | 0 | case DWG_TYPE_VPORT: |
3377 | 0 | id = SECTION_VPORT; |
3378 | 0 | break; |
3379 | 0 | case DWG_TYPE_APPID: |
3380 | 0 | id = SECTION_APPID; |
3381 | 0 | break; |
3382 | 0 | case DWG_TYPE_DIMSTYLE: |
3383 | 0 | id = SECTION_DIMSTYLE; |
3384 | 0 | break; |
3385 | 0 | case DWG_TYPE_VX_TABLE_RECORD: |
3386 | 0 | id = SECTION_VX; |
3387 | 0 | break; |
3388 | 0 | default: |
3389 | 0 | LOG_ERROR ("Invalid table type %s %u", obj->name, |
3390 | 0 | obj->fixedtype); |
3391 | | // assert (!obj->fixedtype); |
3392 | 0 | } |
3393 | 0 | if (id != SECTION_HEADER_R11) |
3394 | 0 | { |
3395 | | // TODO: maybe add a missing CONTROL object here. GH #453 |
3396 | 0 | dwg->header.section[id].number++; |
3397 | 0 | } |
3398 | 0 | } |
3399 | 0 | } |
3400 | | // Note: also _obj->size |
3401 | 0 | else if (strEQc (key, "size") && !obj->size |
3402 | 0 | && t->type == JSMN_PRIMITIVE) |
3403 | 0 | { |
3404 | 0 | obj->size = json_long (dat, tokens); |
3405 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3406 | 0 | if (dwg->header.from_version >= R_13b1 && !obj->handle.value) |
3407 | 0 | { |
3408 | 0 | LOG_ERROR ("Required %s.handle missing", name); |
3409 | 0 | goto harderr; |
3410 | 0 | } |
3411 | 0 | LOG_TRACE ("%s.size: %d\n", obj->name, obj->size) |
3412 | 0 | } |
3413 | 0 | else if (strEQc (key, "bitsize") && !obj->bitsize) |
3414 | 0 | { |
3415 | 0 | obj->bitsize = json_long (dat, tokens); |
3416 | 0 | LOG_TRACE ("%s.bitsize: %d\n", obj->name, obj->bitsize) |
3417 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3418 | 0 | } |
3419 | 0 | else if (strEQc (key, "address") && !obj->address) |
3420 | 0 | { |
3421 | 0 | obj->address = json_long (dat, tokens); |
3422 | 0 | LOG_TRACE ("%s.address: 0x%zx\n", obj->name, obj->address) |
3423 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3424 | 0 | } |
3425 | 0 | else if (strEQc (key, "handle") && !obj->handle.value) |
3426 | 0 | { |
3427 | 0 | BITCODE_H hdl |
3428 | 0 | = json_HANDLE (dat, dwg, tokens, name, key, obj, -1); |
3429 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3430 | 0 | if (hdl) |
3431 | 0 | { |
3432 | 0 | obj->handle.code = hdl->handleref.code; |
3433 | 0 | obj->handle.size = hdl->handleref.size; |
3434 | 0 | obj->handle.value = hdl->handleref.value; |
3435 | 0 | if (!hdl->handleref.code) |
3436 | 0 | { |
3437 | 0 | hdl->obj = obj; |
3438 | 0 | dwg_add_handle (&hdl->handleref, 0, hdl->handleref.value, |
3439 | 0 | obj); |
3440 | 0 | } |
3441 | 0 | } |
3442 | 0 | if (!obj->type) // TODO: We could eventually relax this |
3443 | 0 | { |
3444 | 0 | LOG_ERROR ("Required %s.type missing", name) |
3445 | 0 | return DWG_ERR_INVALIDDWG; |
3446 | 0 | } |
3447 | 0 | } |
3448 | | // ignore subclass markers |
3449 | 0 | else if (t->type == JSMN_STRING && strEQc (key, "_subclass")) |
3450 | 0 | { |
3451 | 0 | LOG_TRACE ("_subclass: %.*s\n", t->end - t->start, |
3452 | 0 | &dat->chain[t->start]); |
3453 | 0 | tokens->index++; |
3454 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3455 | 0 | } |
3456 | 0 | else if (strEQc (key, "num_unknown_bits")) |
3457 | 0 | { |
3458 | 0 | obj->num_unknown_bits = json_long (dat, tokens); |
3459 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3460 | 0 | LOG_TRACE ("num_unknown_bits: %d\n", (int)obj->num_unknown_bits); |
3461 | 0 | } |
3462 | 0 | else if (strEQc (key, "unknown_bits")) |
3463 | 0 | { |
3464 | 0 | const int len = t->end - t->start; |
3465 | 0 | char *hex = json_string (dat, tokens); |
3466 | 0 | const unsigned blen = len / 2; |
3467 | 0 | unsigned read; |
3468 | 0 | BITCODE_TF buf = (BITCODE_TF)malloc (blen + 1); |
3469 | 0 | if ((read = in_hex2bin (buf, hex, blen) != blen)) |
3470 | 0 | LOG_ERROR ("in_hex2bin with key %s at pos %u of %u", key, read, |
3471 | 0 | blen); |
3472 | 0 | buf[blen] = '\0'; |
3473 | 0 | free (hex); |
3474 | 0 | if (!obj->num_unknown_bits) |
3475 | 0 | obj->num_unknown_bits = blen * 8; // minus some padding bits |
3476 | 0 | if (obj->unknown_bits) |
3477 | 0 | free (obj->unknown_bits); |
3478 | 0 | obj->unknown_bits = buf; |
3479 | | // LOG_TRACE ("%s: '%.*s' [%s] (binary)\n", key, blen, buf, |
3480 | | // f->type); |
3481 | 0 | LOG_TRACE ("unknown_bits: %.*s\n", t->end - t->start, |
3482 | 0 | &dat->chain[t->start]) |
3483 | 0 | } |
3484 | 0 | else if (strEQc (key, "num_unknown_rest")) |
3485 | 0 | { |
3486 | 0 | obj->num_unknown_rest = json_long (dat, tokens); |
3487 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3488 | 0 | LOG_TRACE ("num_unknown_rest: %d\n", (int)obj->num_unknown_rest); |
3489 | 0 | } |
3490 | 0 | else if (strEQc (key, "unknown_rest")) |
3491 | 0 | { |
3492 | 0 | const int len = t->end - t->start; |
3493 | 0 | char *hex = json_string (dat, tokens); |
3494 | 0 | const unsigned blen = len / 2; |
3495 | 0 | unsigned read; |
3496 | 0 | BITCODE_TF buf = (BITCODE_TF)malloc (blen + 1); |
3497 | 0 | if (hex) |
3498 | 0 | { |
3499 | 0 | if ((read = in_hex2bin (buf, hex, blen) != blen)) |
3500 | 0 | LOG_ERROR ("in_hex2bin with key %s at pos %u of %u", key, read, |
3501 | 0 | blen); |
3502 | 0 | buf[blen] = '\0'; |
3503 | 0 | free (hex); |
3504 | 0 | } |
3505 | 0 | else |
3506 | 0 | { |
3507 | 0 | memset (buf, 0, blen); |
3508 | 0 | } |
3509 | 0 | if (!obj->num_unknown_rest) |
3510 | 0 | obj->num_unknown_rest = blen * 8; // minus some padding bits |
3511 | 0 | if (obj->unknown_rest) |
3512 | 0 | free (obj->unknown_rest); |
3513 | 0 | obj->unknown_rest = buf; |
3514 | | // LOG_TRACE ("%s: '%.*s' [%s] (binary)\n", key, blen, buf, |
3515 | | // f->type); |
3516 | 0 | LOG_TRACE ("unknown_rest: %.*s\n", t->end - t->start, |
3517 | 0 | &dat->chain[t->start]) |
3518 | 0 | } |
3519 | 0 | else if (strEQc (key, "eed") |
3520 | | // obj->tio.object shares a common prefix with entity until eed |
3521 | 0 | && !obj->tio.object->num_eed && t->type == JSMN_ARRAY) |
3522 | 0 | { |
3523 | 0 | json_eed (dat, dwg, tokens, obj->tio.object); |
3524 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3525 | 0 | } |
3526 | 0 | else |
3527 | | // search_field: |
3528 | 0 | { |
3529 | 0 | if (t->type == JSMN_STRING && is_entity && strEQc (key, "tag")) |
3530 | 0 | { |
3531 | 0 | int sz = t->end - t->start; |
3532 | 0 | char *tag = (char *)malloc (sz + 1); |
3533 | 0 | memcpy (tag, &dat->chain[t->start], sz); |
3534 | 0 | tag[sz] = '\0'; |
3535 | 0 | if (sz <= 0 || !dwg_is_valid_tag (tag)) |
3536 | 0 | { |
3537 | 0 | LOG_WARN ("Invalid %s.tag: %s\n", obj->name, tag); |
3538 | 0 | } |
3539 | 0 | free (tag); |
3540 | 0 | } |
3541 | 0 | if (_set_struct_field (dat, obj, tokens, _obj, name, key, |
3542 | 0 | fields)) |
3543 | 0 | continue; |
3544 | 0 | if (is_entity) |
3545 | 0 | { |
3546 | 0 | if (_set_struct_field (dat, obj, tokens, obj->tio.entity, |
3547 | 0 | name, key, |
3548 | 0 | dwg_dynapi_common_entity_fields ())) |
3549 | 0 | continue; |
3550 | 0 | } |
3551 | 0 | else |
3552 | 0 | { |
3553 | 0 | if (_set_struct_field (dat, obj, tokens, obj->tio.object, |
3554 | 0 | name, key, |
3555 | 0 | dwg_dynapi_common_object_fields ())) |
3556 | 0 | continue; |
3557 | 0 | } |
3558 | | |
3559 | | // This should now be handled in _set_struct_field, recursively. |
3560 | | // esp for TABLE's |
3561 | | // first the MLEADER_AnnotContext union: |
3562 | 0 | if (strEQc (name, "MULTILEADER")) |
3563 | 0 | { |
3564 | | // assert (0); |
3565 | | // embedded structs |
3566 | 0 | if (memBEGINc (key, "ctx.content.txt.")) |
3567 | 0 | { |
3568 | 0 | Dwg_Entity_MULTILEADER *_o |
3569 | 0 | = (Dwg_Entity_MULTILEADER *)_obj; |
3570 | 0 | Dwg_MLEADER_Content *cnt = &_o->ctx.content; |
3571 | 0 | const Dwg_DYNAPI_field *sf = dwg_dynapi_subclass_fields ( |
3572 | 0 | "MLEADER_Content_MText"); |
3573 | 0 | if (sf |
3574 | 0 | && _set_struct_field ( |
3575 | 0 | dat, obj, tokens, cnt, "MLEADER_Content", |
3576 | 0 | &key[strlen ("ctx.content.")], sf)) |
3577 | 0 | continue; |
3578 | 0 | } |
3579 | | // the rest |
3580 | 0 | else if (memBEGINc (key, "ctx.")) |
3581 | 0 | { |
3582 | 0 | Dwg_Entity_MULTILEADER *_o |
3583 | 0 | = (Dwg_Entity_MULTILEADER *)_obj; |
3584 | 0 | Dwg_MLEADER_AnnotContext *ctx = &_o->ctx; |
3585 | 0 | const Dwg_DYNAPI_field *sf = dwg_dynapi_subclass_fields ( |
3586 | 0 | "MLEADER_AnnotContext"); |
3587 | 0 | if (sf |
3588 | 0 | && _set_struct_field (dat, obj, tokens, ctx, |
3589 | 0 | "MLEADER_AnnotContext", |
3590 | 0 | &key[4], sf)) |
3591 | 0 | continue; |
3592 | 0 | } |
3593 | 0 | } |
3594 | 0 | else if (t->type == JSMN_OBJECT && memBEGINc (name, "DICTIONARY") |
3595 | 0 | && strEQc (key, "items")) |
3596 | 0 | { |
3597 | 0 | Dwg_Object_DICTIONARY *o = obj->tio.object->tio.DICTIONARY; |
3598 | 0 | o->numitems = t->size; |
3599 | 0 | o->texts = o->numitems ? (BITCODE_T *)calloc ( |
3600 | 0 | o->numitems, sizeof (BITCODE_T)) |
3601 | 0 | : NULL; |
3602 | 0 | o->itemhandles |
3603 | 0 | = o->numitems ? (BITCODE_H *)calloc (o->numitems, |
3604 | 0 | sizeof (BITCODE_H)) |
3605 | 0 | : NULL; |
3606 | 0 | tokens->index++; |
3607 | 0 | for (int k = 0; k < (int)o->numitems; k++) |
3608 | 0 | { |
3609 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr); |
3610 | 0 | t = &tokens->tokens[tokens->index]; |
3611 | | /*SINCE (R_2007a) |
3612 | | o->texts[k] = (BITCODE_T)json_wstring (dat, tokens); |
3613 | | else*/ |
3614 | 0 | o->texts[k] = json_string (dat, tokens); |
3615 | 0 | LOG_TRACE ("texts[%d]: %.*s\t => ", k, t->end - t->start, |
3616 | 0 | &dat->chain[t->start]); |
3617 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr); |
3618 | 0 | o->itemhandles[k] = json_HANDLE (dat, dwg, tokens, name, |
3619 | 0 | "itemhandles", obj, k); |
3620 | 0 | } |
3621 | 0 | if (!o->numitems) |
3622 | 0 | LOG_TRACE ("%s.%s empty\n", name, key); |
3623 | 0 | continue; |
3624 | 0 | } |
3625 | 0 | LOG_ERROR ("Unknown %s.%s %.*s ignored", name, key, |
3626 | 0 | t->end - t->start, &dat->chain[t->start]); |
3627 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3628 | 0 | JSON_TOKENS_CHECK_OVERFLOW (goto harderr) |
3629 | 0 | } |
3630 | 2 | } |
3631 | 2 | } |
3632 | 0 | LOG_TRACE ("End of %s\n", section) |
3633 | 0 | tokens->index--; |
3634 | 0 | return 0; |
3635 | 2 | harderr: |
3636 | 2 | dwg->num_objects = i; |
3637 | 2 | LOG_TRACE ("End of %s (hard error)\n", section) |
3638 | 2 | tokens->index--; |
3639 | 2 | return DWG_ERR_INVALIDDWG; |
3640 | 0 | typeerr: |
3641 | 0 | dwg->num_objects = i; |
3642 | 0 | LOG_TRACE ("End of %s (type error)\n", section) |
3643 | 0 | tokens->index--; |
3644 | 0 | return DWG_ERR_INVALIDTYPE; |
3645 | 2 | } |
3646 | | |
3647 | | static int |
3648 | | json_HANDLES (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
3649 | | jsmntokens_t *restrict tokens) |
3650 | 0 | { |
3651 | 0 | const char *section = "HANDLES"; |
3652 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
3653 | 0 | int size; |
3654 | 0 | if (t->type != JSMN_ARRAY) |
3655 | 0 | { |
3656 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
3657 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
3658 | 0 | section); |
3659 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3660 | 0 | return DWG_ERR_INVALIDTYPE; |
3661 | 0 | } |
3662 | 0 | size = t->size; |
3663 | 0 | LOG_TRACE ("\n%s pos:%d [%d members]\n--------------------\n", section, |
3664 | 0 | tokens->index, size); |
3665 | | // Maybe create dwg->header.section[SECTION_HANDLES_R13] omap here. |
3666 | | // struct { uint32_t hdloff; int32_t offset } *omap = calloc (size, 8); |
3667 | 0 | for (int i = 0; i < size; i++) |
3668 | 0 | { |
3669 | 0 | tokens->index++; |
3670 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3671 | 0 | for (int k = 0; k < 2; k++) |
3672 | 0 | { |
3673 | 0 | uint32_t hdloff = json_long (dat, tokens); |
3674 | 0 | uint32_t offset = json_long (dat, tokens); |
3675 | 0 | tokens->index++; |
3676 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3677 | 0 | } |
3678 | 0 | } |
3679 | 0 | return 0; |
3680 | 0 | } |
3681 | | |
3682 | | static int |
3683 | | json_THUMBNAILIMAGE (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
3684 | | jsmntokens_t *restrict tokens) |
3685 | 0 | { |
3686 | 0 | const char *section = "THUMBNAILIMAGE"; |
3687 | 0 | const jsmntok_t *restrict t = &tokens->tokens[tokens->index]; |
3688 | 0 | Dwg_Chain *restrict _obj = &dwg->thumbnail; |
3689 | 0 | int size; |
3690 | 0 | uint32_t size1 = 0; |
3691 | 0 | if (t->type != JSMN_OBJECT) |
3692 | 0 | { |
3693 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
3694 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
3695 | 0 | section); |
3696 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3697 | 0 | return DWG_ERR_INVALIDTYPE; |
3698 | 0 | } |
3699 | 0 | size = t->size; |
3700 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
3701 | 0 | tokens->index, size); |
3702 | 0 | tokens->index++; |
3703 | 0 | for (int i = 0; i < size; i++) |
3704 | 0 | { |
3705 | 0 | char key[80]; |
3706 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3707 | 0 | json_fixed_key (key, dat, tokens); |
3708 | 0 | t = &tokens->tokens[tokens->index]; |
3709 | 0 | if (strEQc (key, "size")) |
3710 | 0 | size1 = json_long (dat, tokens); |
3711 | 0 | else if (strEQc (key, "chain")) |
3712 | 0 | { |
3713 | 0 | size_t len; |
3714 | 0 | dwg->thumbnail.chain = json_binary (dat, tokens, key, &len); |
3715 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3716 | 0 | dwg->thumbnail.size = len; |
3717 | 0 | if (size1 > 0 && size1 != (uint32_t)len) |
3718 | 0 | LOG_WARN ("thumbnail size mismatch: binary len %" PRIuSIZE |
3719 | 0 | " != size " FORMAT_BL, |
3720 | 0 | len, size1); |
3721 | 0 | LOG_TRACE ("size: %" PRIuSIZE "\n", len); |
3722 | 0 | } |
3723 | 0 | else |
3724 | 0 | { |
3725 | 0 | LOG_TRACE ("%s\n", key) |
3726 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3727 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3728 | 0 | } |
3729 | 0 | } |
3730 | | |
3731 | 0 | LOG_TRACE ("End of %s\n", section) |
3732 | 0 | tokens->index--; |
3733 | 0 | return 0; |
3734 | 0 | } |
3735 | | |
3736 | | static int |
3737 | | json_R2007_Header (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
3738 | | jsmntokens_t *restrict tokens) |
3739 | 0 | { |
3740 | 0 | const char *section = "R2007_Header"; |
3741 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
3742 | 0 | Dwg_R2007_Header *_obj = &dwg->fhdr.r2007_file_header; |
3743 | 0 | int size; |
3744 | 0 | if (t->type != JSMN_OBJECT) |
3745 | 0 | { |
3746 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
3747 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
3748 | 0 | section); |
3749 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3750 | 0 | return DWG_ERR_INVALIDTYPE; |
3751 | 0 | } |
3752 | 0 | size = t->size; |
3753 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
3754 | 0 | tokens->index, size); |
3755 | 0 | tokens->index++; |
3756 | 0 | for (int i = 0; i < size; i++) |
3757 | 0 | { |
3758 | 0 | char key[80]; |
3759 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3760 | 0 | json_fixed_key (key, dat, tokens); |
3761 | 0 | t = &tokens->tokens[tokens->index]; |
3762 | | |
3763 | | // clang-format off |
3764 | 0 | if (0) ; |
3765 | 0 | FIELD_RLL (header_size, 0) |
3766 | 0 | FIELD_RLL (file_size, 0) |
3767 | 0 | FIELD_RLL (pages_map_crc_compressed, 0) |
3768 | 0 | FIELD_RLL (pages_map_correction, 0) |
3769 | 0 | FIELD_RLL (pages_map_crc_seed, 0) |
3770 | 0 | FIELD_RLL (pages_map2_offset, 0) |
3771 | 0 | FIELD_RLL (pages_map2_id, 0) |
3772 | 0 | FIELD_RLL (pages_map_offset, 0) |
3773 | 0 | FIELD_RLL (pages_map_id, 0) |
3774 | 0 | FIELD_RLL (header2_offset, 0) |
3775 | 0 | FIELD_RLL (pages_map_size_comp, 0) |
3776 | 0 | FIELD_RLL (pages_map_size_uncomp, 0) |
3777 | 0 | FIELD_RLL (pages_amount, 0) |
3778 | 0 | FIELD_RLL (pages_maxid, 0) |
3779 | 0 | FIELD_RLL (unknown1, 0) |
3780 | 0 | FIELD_RLL (unknown2, 0) |
3781 | 0 | FIELD_RLL (pages_map_crc_uncomp, 0) |
3782 | 0 | FIELD_RLL (unknown3, 0) |
3783 | 0 | FIELD_RLL (unknown4, 0) |
3784 | 0 | FIELD_RLL (unknown5, 0) |
3785 | 0 | FIELD_RLL (num_sections, 0) |
3786 | 0 | FIELD_RLL (sections_map_crc_uncomp, 0) |
3787 | 0 | FIELD_RLL (sections_map_size_comp, 0) |
3788 | 0 | FIELD_RLL (sections_map2_id, 0) |
3789 | 0 | FIELD_RLL (sections_map_id, 0) |
3790 | 0 | FIELD_RLL (sections_map_size_uncomp, 0) |
3791 | 0 | FIELD_RLL (sections_map_crc_comp, 0) |
3792 | 0 | FIELD_RLL (sections_map_correction, 0) |
3793 | 0 | FIELD_RLL (sections_map_crc_seed, 0) |
3794 | 0 | FIELD_RLL (stream_version, 0) |
3795 | 0 | FIELD_RLL (crc_seed, 0) |
3796 | 0 | FIELD_RLL (crc_seed_encoded, 0) |
3797 | 0 | FIELD_RLL (random_seed, 0) |
3798 | 0 | FIELD_RLL (header_crc, 0) |
3799 | | // clang-format on |
3800 | | // end of encrypted header |
3801 | 0 | else |
3802 | 0 | { |
3803 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
3804 | 0 | tokens->index++; |
3805 | 0 | } |
3806 | 0 | } |
3807 | | |
3808 | 0 | LOG_TRACE ("End of %s\n", section) |
3809 | 0 | tokens->index--; |
3810 | 0 | return 0; |
3811 | 0 | } |
3812 | | |
3813 | | static int |
3814 | | json_R2004_Header (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
3815 | | jsmntokens_t *restrict tokens) |
3816 | 0 | { |
3817 | 0 | const char *section = "R2004_Header"; |
3818 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
3819 | 0 | Dwg_R2004_Header *_obj = &dwg->fhdr.r2004_header; |
3820 | 0 | int size; |
3821 | 0 | if (t->type != JSMN_OBJECT) |
3822 | 0 | { |
3823 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
3824 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
3825 | 0 | section); |
3826 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3827 | 0 | return DWG_ERR_INVALIDTYPE; |
3828 | 0 | } |
3829 | 0 | size = t->size; |
3830 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
3831 | 0 | tokens->index, size); |
3832 | 0 | tokens->index++; |
3833 | 0 | for (int i = 0; i < size; i++) |
3834 | 0 | { |
3835 | 0 | char key[80]; |
3836 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3837 | 0 | json_fixed_key (key, dat, tokens); |
3838 | 0 | t = &tokens->tokens[tokens->index]; |
3839 | | |
3840 | | // FIELD_TFFx (file_ID_string, 12, 0) //pre-allocated |
3841 | 0 | if (strEQc (key, "file_ID_string")) |
3842 | 0 | { |
3843 | 0 | char *s = json_fixed_string (dat, 11, tokens); |
3844 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3845 | 0 | if (s) |
3846 | 0 | memcpy (&_obj->file_ID_string, s, 12); |
3847 | 0 | else |
3848 | 0 | { |
3849 | 0 | LOG_ERROR ("Invalid R2004_Header.file_ID_string") |
3850 | 0 | memcpy (&_obj->file_ID_string, "AcFssFcAJMB\0", 12); |
3851 | 0 | } |
3852 | 0 | LOG_TRACE ("file_ID_string: \"%.*s\"\n", 12, _obj->file_ID_string) |
3853 | 0 | free (s); |
3854 | 0 | s = NULL; |
3855 | 0 | } |
3856 | 0 | else if (strEQc (key, "padding")) |
3857 | 0 | { |
3858 | | // just zeros encrypted */ |
3859 | 0 | LOG_TRACE ("padding: \"%.*s\" (ignored)\n", t->end - t->start, |
3860 | 0 | &dat->chain[t->start]) |
3861 | 0 | tokens->index++; |
3862 | 0 | } |
3863 | | // clang-format off |
3864 | 0 | FIELD_RLx (header_address, 0) |
3865 | 0 | FIELD_RL (header_size, 0) |
3866 | 0 | FIELD_RL (x04, 0) |
3867 | 0 | FIELD_RLd (root_tree_node_gap, 0) |
3868 | 0 | FIELD_RLd (lowermost_left_tree_node_gap, 0) |
3869 | 0 | FIELD_RLd (lowermost_right_tree_node_gap, 0) |
3870 | 0 | FIELD_RL (unknown_long, 0) |
3871 | 0 | FIELD_RL (last_section_id, 0) |
3872 | 0 | FIELD_RLL (last_section_address, 0) |
3873 | 0 | FIELD_RLL (secondheader_address, 0) |
3874 | 0 | FIELD_RL (numgaps, 0) |
3875 | 0 | FIELD_RL (numsections, 0) |
3876 | 0 | FIELD_RL (x20, 0) |
3877 | 0 | FIELD_RL (x80, 0) |
3878 | 0 | FIELD_RL (x40, 0) |
3879 | 0 | FIELD_RL (section_map_id, 0) |
3880 | 0 | FIELD_RLL (section_map_address, 0) |
3881 | 0 | FIELD_RL (section_info_id, 0) |
3882 | 0 | FIELD_RL (section_array_size, 0) |
3883 | 0 | FIELD_RL (gap_array_size, 0) |
3884 | 0 | FIELD_RLx (crc32, 0) |
3885 | | // clang-format on |
3886 | | // end of encrypted 0x6c header |
3887 | 0 | else |
3888 | 0 | { |
3889 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
3890 | 0 | tokens->index++; |
3891 | 0 | } |
3892 | 0 | } |
3893 | | |
3894 | 0 | LOG_TRACE ("End of %s\n", section) |
3895 | 0 | tokens->index--; |
3896 | 0 | return 0; |
3897 | 0 | } |
3898 | | |
3899 | | static int |
3900 | | json_AuxHeader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
3901 | | jsmntokens_t *restrict tokens) |
3902 | 0 | { |
3903 | 0 | const char *section = "AuxHeader"; |
3904 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
3905 | 0 | Dwg_AuxHeader *_obj = &dwg->auxheader; |
3906 | 0 | int size; |
3907 | 0 | if (t->type != JSMN_OBJECT) |
3908 | 0 | { |
3909 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
3910 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
3911 | 0 | section); |
3912 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3913 | 0 | return DWG_ERR_INVALIDTYPE; |
3914 | 0 | } |
3915 | 0 | size = t->size; |
3916 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
3917 | 0 | tokens->index, size); |
3918 | 0 | tokens->index++; |
3919 | 0 | for (int i = 0; i < size; i++) |
3920 | 0 | { |
3921 | 0 | char key[80]; |
3922 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3923 | 0 | json_fixed_key (key, dat, tokens); |
3924 | 0 | t = &tokens->tokens[tokens->index]; |
3925 | | |
3926 | | // clang-format off |
3927 | 0 | if (0) ; // else |
3928 | 0 | FIELD_VECTOR_INL (aux_intro, RC, 3, 0) |
3929 | 0 | FIELD_RSx (dwg_version, 0) |
3930 | 0 | FIELD_RL (maint_version, 0) |
3931 | 0 | FIELD_RL (numsaves, 0) |
3932 | 0 | FIELD_RL (minus_1, 0) |
3933 | 0 | FIELD_RS (numsaves_1, 0) |
3934 | 0 | FIELD_RS (numsaves_2, 0) |
3935 | 0 | FIELD_RL (zero, 0) |
3936 | 0 | FIELD_RSx (dwg_version_1, 0) |
3937 | 0 | FIELD_RL (maint_version_1, 0) |
3938 | 0 | FIELD_RSx (dwg_version_2, 0) |
3939 | 0 | FIELD_RL (maint_version_2, 0) |
3940 | 0 | FIELD_VECTOR_INL (unknown_6rs, RS, 6, 0) |
3941 | 0 | FIELD_VECTOR_INL (unknown_5rl, RL, 5, 0) |
3942 | 0 | FIELD_TIMERLL (TDCREATE, 0) |
3943 | 0 | FIELD_TIMERLL (TDUPDATE, 0) |
3944 | 0 | FIELD_HV (HANDSEED, 0) |
3945 | 0 | FIELD_RL (plot_stamp, 0) |
3946 | 0 | FIELD_RS (zero_1, 0) |
3947 | 0 | FIELD_RS (numsaves_3, 0) |
3948 | 0 | FIELD_RL (zero_2, 0) |
3949 | 0 | FIELD_RL (zero_3, 0) |
3950 | 0 | FIELD_RL (zero_4, 0) |
3951 | 0 | FIELD_RL (numsaves_4, 0) |
3952 | 0 | FIELD_RL (zero_5, 0) |
3953 | 0 | FIELD_RL (zero_6, 0) |
3954 | 0 | FIELD_RL (zero_7, 0) |
3955 | 0 | FIELD_RL (zero_8, 0) |
3956 | 0 | FIELD_VECTOR_INL (zero_18, RS, 3, 0) |
3957 | | // clang-format on |
3958 | 0 | else |
3959 | 0 | { |
3960 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
3961 | 0 | tokens->index++; |
3962 | 0 | } |
3963 | 0 | } |
3964 | | |
3965 | 0 | LOG_TRACE ("End of %s\n", section) |
3966 | 0 | tokens->index--; |
3967 | 0 | return 0; |
3968 | 0 | } |
3969 | | |
3970 | | static int |
3971 | | json_SecondHeader_Sections (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
3972 | | jsmntokens_t *restrict tokens, |
3973 | | Dwg_SecondHeader *_obj, int size) |
3974 | 0 | { |
3975 | 0 | const char *section = "SecondHeader_Sections"; |
3976 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
3977 | 0 | if (t->type != JSMN_ARRAY) |
3978 | 0 | { |
3979 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s ARRAY", |
3980 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
3981 | 0 | section); |
3982 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
3983 | 0 | return DWG_ERR_INVALIDTYPE; |
3984 | 0 | } |
3985 | 0 | _obj->num_sections = MIN (size, 6); |
3986 | 0 | LOG_TRACE ("%s: %d\n", section, _obj->num_sections); |
3987 | 0 | for (int j = 0; j < _obj->num_sections; j++) |
3988 | 0 | { |
3989 | 0 | int keys; |
3990 | 0 | tokens->index++; |
3991 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
3992 | 0 | t = &tokens->tokens[tokens->index]; |
3993 | 0 | keys = t->size; |
3994 | 0 | if (t->type != JSMN_OBJECT) |
3995 | 0 | { |
3996 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
3997 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
3998 | 0 | section); |
3999 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4000 | 0 | return DWG_ERR_INVALIDTYPE; |
4001 | 0 | } |
4002 | 0 | assert (t->type == JSMN_OBJECT); |
4003 | 0 | tokens->index++; |
4004 | 0 | for (int k = 0; k < MIN (keys, 3); k++) |
4005 | 0 | { |
4006 | 0 | char key[80]; |
4007 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4008 | 0 | json_fixed_key (key, dat, tokens); |
4009 | 0 | t = &tokens->tokens[tokens->index]; |
4010 | | // clang-format off |
4011 | 0 | if (0) ; // else |
4012 | 0 | SUB_FIELD_LONG (sections[j], nr, RCd) |
4013 | 0 | SUB_FIELD_LONG (sections[j], address, BLx) |
4014 | 0 | SUB_FIELD_LONG (sections[j], size, BL) |
4015 | 0 | else |
4016 | 0 | { |
4017 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4018 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4019 | 0 | } |
4020 | | // clang-format on |
4021 | 0 | } |
4022 | 0 | tokens->index--; |
4023 | 0 | } |
4024 | 0 | tokens->index++; |
4025 | 0 | return 0; |
4026 | 0 | } |
4027 | | |
4028 | | static int |
4029 | | json_SecondHeader_Handles (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4030 | | jsmntokens_t *restrict tokens, |
4031 | | Dwg_SecondHeader *_obj, int size) |
4032 | 0 | { |
4033 | 0 | const char *section = "SecondHeader_Handles"; |
4034 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4035 | 0 | if (t->type != JSMN_ARRAY) |
4036 | 0 | { |
4037 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s ARRAY", |
4038 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4039 | 0 | section); |
4040 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4041 | 0 | return DWG_ERR_INVALIDTYPE; |
4042 | 0 | } |
4043 | 0 | _obj->num_handles = MIN (size, 14); |
4044 | 0 | LOG_TRACE ("%s: %d\n", section, _obj->num_handles); |
4045 | 0 | for (int j = 0; j < _obj->num_handles; j++) |
4046 | 0 | { |
4047 | 0 | int keys; |
4048 | 0 | tokens->index++; |
4049 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4050 | 0 | t = &tokens->tokens[tokens->index]; |
4051 | 0 | keys = t->size; |
4052 | 0 | if (t->type != JSMN_OBJECT) |
4053 | 0 | { |
4054 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4055 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4056 | 0 | section); |
4057 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4058 | 0 | return DWG_ERR_INVALIDTYPE; |
4059 | 0 | } |
4060 | 0 | assert (t->type == JSMN_OBJECT); |
4061 | 0 | tokens->index++; |
4062 | 0 | for (int k = 0; k < MIN (keys, 3); k++) |
4063 | 0 | { |
4064 | 0 | char key[80]; |
4065 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4066 | 0 | json_fixed_key (key, dat, tokens); |
4067 | 0 | t = &tokens->tokens[tokens->index]; |
4068 | | // clang-format off |
4069 | 0 | if (0) ; // else |
4070 | 0 | SUB_FIELD_LONG (handles[j], num_hdl, RCd) // disabled |
4071 | 0 | SUB_FIELD_LONG (handles[j], nr, RCd) |
4072 | | // SUB_FIELD_VECTOR_INL (handles[j], hdl, RC, num_hdl, 0) |
4073 | 0 | else if (strEQc (key, "hdl") && t->type == JSMN_ARRAY) |
4074 | 0 | { |
4075 | 0 | tokens->index++; |
4076 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4077 | 0 | if (t->size < 8) |
4078 | 0 | _obj->handles[j].num_hdl = t->size; |
4079 | 0 | for (int vcount = 0; vcount < t->size; vcount++) |
4080 | 0 | { |
4081 | 0 | if (vcount >= 8) |
4082 | 0 | { |
4083 | 0 | tokens->index++; |
4084 | 0 | continue; |
4085 | 0 | } |
4086 | 0 | _obj->handles[j].hdl[vcount] = |
4087 | 0 | (BITCODE_RC)json_long (dat, tokens) & 0xFF; |
4088 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4089 | 0 | LOG_TRACE ("hdl[%d]: " FORMAT_RC " [RC %d]\n", vcount, |
4090 | 0 | _obj->handles[j].hdl[vcount], 0); |
4091 | 0 | } |
4092 | 0 | } |
4093 | 0 | else |
4094 | 0 | { |
4095 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4096 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4097 | 0 | } |
4098 | | // clang-format on |
4099 | 0 | } |
4100 | 0 | tokens->index--; |
4101 | 0 | } |
4102 | 0 | tokens->index++; |
4103 | 0 | return 0; |
4104 | 0 | } |
4105 | | |
4106 | | static int |
4107 | | json_SecondHeader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4108 | | jsmntokens_t *restrict tokens) |
4109 | 1 | { |
4110 | 1 | const char *section = "SecondHeader"; |
4111 | 1 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4112 | 1 | Dwg_SecondHeader *_obj = &dwg->secondheader; |
4113 | 1 | int size, size1, error = 0; |
4114 | 1 | if (t->type != JSMN_OBJECT) |
4115 | 0 | { |
4116 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4117 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4118 | 0 | section); |
4119 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4120 | 0 | return DWG_ERR_INVALIDTYPE; |
4121 | 0 | } |
4122 | 1 | size = t->size; |
4123 | 1 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
4124 | 1 | tokens->index, size); |
4125 | 1 | tokens->index++; |
4126 | 4.12k | for (int i = 0; i < size; i++) |
4127 | 4.12k | { |
4128 | 4.12k | char key[80]; |
4129 | 4.12k | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4130 | 4.12k | json_fixed_key (key, dat, tokens); |
4131 | 4.12k | t = &tokens->tokens[tokens->index]; |
4132 | | |
4133 | 4.12k | if (strEQc (key, "handles")) |
4134 | 0 | { |
4135 | 0 | if (t->type != JSMN_ARRAY) // of OBJECTs |
4136 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4137 | 0 | else if (t->size) |
4138 | 0 | error |
4139 | 0 | |= json_SecondHeader_Handles (dat, dwg, tokens, _obj, t->size); |
4140 | 0 | else |
4141 | 0 | tokens->index++; // empty array |
4142 | 0 | if (error >= DWG_ERR_CRITICAL) |
4143 | 0 | return error; |
4144 | 0 | } |
4145 | 4.12k | else if (strEQc (key, "sections")) |
4146 | 376 | { |
4147 | 376 | if (t->type != JSMN_ARRAY) // of OBJECTs |
4148 | 376 | json_advance_unknown (dat, tokens, t->type, 0); |
4149 | 0 | else if (t->size) |
4150 | 0 | error |= json_SecondHeader_Sections (dat, dwg, tokens, _obj, |
4151 | 0 | t->size); |
4152 | 0 | else |
4153 | 0 | tokens->index++; // empty array |
4154 | 376 | if (error >= DWG_ERR_CRITICAL) |
4155 | 0 | return error; |
4156 | 376 | } |
4157 | | // clang-format off |
4158 | 3.75k | FIELD_RL (size, 0) |
4159 | 3.75k | FIELD_RL (address, 0) |
4160 | 3.75k | FIELD_TFF (version, 11, 0) |
4161 | 3.75k | FIELD_RC (is_maint, 0) |
4162 | 3.75k | FIELD_RC (zero_one_or_three, 0) |
4163 | 3.75k | FIELD_BS (dwg_versions, 0) |
4164 | 3.75k | FIELD_RS (codepage, 0) |
4165 | 3.75k | FIELD_BS (num_sections, 0) |
4166 | 3.75k | FIELD_BS (num_handles, 0) |
4167 | 3.75k | FIELD_RLL (junk_r14, 0) |
4168 | 3.75k | FIELD_RS (crc, 0) |
4169 | | // clang-format on |
4170 | 3.75k | else |
4171 | 3.75k | { |
4172 | 3.75k | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4173 | 3.75k | tokens->index++; |
4174 | 3.75k | } |
4175 | 4.12k | } |
4176 | | |
4177 | 0 | LOG_TRACE ("End of %s\n", section) |
4178 | 0 | tokens->index--; |
4179 | 0 | return error; |
4180 | 1 | } |
4181 | | |
4182 | | static int |
4183 | | json_SummaryInfo (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4184 | | jsmntokens_t *restrict tokens) |
4185 | 0 | { |
4186 | 0 | const char *section = "SummaryInfo"; |
4187 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4188 | 0 | Dwg_SummaryInfo *_obj = &dwg->summaryinfo; |
4189 | 0 | int size; |
4190 | 0 | if (t->type != JSMN_OBJECT) |
4191 | 0 | { |
4192 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4193 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4194 | 0 | section); |
4195 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4196 | 0 | return DWG_ERR_INVALIDTYPE; |
4197 | 0 | } |
4198 | 0 | size = t->size; |
4199 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
4200 | 0 | tokens->index, size); |
4201 | 0 | tokens->index++; |
4202 | 0 | for (int i = 0; i < size; i++) |
4203 | 0 | { |
4204 | 0 | int size1; |
4205 | 0 | char key[80]; |
4206 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4207 | 0 | json_fixed_key (key, dat, tokens); |
4208 | 0 | t = &tokens->tokens[tokens->index]; |
4209 | |
|
4210 | 0 | if (strEQc (key, "num_props")) |
4211 | 0 | { |
4212 | 0 | if (t->type == JSMN_PRIMITIVE) |
4213 | 0 | tokens->index++; |
4214 | 0 | else |
4215 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4216 | 0 | } |
4217 | 0 | else if (strEQc (key, "props")) |
4218 | 0 | { |
4219 | 0 | if (t->type != JSMN_ARRAY) |
4220 | 0 | { |
4221 | 0 | LOG_ERROR ( |
4222 | 0 | "Unexpected %s at %u of %ld tokens, expected %s.%s ARRAY", |
4223 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4224 | 0 | section, key); |
4225 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4226 | 0 | return DWG_ERR_INVALIDTYPE; |
4227 | 0 | } |
4228 | 0 | size1 = t->size; |
4229 | 0 | LOG_TRACE ("\n%s pos:%d [%d members]\n--------------------\n", |
4230 | 0 | "SummaryInfo_Property", tokens->index, size); |
4231 | 0 | _obj->props = (Dwg_SummaryInfo_Property *)calloc ( |
4232 | 0 | size1, sizeof (Dwg_SummaryInfo_Property)); |
4233 | 0 | _obj->num_props = size1; |
4234 | 0 | tokens->index++; |
4235 | 0 | for (int j = 0; j < size1; j++) |
4236 | 0 | { |
4237 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4238 | 0 | t = &tokens->tokens[tokens->index]; |
4239 | 0 | if (t->type != JSMN_OBJECT) |
4240 | 0 | { |
4241 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected " |
4242 | 0 | "%s.%s OBJECT", |
4243 | 0 | t_typename[t->type], tokens->index, |
4244 | 0 | tokens->num_tokens, section, key); |
4245 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4246 | 0 | return DWG_ERR_INVALIDTYPE; |
4247 | 0 | } |
4248 | 0 | tokens->index++; // OBJECT of 2: tag, value. TODO: array of 2 |
4249 | 0 | json_fixed_key (key, dat, tokens); |
4250 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4251 | 0 | t = &tokens->tokens[tokens->index]; |
4252 | 0 | if (t->type == JSMN_STRING) // CUSTOMPROPERTYTAG |
4253 | 0 | { |
4254 | 0 | _obj->props[j].tag = json_string (dat, tokens); |
4255 | 0 | LOG_TRACE ("props[%d] = (%.*s", j, t->end - t->start, |
4256 | 0 | &dat->chain[t->start]) |
4257 | 0 | } |
4258 | 0 | else if (t->type == JSMN_PRIMITIVE) |
4259 | 0 | tokens->index++; |
4260 | 0 | else |
4261 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4262 | |
|
4263 | 0 | json_fixed_key (key, dat, tokens); |
4264 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4265 | 0 | t = &tokens->tokens[tokens->index]; |
4266 | 0 | if (t->type == JSMN_STRING) // CUSTOMPROPERTY |
4267 | 0 | { |
4268 | 0 | _obj->props[j].value = json_string (dat, tokens); |
4269 | 0 | LOG_TRACE (",%.*s)", t->end - t->start, |
4270 | 0 | &dat->chain[t->start]) |
4271 | 0 | } |
4272 | 0 | else if (t->type == JSMN_PRIMITIVE) |
4273 | 0 | tokens->index++; |
4274 | 0 | else |
4275 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4276 | 0 | LOG_TRACE ("\n") |
4277 | 0 | } |
4278 | 0 | } |
4279 | | // clang-format off |
4280 | 0 | FIELD_T16 (TITLE, 1) |
4281 | 0 | FIELD_T16 (SUBJECT, 1) |
4282 | 0 | FIELD_T16 (AUTHOR, 1) |
4283 | 0 | FIELD_T16 (KEYWORDS, 1) |
4284 | 0 | FIELD_T16 (COMMENTS, 1) |
4285 | 0 | FIELD_T16 (LASTSAVEDBY, 1) |
4286 | 0 | FIELD_T16 (REVISIONNUMBER, 1) |
4287 | 0 | FIELD_T16 (HYPERLINKBASE, 1) |
4288 | 0 | FIELD_TIMERLL (TDINDWG, 0) |
4289 | 0 | FIELD_TIMERLL (TDCREATE, 0) |
4290 | 0 | FIELD_TIMERLL (TDUPDATE, 0) |
4291 | 0 | FIELD_RL (unknown1, 0) |
4292 | 0 | FIELD_RL (unknown2, 0) |
4293 | 0 | else |
4294 | 0 | { |
4295 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4296 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4297 | 0 | } |
4298 | | // clang-format on |
4299 | 0 | } |
4300 | | |
4301 | 0 | LOG_TRACE ("End of %s\n", section) |
4302 | 0 | tokens->index--; |
4303 | 0 | return 0; |
4304 | 0 | } |
4305 | | |
4306 | | static int |
4307 | | json_VBAProject (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4308 | | jsmntokens_t *restrict tokens) |
4309 | 0 | { |
4310 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4311 | 0 | memset (&dwg->vbaproject, 0, sizeof (Dwg_VBAProject)); |
4312 | 0 | LOG_WARN ("Ignore VBAProject"); |
4313 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4314 | 0 | return DWG_ERR_INVALIDTYPE; |
4315 | 0 | } |
4316 | | |
4317 | | static int |
4318 | | json_AppInfo (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4319 | | jsmntokens_t *restrict tokens) |
4320 | 9 | { |
4321 | 9 | const char *section = "AppInfo"; |
4322 | 9 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4323 | 9 | Dwg_AppInfo *_obj = &dwg->appinfo; |
4324 | 9 | int size; |
4325 | 9 | if (t->type != JSMN_OBJECT) |
4326 | 0 | { |
4327 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4328 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4329 | 0 | section); |
4330 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4331 | 0 | return DWG_ERR_INVALIDTYPE; |
4332 | 0 | } |
4333 | 9 | size = t->size; |
4334 | 9 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
4335 | 9 | tokens->index, size); |
4336 | 9 | tokens->index++; |
4337 | 53.4k | for (int i = 0; i < size; i++) |
4338 | 53.3k | { |
4339 | 53.3k | char key[80]; |
4340 | 53.3k | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4341 | 53.3k | json_fixed_key (key, dat, tokens); |
4342 | | // LOG_TRACE ("%s\n", key) |
4343 | 53.3k | t = &tokens->tokens[tokens->index]; |
4344 | | |
4345 | | // clang-format off |
4346 | 53.3k | if (0) ; |
4347 | 53.3k | FIELD_RL (class_version, 0) |
4348 | 53.3k | FIELD_T16 (appinfo_name, 0) |
4349 | 53.3k | FIELD_TFFx (version_checksum, 16, 0) |
4350 | 53.3k | FIELD_T16 (version, 0) |
4351 | 53.3k | FIELD_TFFx (comment_checksum, 16, 0) |
4352 | 51.1k | FIELD_T16 (comment, 0) |
4353 | 51.1k | FIELD_TFFx (product_checksum, 16, 0) |
4354 | 51.1k | FIELD_T16 (product_info, 0) |
4355 | 51.1k | else |
4356 | 51.1k | { |
4357 | 51.1k | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4358 | 51.1k | json_advance_unknown (dat, tokens, t->type, 0); |
4359 | 51.1k | } |
4360 | | // clang-format on |
4361 | 53.3k | } |
4362 | | |
4363 | 8 | _obj->num_strings = 3; |
4364 | 8 | LOG_TRACE ("num_strings => 3\n"); |
4365 | 8 | LOG_TRACE ("End of %s\n", section); |
4366 | 8 | tokens->index--; |
4367 | 8 | return 0; |
4368 | 9 | } |
4369 | | |
4370 | | static int |
4371 | | json_AppInfoHistory (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4372 | | jsmntokens_t *restrict tokens) |
4373 | 0 | { |
4374 | 0 | const char *section = "AppInfoHistory"; |
4375 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4376 | 0 | Dwg_AppInfoHistory *_obj = &dwg->appinfohistory; |
4377 | 0 | int size; |
4378 | 0 | if (t->type != JSMN_OBJECT) |
4379 | 0 | { |
4380 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4381 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4382 | 0 | section); |
4383 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4384 | 0 | return DWG_ERR_INVALIDTYPE; |
4385 | 0 | } |
4386 | 0 | size = t->size; |
4387 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
4388 | 0 | tokens->index, size); |
4389 | 0 | tokens->index++; |
4390 | 0 | for (int i = 0; i < size; i++) |
4391 | 0 | { |
4392 | 0 | char key[80]; |
4393 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4394 | 0 | json_fixed_key (key, dat, tokens); |
4395 | | // LOG_TRACE ("%s\n", key) |
4396 | 0 | t = &tokens->tokens[tokens->index]; |
4397 | | // clang-format off |
4398 | 0 | if (0) ; |
4399 | 0 | FIELD_RL (size, 0) |
4400 | 0 | FIELD_BINARY (unknown_bits, size, 0) |
4401 | 0 | else |
4402 | 0 | { |
4403 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4404 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4405 | 0 | } |
4406 | | // clang-format on |
4407 | 0 | } |
4408 | | |
4409 | 0 | LOG_TRACE ("End of %s\n", section) |
4410 | 0 | tokens->index--; |
4411 | 0 | return 0; |
4412 | 0 | } |
4413 | | |
4414 | | static int |
4415 | | json_FileDepList_Files (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4416 | | jsmntokens_t *restrict tokens, Dwg_FileDepList *o, |
4417 | | int size) |
4418 | 0 | { |
4419 | 0 | const char *section = "FileDepList_Files"; |
4420 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4421 | 0 | if (t->type != JSMN_ARRAY) |
4422 | 0 | { |
4423 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s ARRAY", |
4424 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4425 | 0 | section); |
4426 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4427 | 0 | return DWG_ERR_INVALIDTYPE; |
4428 | 0 | } |
4429 | 0 | o->files |
4430 | 0 | = (Dwg_FileDepList_Files *)calloc (size, sizeof (Dwg_FileDepList_Files)); |
4431 | 0 | o->num_files = size; |
4432 | 0 | for (int j = 0; j < size; j++) |
4433 | 0 | { |
4434 | 0 | int keys; |
4435 | 0 | Dwg_FileDepList_Files *_obj = &o->files[j]; |
4436 | 0 | tokens->index++; |
4437 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4438 | 0 | t = &tokens->tokens[tokens->index]; |
4439 | 0 | keys = t->size; |
4440 | 0 | if (t->type != JSMN_OBJECT) |
4441 | 0 | { |
4442 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4443 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4444 | 0 | section); |
4445 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4446 | 0 | return DWG_ERR_INVALIDTYPE; |
4447 | 0 | } |
4448 | 0 | assert (t->type == JSMN_OBJECT); |
4449 | 0 | tokens->index++; |
4450 | 0 | for (int k = 0; k < keys; k++) |
4451 | 0 | { |
4452 | 0 | char key[80]; |
4453 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4454 | 0 | json_fixed_key (key, dat, tokens); |
4455 | 0 | t = &tokens->tokens[tokens->index]; |
4456 | | // clang-format off |
4457 | 0 | if (0) ; // else |
4458 | 0 | FIELD_T32 (filename, 0) |
4459 | 0 | FIELD_T32 (filepath, 0) |
4460 | 0 | FIELD_T32 (fingerprint, 0) |
4461 | 0 | FIELD_T32 (version, 0) |
4462 | 0 | FIELD_RL (feature_index, 0) |
4463 | 0 | FIELD_RL(timestamp, 0) |
4464 | 0 | FIELD_RL (filesize, 0) |
4465 | 0 | FIELD_RL (affects_graphics, 0) |
4466 | 0 | FIELD_RL (refcount, 0) |
4467 | 0 | else |
4468 | 0 | { |
4469 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4470 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4471 | 0 | } |
4472 | | // clang-format on |
4473 | 0 | } |
4474 | 0 | tokens->index--; |
4475 | 0 | } |
4476 | 0 | tokens->index++; |
4477 | 0 | return 0; |
4478 | 0 | } |
4479 | | |
4480 | | static int |
4481 | | json_FileDepList (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4482 | | jsmntokens_t *restrict tokens) |
4483 | 0 | { |
4484 | 0 | int error = 0; |
4485 | 0 | const char *section = "FileDepList"; |
4486 | 0 | Dwg_FileDepList *_obj = &dwg->filedeplist; |
4487 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4488 | 0 | int size; |
4489 | |
|
4490 | 0 | if (t->type != JSMN_OBJECT) |
4491 | 0 | { |
4492 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4493 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4494 | 0 | section); |
4495 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4496 | 0 | return DWG_ERR_INVALIDTYPE; |
4497 | 0 | } |
4498 | 0 | size = t->size; |
4499 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
4500 | 0 | tokens->index, size); |
4501 | 0 | tokens->index++; |
4502 | 0 | for (int i = 0; i < size; i++) |
4503 | 0 | { |
4504 | 0 | char key[80]; |
4505 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4506 | 0 | json_fixed_key (key, dat, tokens); |
4507 | 0 | LOG_TRACE ("%s\n", key) |
4508 | 0 | t = &tokens->tokens[tokens->index]; |
4509 | 0 | if (strEQc (key, "features")) // TV[] |
4510 | 0 | { |
4511 | 0 | if (t->type != JSMN_ARRAY) |
4512 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4513 | 0 | else |
4514 | 0 | { |
4515 | 0 | int size1 = t->size; |
4516 | 0 | _obj->features |
4517 | 0 | = (BITCODE_TV *)calloc (size1, sizeof (BITCODE_TV)); |
4518 | 0 | _obj->num_features = size1; |
4519 | 0 | tokens->index++; |
4520 | 0 | for (int j = 0; j < size1; j++) |
4521 | 0 | { |
4522 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4523 | 0 | t = &tokens->tokens[tokens->index]; |
4524 | 0 | if (t->type == JSMN_STRING) |
4525 | 0 | { |
4526 | 0 | _obj->features[j] = json_string (dat, tokens); |
4527 | 0 | LOG_TRACE (" %s\n", _obj->features[j]); |
4528 | 0 | } |
4529 | 0 | else if (t->type == JSMN_PRIMITIVE) |
4530 | 0 | tokens->index++; |
4531 | 0 | else |
4532 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4533 | 0 | } |
4534 | 0 | } |
4535 | 0 | } |
4536 | 0 | else if (strEQc (key, "files")) |
4537 | 0 | { |
4538 | 0 | if (t->type != JSMN_ARRAY) // of OBJECTs |
4539 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4540 | 0 | else if (t->size) |
4541 | 0 | error |= json_FileDepList_Files (dat, dwg, tokens, _obj, t->size); |
4542 | 0 | else |
4543 | 0 | tokens->index++; // empty array |
4544 | 0 | if (error >= DWG_ERR_CRITICAL) |
4545 | 0 | return error; |
4546 | 0 | } |
4547 | 0 | else |
4548 | 0 | { |
4549 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4550 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4551 | 0 | } |
4552 | 0 | } |
4553 | | |
4554 | 0 | LOG_TRACE ("End of %s\n", section) |
4555 | 0 | tokens->index--; |
4556 | 0 | return 0; |
4557 | 0 | } |
4558 | | |
4559 | | static int |
4560 | | json_Security (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4561 | | jsmntokens_t *restrict tokens) |
4562 | 0 | { |
4563 | 0 | const char *section = "Security"; |
4564 | 0 | Dwg_Security *_obj = &dwg->security; |
4565 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4566 | 0 | int size; |
4567 | 0 | if (t->type != JSMN_OBJECT) |
4568 | 0 | { |
4569 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4570 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4571 | 0 | section); |
4572 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4573 | 0 | return DWG_ERR_INVALIDTYPE; |
4574 | 0 | } |
4575 | 0 | size = t->size; |
4576 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
4577 | 0 | tokens->index, size); |
4578 | 0 | tokens->index++; |
4579 | 0 | for (int i = 0; i < size; i++) |
4580 | 0 | { |
4581 | 0 | char key[80]; |
4582 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4583 | 0 | json_fixed_key (key, dat, tokens); |
4584 | 0 | t = &tokens->tokens[tokens->index]; |
4585 | | // clang-format off |
4586 | 0 | if (0) ; |
4587 | 0 | FIELD_RLx (unknown_1, 0) |
4588 | 0 | FIELD_RLx (unknown_2, 0) |
4589 | 0 | FIELD_RLx (unknown_3, 0) |
4590 | 0 | FIELD_RL (crypto_id, 0) |
4591 | 0 | FIELD_T32 (crypto_name, 0) |
4592 | 0 | FIELD_RL (algo_id, 0) |
4593 | 0 | FIELD_RL (key_len, 0) |
4594 | 0 | FIELD_RL (encr_size, 0) |
4595 | 0 | FIELD_BINARY (encr_buffer, encr_size, 0) |
4596 | 0 | else |
4597 | 0 | { |
4598 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4599 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4600 | 0 | } |
4601 | | // clang-format on |
4602 | 0 | } |
4603 | | |
4604 | 0 | LOG_TRACE ("End of %s\n", section) |
4605 | 0 | tokens->index--; |
4606 | 0 | return 0; |
4607 | 0 | } |
4608 | | |
4609 | | static int |
4610 | | json_RevHistory (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4611 | | jsmntokens_t *restrict tokens) |
4612 | 0 | { |
4613 | 0 | const char *section = "RevHistory"; |
4614 | 0 | Dwg_RevHistory *_obj = &dwg->revhistory; |
4615 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4616 | 0 | int size; |
4617 | 0 | if (t->type != JSMN_OBJECT) |
4618 | 0 | { |
4619 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4620 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4621 | 0 | section); |
4622 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4623 | 0 | return DWG_ERR_INVALIDTYPE; |
4624 | 0 | } |
4625 | 0 | size = t->size; |
4626 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
4627 | 0 | tokens->index, size); |
4628 | 0 | tokens->index++; |
4629 | 0 | for (int i = 0; i < size; i++) |
4630 | 0 | { |
4631 | 0 | char key[80]; |
4632 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4633 | 0 | json_fixed_key (key, dat, tokens); |
4634 | 0 | t = &tokens->tokens[tokens->index]; |
4635 | | // clang-format off |
4636 | 0 | if (0) ; |
4637 | 0 | FIELD_RL (class_version, 0) |
4638 | 0 | FIELD_RL (class_minor, 0) |
4639 | 0 | FIELD_RL (num_histories, 0) |
4640 | 0 | FIELD_VECTOR (histories, RL, num_histories, 0) |
4641 | 0 | else |
4642 | 0 | { |
4643 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4644 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4645 | 0 | } |
4646 | | // clang-format on |
4647 | 0 | } |
4648 | | |
4649 | 0 | LOG_TRACE ("End of %s\n", section) |
4650 | 0 | tokens->index--; |
4651 | 0 | return 0; |
4652 | 0 | } |
4653 | | |
4654 | | static int |
4655 | | json_ObjFreeSpace (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4656 | | jsmntokens_t *restrict tokens) |
4657 | 3 | { |
4658 | 3 | const char *section = "ObjFreeSpace"; |
4659 | 3 | Dwg_ObjFreeSpace *_obj = &dwg->objfreespace; |
4660 | 3 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4661 | 3 | int size; |
4662 | 3 | if (t->type != JSMN_OBJECT) |
4663 | 0 | { |
4664 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4665 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4666 | 0 | section); |
4667 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4668 | 0 | return DWG_ERR_INVALIDTYPE; |
4669 | 0 | } |
4670 | 3 | size = t->size; |
4671 | 3 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
4672 | 3 | tokens->index, size); |
4673 | 3 | tokens->index++; |
4674 | 5.23k | for (int i = 0; i < size; i++) |
4675 | 5.23k | { |
4676 | 5.23k | char key[80]; |
4677 | 5.23k | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4678 | 5.23k | json_fixed_key (key, dat, tokens); |
4679 | | // t = &tokens->tokens[tokens->index]; |
4680 | | // clang-format off |
4681 | 5.23k | if (0) ; |
4682 | 5.23k | FIELD_RLL (zero, 0) |
4683 | 5.23k | FIELD_RLL (numhandles, 0) |
4684 | 5.23k | FIELD_TIMERLL (TDUPDATE, 0) |
4685 | 5.23k | FIELD_RC (numnums, 0) |
4686 | 5.23k | FIELD_RLL (max32, 0) |
4687 | 5.23k | FIELD_RLL (max32_hi, 0) |
4688 | 4.17k | FIELD_RLL (max64, 0) |
4689 | 4.17k | FIELD_RLL (max64_hi, 0) |
4690 | 4.17k | FIELD_RLL (maxtbl, 0) |
4691 | 4.17k | FIELD_RLL (maxtbl_hi, 0) |
4692 | 4.17k | FIELD_RLL (maxrl, 0) |
4693 | 4.17k | FIELD_RLL (maxrl_hi, 0) |
4694 | 4.17k | FIELD_RL (objects_address, 0) |
4695 | 4.17k | else |
4696 | 4.17k | { |
4697 | 4.17k | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4698 | 4.17k | json_advance_unknown (dat, tokens, t->type, 0); |
4699 | 4.17k | } |
4700 | | // clang-format on |
4701 | 5.23k | } |
4702 | | |
4703 | 3 | LOG_TRACE ("End of %s\n", section) |
4704 | 3 | tokens->index--; |
4705 | 3 | return 0; |
4706 | 3 | } |
4707 | | |
4708 | | static int |
4709 | | json_AcDs_SegmentIndex (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4710 | | jsmntokens_t *restrict tokens, Dwg_AcDs *o, int size) |
4711 | 0 | { |
4712 | 0 | const char *section = "AcDs_SegmentIndex"; |
4713 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4714 | 0 | if (t->type != JSMN_ARRAY) |
4715 | 0 | { |
4716 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s ARRAY", |
4717 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4718 | 0 | section); |
4719 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4720 | 0 | return DWG_ERR_INVALIDTYPE; |
4721 | 0 | } |
4722 | 0 | o->segidx |
4723 | 0 | = (Dwg_AcDs_SegmentIndex *)calloc (size, sizeof (Dwg_AcDs_SegmentIndex)); |
4724 | 0 | o->num_segidx = size; |
4725 | 0 | for (int j = 0; j < size; j++) |
4726 | 0 | { |
4727 | 0 | int keys; |
4728 | 0 | Dwg_AcDs_SegmentIndex *_obj = &o->segidx[j]; |
4729 | 0 | tokens->index++; |
4730 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4731 | 0 | t = &tokens->tokens[tokens->index]; |
4732 | 0 | keys = t->size; |
4733 | 0 | if (t->type != JSMN_OBJECT) |
4734 | 0 | { |
4735 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4736 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4737 | 0 | section); |
4738 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4739 | 0 | return DWG_ERR_INVALIDTYPE; |
4740 | 0 | } |
4741 | 0 | assert (t->type == JSMN_OBJECT); |
4742 | 0 | tokens->index++; |
4743 | 0 | LOG_TRACE ("segidx[%d]:\n", j); |
4744 | 0 | for (int k = 0; k < keys; k++) |
4745 | 0 | { |
4746 | 0 | char key[80]; |
4747 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4748 | 0 | json_fixed_key (key, dat, tokens); |
4749 | 0 | t = &tokens->tokens[tokens->index]; |
4750 | | // clang-format off |
4751 | 0 | if (strEQc (key, "index")) |
4752 | 0 | tokens->index++; // ignore |
4753 | 0 | FIELD_RLL (offset, 0) |
4754 | 0 | FIELD_RL (size, 0) |
4755 | 0 | else |
4756 | 0 | { |
4757 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4758 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4759 | 0 | } |
4760 | | // clang-format on |
4761 | 0 | } |
4762 | 0 | tokens->index--; |
4763 | 0 | } |
4764 | 0 | tokens->index++; |
4765 | 0 | return 0; |
4766 | 0 | } |
4767 | | |
4768 | | static int |
4769 | | json_AcDs_Segments (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4770 | | jsmntokens_t *restrict tokens, Dwg_AcDs *o, int size) |
4771 | 0 | { |
4772 | 0 | const char *section = "AcDs_Segment"; |
4773 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4774 | 0 | if (t->type != JSMN_ARRAY) |
4775 | 0 | { |
4776 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s ARRAY", |
4777 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4778 | 0 | section); |
4779 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4780 | 0 | return DWG_ERR_INVALIDTYPE; |
4781 | 0 | } |
4782 | 0 | o->segments = (Dwg_AcDs_Segment *)calloc (size, sizeof (Dwg_AcDs_Segment)); |
4783 | | // o->num_segidx = size; |
4784 | 0 | for (int j = 0; j < size; j++) |
4785 | 0 | { |
4786 | 0 | int keys; |
4787 | 0 | Dwg_AcDs_Segment *_obj = &o->segments[j]; |
4788 | 0 | tokens->index++; |
4789 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4790 | 0 | t = &tokens->tokens[tokens->index]; |
4791 | 0 | keys = t->size; |
4792 | 0 | if (t->type != JSMN_OBJECT) |
4793 | 0 | { |
4794 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4795 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4796 | 0 | section); |
4797 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4798 | 0 | return DWG_ERR_INVALIDTYPE; |
4799 | 0 | } |
4800 | 0 | assert (t->type == JSMN_OBJECT); |
4801 | 0 | tokens->index++; |
4802 | 0 | LOG_TRACE ("segments[%d]:\n", j); |
4803 | 0 | for (int k = 0; k < keys; k++) |
4804 | 0 | { |
4805 | 0 | char key[80]; |
4806 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4807 | 0 | json_fixed_key (key, dat, tokens); |
4808 | 0 | t = &tokens->tokens[tokens->index]; |
4809 | | // clang-format off |
4810 | 0 | if (strEQc (key, "index")) |
4811 | 0 | tokens->index++; // ignore |
4812 | 0 | FIELD_RLx (signature, 0) |
4813 | 0 | FIELD_TFF (name, 6, 0) |
4814 | 0 | FIELD_RL (type, 0) |
4815 | 0 | FIELD_RL (segment_idx, 0) |
4816 | 0 | FIELD_RL (is_blob01, 0) |
4817 | 0 | FIELD_RL (segsize, 0) |
4818 | 0 | FIELD_RL (unknown_2, 0) |
4819 | 0 | FIELD_RL (ds_version, 0) |
4820 | 0 | FIELD_RL (unknown_3, 0) |
4821 | 0 | FIELD_RL (data_algn_offset, 0) |
4822 | 0 | FIELD_RL (objdata_algn_offset, 0) |
4823 | 0 | FIELD_TFF (padding, 8, 0) |
4824 | 0 | else if (strEQc (key, "datidx.entries")) |
4825 | 0 | { |
4826 | 0 | o->datidx.entries = (Dwg_AcDs_DataIndex_Entry*)json_records (dat, tokens, |
4827 | 0 | o, "AcDs_DataIndex_Entry", &o->datidx.num_entries); |
4828 | 0 | } |
4829 | 0 | else if (strEQc (key, "di_unknown")) |
4830 | 0 | { |
4831 | 0 | o->datidx.di_unknown = json_long (dat, tokens); |
4832 | 0 | LOG_TRACE ("datidx.di_unknown_1: " FORMAT_RL "\n", o->datidx.di_unknown); |
4833 | 0 | } |
4834 | 0 | else if (strEQc (key, "si_unknown_1")) |
4835 | 0 | { |
4836 | 0 | o->schidx.si_unknown_1 = json_long (dat, tokens); |
4837 | 0 | LOG_TRACE ("schidx.unknown_1: " FORMAT_RL "\n", o->schidx.si_unknown_1); |
4838 | 0 | } |
4839 | 0 | else if (strEQc (key, "si_unknown_2")) |
4840 | 0 | { |
4841 | 0 | o->schidx.si_unknown_2 = json_long (dat, tokens); |
4842 | 0 | LOG_TRACE ("schidx.unknown_2: " FORMAT_RL "\n", o->schidx.si_unknown_2); |
4843 | 0 | } |
4844 | 0 | else if (strEQc (key, "si_tag")) |
4845 | 0 | { |
4846 | 0 | o->schidx.si_tag = (BITCODE_RLL)json_longlong (dat, tokens); |
4847 | 0 | LOG_TRACE ("schidx.si_tag: " FORMAT_RLL "\n", o->schidx.si_tag); |
4848 | 0 | } |
4849 | 0 | else if (strEQc (key, "schidx.props")) |
4850 | 0 | { |
4851 | 0 | o->schidx.props = (Dwg_AcDs_SchemaIndex_Prop*)json_records (dat, tokens, |
4852 | 0 | o, "AcDs_SchemaIndex_Prop", &o->schidx.num_props); |
4853 | 0 | } |
4854 | 0 | else if (strEQc (key, "schidx.prop_entries")) |
4855 | 0 | { |
4856 | 0 | o->schidx.prop_entries = (Dwg_AcDs_SchemaIndex_Prop*)json_records (dat, tokens, |
4857 | 0 | o, "AcDs_SchemaIndex_Prop", &o->schidx.num_prop_entries); |
4858 | 0 | } |
4859 | 0 | else if (strEQc (key, "schdat.uprops")) |
4860 | 0 | { |
4861 | 0 | o->schdat.uprops = (Dwg_AcDs_SchemaData_UProp*)json_records (dat, tokens, |
4862 | 0 | o, "AcDs_SchemaData_UProp", &o->schdat.num_uprops); |
4863 | 0 | } |
4864 | 0 | else if (strEQc (key, "schdat.schemas")) |
4865 | 0 | { |
4866 | 0 | o->schdat.schemas = (Dwg_AcDs_Schema*)json_records (dat, tokens, |
4867 | 0 | o, "AcDs_Schema", &o->schdat.num_schemas); |
4868 | 0 | } |
4869 | 0 | else if (strEQc (key, "schdat.propnames")) |
4870 | 0 | { |
4871 | 0 | o->schdat.propnames = (BITCODE_TV*)json_vector (dat, tokens, |
4872 | 0 | key, "TV", &o->schdat.num_propnames); |
4873 | 0 | } |
4874 | 0 | else if (strEQc (key, "search.search")) |
4875 | 0 | { |
4876 | 0 | o->search.search = (Dwg_AcDs_Search_Data*)json_records (dat, tokens, |
4877 | 0 | o, "AcDs_Search_Data", &o->search.num_search); |
4878 | 0 | } |
4879 | | /* |
4880 | | else if (strEQc (key, "schema.index")) |
4881 | | { |
4882 | | o->schdat.schema.index = (BITCODE_RLL*)json_vector (dat, tokens, |
4883 | | o, key, "RLL", &o->schdat.schemas[i].num_index); |
4884 | | } |
4885 | | else if (strEQc (key, "schema.props")) |
4886 | | { |
4887 | | o->schdat.schemas[i].props = (Dwg_AcDs_SchemaIndex_Prop*)json_records (dat, tokens, |
4888 | | o, "AcDs_SchemaIndex_Prop", &o->schdat.schemas[i].num_props); |
4889 | | } |
4890 | | */ |
4891 | | // todo: support more types |
4892 | 0 | else |
4893 | 0 | { |
4894 | 0 | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4895 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4896 | 0 | } |
4897 | | // clang-format on |
4898 | 0 | } |
4899 | 0 | tokens->index--; |
4900 | 0 | } |
4901 | 0 | tokens->index++; |
4902 | 0 | return 0; |
4903 | 0 | } |
4904 | | |
4905 | | static int |
4906 | | json_AcDs (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4907 | | jsmntokens_t *restrict tokens) |
4908 | 4.15k | { |
4909 | 4.15k | const char *section = "AcDs"; |
4910 | 4.15k | Dwg_AcDs *_obj = &dwg->acds; |
4911 | 4.15k | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4912 | 4.15k | int error = 0; |
4913 | 4.15k | int size; |
4914 | 4.15k | if (t->type != JSMN_OBJECT) |
4915 | 0 | { |
4916 | 0 | LOG_ERROR ("Unexpected %s at %u of %ld tokens, expected %s OBJECT", |
4917 | 0 | t_typename[t->type], tokens->index, tokens->num_tokens, |
4918 | 0 | section); |
4919 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4920 | 0 | return DWG_ERR_INVALIDTYPE; |
4921 | 0 | } |
4922 | 4.15k | size = t->size; |
4923 | 4.15k | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
4924 | 4.15k | tokens->index, size); |
4925 | 4.15k | tokens->index++; |
4926 | 8.31k | for (int i = 0; i < size; i++) |
4927 | 4.15k | { |
4928 | 4.15k | char key[80]; |
4929 | 4.15k | JSON_TOKENS_CHECK_OVERFLOW_ERR |
4930 | 4.15k | json_fixed_key (key, dat, tokens); |
4931 | 4.15k | t = &tokens->tokens[tokens->index]; |
4932 | | // clang-format off |
4933 | 4.15k | if (0) ; |
4934 | 4.15k | FIELD_RLx (file_signature, 0) |
4935 | 4.15k | FIELD_RLd (file_header_size, 0) |
4936 | 4.15k | FIELD_RLd (unknown_1, 0) |
4937 | 4.15k | FIELD_RLd (version, 0) |
4938 | 4.15k | FIELD_RLd (unknown_2, 0) |
4939 | 4.15k | FIELD_RLd (ds_version, 0) |
4940 | 4.15k | FIELD_RLd (segidx_offset, 0) |
4941 | 4.15k | FIELD_RLd (segidx_unknown, 0) |
4942 | 4.15k | FIELD_RLd (num_segidx, 0) |
4943 | 4.15k | FIELD_RLd (schidx_segidx, 0) |
4944 | 4.15k | FIELD_RLd (datidx_segidx, 0) |
4945 | 4.15k | FIELD_RLd (search_segidx, 0) |
4946 | 4.15k | FIELD_RLd (prvsav_segidx, 0) |
4947 | 4.15k | FIELD_RL (file_size, 0) |
4948 | | // clang-format on |
4949 | 4.15k | else if (strEQc (key, "segidx")) |
4950 | 0 | { |
4951 | 0 | if (t->type != JSMN_ARRAY) // of OBJECTs |
4952 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4953 | 0 | else if (t->size) |
4954 | 0 | error |= json_AcDs_SegmentIndex (dat, dwg, tokens, _obj, t->size); |
4955 | 0 | else |
4956 | 0 | tokens->index++; // empty array |
4957 | | // if (error >= DWG_ERR_CRITICAL) |
4958 | | // return error; |
4959 | 0 | } |
4960 | 4.15k | else if (strEQc (key, "segments")) |
4961 | 0 | { |
4962 | 0 | if (t->type != JSMN_ARRAY) // of OBJECTs |
4963 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4964 | 0 | else if (t->size) |
4965 | 0 | error |= json_AcDs_Segments (dat, dwg, tokens, _obj, t->size); |
4966 | 0 | else |
4967 | 0 | tokens->index++; // empty array |
4968 | | // if (error >= DWG_ERR_CRITICAL) |
4969 | | // return error; |
4970 | 0 | } |
4971 | 4.15k | else |
4972 | 4.15k | { |
4973 | 4.15k | LOG_ERROR ("Unknown %s.%s ignored", section, key); |
4974 | 4.15k | json_advance_unknown (dat, tokens, t->type, 0); |
4975 | 4.15k | } |
4976 | 4.15k | } |
4977 | | |
4978 | 4.15k | LOG_TRACE ("End of %s\n", section) |
4979 | 4.15k | tokens->index--; |
4980 | 4.15k | return 0; |
4981 | 4.15k | } |
4982 | | |
4983 | | static int |
4984 | | json_Template (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
4985 | | jsmntokens_t *restrict tokens) |
4986 | 0 | { |
4987 | 0 | const char *section = "Template"; |
4988 | 0 | Dwg_Template *_obj = &dwg->Template; |
4989 | 0 | const jsmntok_t *t = &tokens->tokens[tokens->index]; |
4990 | 0 | int size; |
4991 | 0 | if (t->type != JSMN_OBJECT) |
4992 | 0 | { |
4993 | 0 | LOG_ERROR ("Unexpected %s OBJECT at %u of %ld tokens, got %s", section, |
4994 | 0 | tokens->index, tokens->num_tokens, t_typename[t->type]); |
4995 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
4996 | 0 | return DWG_ERR_INVALIDTYPE; |
4997 | 0 | } |
4998 | 0 | size = t->size; |
4999 | 0 | LOG_TRACE ("\n%s pos:%d [%d keys]\n--------------------\n", section, |
5000 | 0 | tokens->index, size); |
5001 | 0 | tokens->index++; |
5002 | 0 | for (int i = 0; i < size; i++) |
5003 | 0 | { |
5004 | 0 | char key[80]; |
5005 | 0 | JSON_TOKENS_CHECK_OVERFLOW_ERR |
5006 | 0 | json_fixed_key (key, dat, tokens); |
5007 | 0 | t = &tokens->tokens[tokens->index]; |
5008 | 0 | if (strEQc (key, "MEASUREMENT")) |
5009 | 0 | { |
5010 | 0 | _obj->MEASUREMENT = (BITCODE_BS)json_long (dat, tokens); |
5011 | 0 | dwg->header_vars.MEASUREMENT = _obj->MEASUREMENT; |
5012 | 0 | LOG_TRACE ("%s: %d\n", key, (int)_obj->MEASUREMENT) |
5013 | 0 | } |
5014 | 0 | FIELD_T (description, 0) |
5015 | 0 | else |
5016 | 0 | { |
5017 | 0 | LOG_TRACE ("%s\n", key); |
5018 | 0 | json_advance_unknown (dat, tokens, t->type, 0); |
5019 | 0 | } |
5020 | 0 | } |
5021 | | |
5022 | 0 | LOG_TRACE ("End of %s\n", section) |
5023 | 0 | tokens->index--; |
5024 | 0 | return 0; |
5025 | 0 | } |
5026 | | |
5027 | | static void |
5028 | | json_free_globals (jsmntokens_t *tokens) |
5029 | 29 | { |
5030 | 29 | if (tokens) |
5031 | 29 | free (tokens->tokens); |
5032 | 29 | free (created_by); |
5033 | 29 | } |
5034 | | |
5035 | | EXPORT int |
5036 | | dwg_read_json (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
5037 | 35 | { |
5038 | 35 | Dwg_Header *obj = &dwg->header; |
5039 | 35 | jsmn_parser parser; |
5040 | 35 | jsmntokens_t tokens; |
5041 | 35 | unsigned int i; |
5042 | 35 | int error = -1; |
5043 | 35 | created_by = NULL; |
5044 | | |
5045 | 35 | dwg->opts |= (loglevel | DWG_OPTS_INJSON); |
5046 | 35 | dat->opts |= (loglevel | DWG_OPTS_INJSON); |
5047 | 35 | loglevel = dwg->opts & 0xf; |
5048 | 35 | if (dat->fh && (!dat->chain || !*dat->chain)) |
5049 | 0 | { |
5050 | 0 | error = dat_read_stream (dat, dat->fh); |
5051 | 0 | if (error >= DWG_ERR_CRITICAL) |
5052 | 0 | return error; |
5053 | 0 | LOG_TRACE (" json file size: %" PRIuSIZE "\n", dat->size); |
5054 | 0 | } |
5055 | 35 | g_dat = dat; |
5056 | | |
5057 | 35 | jsmn_init (&parser); |
5058 | | // How big will it be? This is the max. memory variant. |
5059 | | // we could also use less, see jsmn/examples/jsondump.c for small devices. |
5060 | 35 | tokens.num_tokens |
5061 | 35 | = jsmn_parse (&parser, (char *)dat->chain, dat->size, NULL, 0); |
5062 | 35 | if (tokens.num_tokens <= 0) |
5063 | 6 | { |
5064 | 6 | const long remaining = (long)(dat->size - parser.pos); |
5065 | 6 | if (parser.pos > 10 && remaining > 10) |
5066 | 2 | { |
5067 | 2 | char err[21]; |
5068 | 2 | memcpy (&err, &dat->chain[parser.pos - 10], 20); |
5069 | 2 | err[20] = 0; |
5070 | 2 | LOG_ERROR ("Invalid json. jsmn error at pos: %u (... %s ...)", |
5071 | 2 | parser.pos, err); |
5072 | 2 | } |
5073 | 4 | else |
5074 | 4 | { |
5075 | 4 | LOG_ERROR ("Invalid json. jsmn error at pos: %u (%.*s ...)", |
5076 | 4 | parser.pos, (int)remaining, &dat->chain[parser.pos]); |
5077 | 4 | } |
5078 | 6 | return DWG_ERR_INVALIDDWG; |
5079 | 6 | } |
5080 | 29 | LOG_TRACE (" num_tokens: %ld\n", tokens.num_tokens); |
5081 | 29 | tokens.tokens |
5082 | 29 | = (jsmntok_t *)calloc (tokens.num_tokens + 1024, sizeof (jsmntok_t)); |
5083 | 29 | if (!tokens.tokens) |
5084 | 0 | return DWG_ERR_OUTOFMEM; |
5085 | | |
5086 | 29 | dwg->object_map = hash_new (tokens.num_tokens / 50); |
5087 | 29 | if (!dwg->object_map) // we are obviously on a tiny system |
5088 | 0 | { |
5089 | 0 | dwg->object_map = hash_new (1024); |
5090 | 0 | if (!dwg->object_map) |
5091 | 0 | { |
5092 | 0 | LOG_ERROR ("Out of memory"); |
5093 | 0 | json_free_globals (&tokens); |
5094 | 0 | return DWG_ERR_OUTOFMEM; |
5095 | 0 | } |
5096 | 0 | } |
5097 | 29 | dwg->dirty_refs = 1; |
5098 | | // set the target version earlier (than e.g. in DXF) |
5099 | | // we cannot write DWG >= R_2004 yet. avoid widestrings for now |
5100 | | /* if (!dwg->header.version) |
5101 | | dwg->header.version = dat->version = R_2000; |
5102 | | */ |
5103 | 29 | dat->version = R_2000; |
5104 | | |
5105 | 29 | jsmn_init (&parser); // reset pos to 0 |
5106 | 29 | error = jsmn_parse (&parser, (char *)dat->chain, dat->size, tokens.tokens, |
5107 | 29 | (unsigned int)tokens.num_tokens); |
5108 | 29 | if (error < 0) |
5109 | 7 | { |
5110 | 7 | const long remaining = (long)(dat->size - parser.pos); |
5111 | 7 | if (parser.pos > 10 && remaining > 10) |
5112 | 3 | { |
5113 | 3 | char err[21]; |
5114 | 3 | memcpy (&err, &dat->chain[parser.pos - 10], 20); |
5115 | 3 | err[20] = 0; |
5116 | 3 | LOG_ERROR ("Invalid json. jsmn error %d at the %u-th token, pos: %u " |
5117 | 3 | "(... %s ...)", |
5118 | 3 | error, parser.toknext, parser.pos, err); |
5119 | 3 | } |
5120 | 4 | else |
5121 | 4 | { |
5122 | 4 | LOG_ERROR ("Invalid json. jsmn error %d at the %u-th token, pos: %u " |
5123 | 4 | "(%.*s ...)", |
5124 | 4 | error, parser.toknext, parser.pos, (int)remaining, |
5125 | 4 | &dat->chain[parser.pos]); |
5126 | 4 | } |
5127 | 7 | json_free_globals (&tokens); |
5128 | 7 | return DWG_ERR_INVALIDDWG; |
5129 | 7 | } |
5130 | | |
5131 | 22 | if (tokens.tokens[0].type != JSMN_OBJECT) |
5132 | 0 | { |
5133 | 0 | fprintf (stderr, "First JSON element is not an object/hash\n"); |
5134 | 0 | json_free_globals (&tokens); |
5135 | 0 | return DWG_ERR_INVALIDDWG; |
5136 | 0 | } |
5137 | | |
5138 | | // valid first level tokens: |
5139 | | // created_by: string |
5140 | | // section objects: FILEHEADER, HEADER, THUMBNAILIMAGE, R2004_Header, |
5141 | | // SummaryInfo, AppInfo, |
5142 | | // AppInfoHistory, FileDepList, Security, RevHistory, |
5143 | | // ObjFreeSpace, Template, |
5144 | | // AuxHeader, SecondHeader |
5145 | | // section arrays: CLASSES, OBJECTS, HANDLES |
5146 | 22 | error = 0; |
5147 | 4.19k | for (tokens.index = 1; tokens.index < (unsigned int)tokens.num_tokens; |
5148 | 4.16k | tokens.index++) |
5149 | 4.17k | { |
5150 | 4.17k | char key[80]; |
5151 | 4.17k | const jsmntok_t *t = &tokens.tokens[tokens.index]; |
5152 | 4.17k | const int len = t->end - t->start; |
5153 | | |
5154 | 4.17k | if (t->type == JSMN_UNDEFINED) |
5155 | 0 | break; |
5156 | 4.17k | if (t->type != JSMN_STRING) |
5157 | 1 | { |
5158 | 1 | LOG_ERROR ("Unexpected JSON key at %u of %ld tokens, got %s", |
5159 | 1 | tokens.index, tokens.num_tokens, t_typename[t->type]); |
5160 | 1 | json_free_globals (&tokens); |
5161 | 1 | return DWG_ERR_INVALIDDWG; |
5162 | 1 | } |
5163 | 4.17k | if (len >= 80) |
5164 | 0 | { |
5165 | 0 | LOG_ERROR ("Unknown JSON key at %u of %ld tokens, len %d > 80", |
5166 | 0 | tokens.index, tokens.num_tokens, len); |
5167 | 0 | json_free_globals (&tokens); |
5168 | 0 | return DWG_ERR_INVALIDDWG; |
5169 | 0 | } |
5170 | 4.17k | memcpy (key, &dat->chain[t->start], len); |
5171 | 4.17k | key[len] = '\0'; |
5172 | 4.17k | tokens.index++; |
5173 | 4.17k | if (tokens.index > (unsigned int)tokens.num_tokens) |
5174 | 0 | { |
5175 | 0 | LOG_ERROR ("Unexpected end of JSON at %u of %ld tokens %s:%d", |
5176 | 0 | tokens.index, tokens.num_tokens, __FILE__, __LINE__); |
5177 | 0 | json_free_globals (&tokens); |
5178 | 0 | return DWG_ERR_INVALIDDWG; |
5179 | 0 | } |
5180 | 4.17k | if (strEQc (key, "created_by")) |
5181 | 0 | error |= json_created_by (dat, dwg, &tokens); |
5182 | 4.17k | else if (strEQc (key, "FILEHEADER")) |
5183 | 0 | error |= json_FILEHEADER (dat, dwg, &tokens); |
5184 | 4.17k | else if (strEQc (key, "HEADER")) |
5185 | 1 | error |= json_HEADER (dat, dwg, &tokens); |
5186 | 4.17k | else if (strEQc (key, "CLASSES")) |
5187 | 1 | error |= json_CLASSES (dat, dwg, &tokens); |
5188 | 4.17k | else if (strEQc (key, "OBJECTS")) |
5189 | 2 | error |= json_OBJECTS (dat, dwg, &tokens); |
5190 | 4.17k | else if (strEQc (key, "THUMBNAILIMAGE")) |
5191 | 0 | error |= json_THUMBNAILIMAGE (dat, dwg, &tokens); |
5192 | 4.17k | else if (strEQc (key, "AuxHeader")) |
5193 | 0 | error |= json_AuxHeader (dat, dwg, &tokens); |
5194 | 4.17k | else if (strEQc (key, "SecondHeader")) |
5195 | 1 | error |= json_SecondHeader (dat, dwg, &tokens); |
5196 | 4.17k | else if (strEQc (key, "R2004_Header")) |
5197 | 0 | error |= json_R2004_Header (dat, dwg, &tokens); |
5198 | 4.17k | else if (strEQc (key, "R2007_Header")) |
5199 | 0 | error |= json_R2007_Header (dat, dwg, &tokens); |
5200 | 4.17k | else if (strEQc (key, "SummaryInfo")) |
5201 | 0 | error |= json_SummaryInfo (dat, dwg, &tokens); |
5202 | 4.17k | else if (strEQc (key, "VBAProject")) |
5203 | 0 | error |= json_VBAProject (dat, dwg, &tokens); |
5204 | 4.17k | else if (strEQc (key, "AppInfo")) |
5205 | 9 | error |= json_AppInfo (dat, dwg, &tokens); |
5206 | 4.16k | else if (strEQc (key, "AppInfoHistory")) |
5207 | 0 | error |= json_AppInfoHistory (dat, dwg, &tokens); |
5208 | 4.16k | else if (strEQc (key, "FileDepList")) |
5209 | 0 | error |= json_FileDepList (dat, dwg, &tokens); |
5210 | 4.16k | else if (strEQc (key, "Security")) |
5211 | 0 | error |= json_Security (dat, dwg, &tokens); |
5212 | 4.16k | else if (strEQc (key, "RevHistory")) |
5213 | 0 | error |= json_RevHistory (dat, dwg, &tokens); |
5214 | 4.16k | else if (strEQc (key, "ObjFreeSpace")) |
5215 | 3 | error |= json_ObjFreeSpace (dat, dwg, &tokens); |
5216 | 4.16k | else if (strEQc (key, "AcDs")) |
5217 | 4.15k | error |= json_AcDs (dat, dwg, &tokens); |
5218 | 5 | else if (strEQc (key, "Template")) |
5219 | 0 | error |= json_Template (dat, dwg, &tokens); |
5220 | | /* Only in json early versions <0.11 */ |
5221 | 5 | else if (strEQc (key, "HANDLES")) |
5222 | 0 | error |= json_HANDLES (dat, dwg, &tokens); |
5223 | 5 | else |
5224 | 5 | { |
5225 | 5 | LOG_ERROR ("Unexpected JSON key %s at %u of %ld tokens. %s:%d", key, |
5226 | 5 | tokens.index, tokens.num_tokens, __FUNCTION__, __LINE__); |
5227 | 5 | LOG_TRACE ("\n") |
5228 | 5 | json_free_globals (&tokens); |
5229 | 5 | return error | DWG_ERR_INVALIDTYPE; |
5230 | 5 | } |
5231 | 4.17k | if (error >= DWG_ERR_CRITICAL) |
5232 | 4 | { |
5233 | 4 | LOG_TRACE ("\n") |
5234 | 4 | json_free_globals (&tokens); |
5235 | 4 | return error; |
5236 | 4 | } |
5237 | 4.17k | } |
5238 | | |
5239 | 12 | LOG_TRACE ("\n") |
5240 | 12 | if (dat->version <= R_2000 && dwg->header.from_version > R_2000) |
5241 | 0 | dwg_fixup_BLOCKS_entities (dwg); |
5242 | | |
5243 | 12 | json_free_globals (&tokens); |
5244 | | created_by = NULL; |
5245 | 12 | return error; |
5246 | 22 | } |
5247 | | |
5248 | | #undef IS_ENCODER |
5249 | | #undef IS_JSON |