Coverage Report

Created: 2025-12-01 07:24

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