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