Coverage Report

Created: 2026-07-15 07:10

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