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