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