Coverage Report

Created: 2025-12-01 07:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libredwg/src/out_json.c
Line
Count
Source
1
/*****************************************************************************/
2
/*  LibreDWG - free implementation of the DWG file format                    */
3
/*                                                                           */
4
/*  Copyright (C) 2018-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
 * out_json.c: write as JSON
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 <ctype.h>
24
#include <limits.h>
25
#ifdef HAVE_ICONV
26
#  include <iconv.h>
27
#endif
28
29
#define IS_JSON
30
#include "common.h"
31
#include "codepages.h"
32
#include "bits.h"
33
#include "dwg.h"
34
#include "decode.h"
35
#include "out_json.h"
36
37
0
#define DWG_LOGLEVEL DWG_LOGLEVEL_NONE
38
#include "logging.h"
39
40
/* the current version per spec block */
41
static unsigned int cur_ver = 0;
42
static BITCODE_BL rcount1, rcount2;
43
44
/* see also examples/unknown.c */
45
#ifdef HAVE_NATIVE_WCHAR2
46
static wchar_t *wcquote (wchar_t *restrict dest, const wchar_t *restrict src);
47
#else
48
static void print_wcquote (Bit_Chain *restrict dat,
49
                           dwg_wchar_t *restrict wstr);
50
#endif
51
void json_write_TFv (Bit_Chain *restrict dat, const BITCODE_TF restrict src,
52
                     const size_t len);
53
// write even past the \0, to keep existing slack
54
void json_write_TF (Bit_Chain *restrict dat, const BITCODE_TF restrict src,
55
                    const size_t len);
56
57
static int json_3dsolid (Bit_Chain *restrict dat,
58
                         const Dwg_Object *restrict obj,
59
                         Dwg_Entity_3DSOLID *restrict _obj);
60
static void _prefix (Bit_Chain *dat);
61
static char *_path_field (const char *path);
62
63
/*--------------------------------------------------------------------------------
64
 * MACROS
65
 */
66
67
#define ACTION json
68
69
0
#define ISFIRST (dat->opts & DWG_OPTS_JSONFIRST)
70
0
#define SETFIRST dat->opts |= DWG_OPTS_JSONFIRST
71
0
#define CLEARFIRST dat->opts &= ~DWG_OPTS_JSONFIRST
72
73
0
#define PREFIX _prefix (dat);
74
0
#define IS_MINJS (dat->opts & DWG_OPTS_MINIMAL)
75
#define JSON_SPC IS_MINJS ? "" : " "
76
#define JSON_NL IS_MINJS ? "" : "\n"
77
#define JSON_KEY "\"%s\":%s"
78
79
#define PRINTFIRST                                                            \
80
0
  {                                                                           \
81
0
    if (!ISFIRST)                                                             \
82
0
      fprintf (dat->fh, ",%s", JSON_NL);                                      \
83
0
    else                                                                      \
84
0
      CLEARFIRST;                                                             \
85
0
  }
86
0
#define FIRSTPREFIX PRINTFIRST PREFIX
87
88
0
#define KEYs(nam) FIRSTPREFIX fprintf (dat->fh, "\"%s\":%s", nam, JSON_SPC)
89
// strip path to field only
90
#define KEY(nam)                                                              \
91
0
  FIRSTPREFIX fprintf (dat->fh, "\"%s\":%s", _path_field (#nam), JSON_SPC)
92
93
#define ARRAY                                                                 \
94
0
  {                                                                           \
95
0
    fprintf (dat->fh, "[%s", JSON_NL);                                        \
96
0
    SETFIRST;                                                                 \
97
0
    dat->bit++;                                                               \
98
0
  }
99
#define ENDARRAY                                                              \
100
0
  {                                                                           \
101
0
    fprintf (dat->fh, "%s", JSON_NL);                                         \
102
0
    dat->bit--;                                                               \
103
0
    PREFIX fprintf (dat->fh, "]");                                            \
104
0
    CLEARFIRST;                                                               \
105
0
  }
106
#define HASH                                                                  \
107
0
  {                                                                           \
108
0
    fprintf (dat->fh, "{%s", JSON_NL);                                        \
109
0
    SETFIRST;                                                                 \
110
0
    dat->bit++;                                                               \
111
0
  }
112
#define ENDHASH                                                               \
113
0
  {                                                                           \
114
0
    fprintf (dat->fh, "%s", JSON_NL);                                         \
115
0
    dat->bit--;                                                               \
116
0
    PREFIX fprintf (dat->fh, "}");                                            \
117
0
    CLEARFIRST;                                                               \
118
0
  }
119
120
#define TABLE(nam)                                                            \
121
  KEY (nam);                                                                  \
122
  HASH
123
#define ENDTAB() ENDHASH
124
// a named hash
125
#define RECORD(nam)                                                           \
126
0
  KEY (nam);                                                                  \
127
0
  HASH
128
0
#define ENDRECORD() ENDHASH
129
// a named list
130
#define SECTION(nam)                                                          \
131
0
  KEY (nam);                                                                  \
132
0
  ARRAY
133
0
#define ENDSEC() ENDARRAY
134
135
#undef FORMAT_H
136
#undef FORMAT_RLL
137
#undef FORMAT_BLL
138
#undef FORMAT_RC
139
#undef FORMAT_RSx
140
#undef FORMAT_RLx
141
#undef FORMAT_BLx
142
#undef FORMAT_BLX
143
#undef FORMAT_4BITS
144
#undef FORMAT_RD
145
#undef FORMAT_BD
146
#define FORMAT_RD "%.14f"
147
#define FORMAT_BD FORMAT_RD
148
#define FORMAT_RLL "%" PRIu64
149
#define FORMAT_BLL "%" PRIu64
150
#define FORMAT_HREF "[%u,%u," FORMAT_RLL "," FORMAT_RLL "]"
151
#undef FORMAT_HREF11
152
#define FORMAT_HREF11 "[%u,%hd," FORMAT_RLL "]"
153
#undef ARGS_H
154
#define ARGS_H(hdl) hdl.code, hdl.size, hdl.value
155
#define FORMAT_H "[%u,%u," FORMAT_RLL "]"
156
#define ARGS_HREF(ref)                                                        \
157
  ref->handleref.code, ref->handleref.size, ref->handleref.value,             \
158
      ref->absolute_ref
159
160
#define ARGS_HREF11(ref) ref->handleref.size, ref->r11_idx, ref->absolute_ref
161
#define FORMAT_RC "%d"
162
#define FORMAT_RSx FORMAT_RS
163
#define FORMAT_RLx FORMAT_RL
164
#define FORMAT_BLx FORMAT_BL
165
#define FORMAT_BLX FORMAT_BL
166
#define FORMAT_4BITS FORMAT_RC
167
168
0
#define VALUE(value, type, dxf) fprintf (dat->fh, FORMAT_##type, value)
169
0
#define VALUE_B(value, dxf) VALUE (value, B, dxf)
170
0
#define VALUE_RC(value, dxf) VALUE (value, RC, dxf)
171
0
#define VALUE_RS(value, dxf) VALUE (value, RS, dxf)
172
0
#define VALUE_RSd(value, dxf) VALUE (value, RSd, dxf)
173
0
#define VALUE_RL(value, dxf) VALUE (value, RL, dxf)
174
0
#define VALUE_RLd(value, dxf) VALUE (value, RLd, dxf)
175
0
#define VALUE_RLx(value, dxf) VALUE ((BITCODE_RL)value, RL, dxf)
176
0
#define VALUE_RLL(value, dxf) VALUE (value, RLL, dxf)
177
0
#define VALUE_RLLd(value, dxf) VALUE (value, RLLd, dxf)
178
#ifdef IS_RELEASE
179
#  define VALUE_RD(value, dxf)                                                \
180
0
    if (bit_isnan (value))                                                    \
181
0
      _VALUE_RD (0.0, dxf)                                                    \
182
0
    else                                                                      \
183
0
      _VALUE_RD (value, dxf)
184
#else
185
#  define VALUE_RD(value, dxf) _VALUE_RD (value, dxf)
186
#endif
187
#define _VALUE_RD(value, dxf)                                                 \
188
0
  {                                                                           \
189
0
    char _buf[256];                                                           \
190
0
    size_t k;                                                                 \
191
0
    snprintf (_buf, 255, FORMAT_RD, value);                                   \
192
0
    k = strlen (_buf);                                                        \
193
0
    if (k > 0 && strrchr (_buf, '.') && _buf[k - 1] == '0')                   \
194
0
      {                                                                       \
195
0
        for (k--; k > 1 && _buf[k - 1] != '.' && _buf[k] == '0'; k--)         \
196
0
          _buf[k] = '\0';                                                     \
197
0
      }                                                                       \
198
0
    fprintf (dat->fh, "%s", _buf);                                            \
199
0
  }
200
#define VALUE_2RD(pt, dxf)                                                    \
201
0
  {                                                                           \
202
0
    fprintf (dat->fh, "[%s", JSON_SPC);                                       \
203
0
    VALUE_RD (pt.x, 0);                                                       \
204
0
    fprintf (dat->fh, ",%s", JSON_SPC);                                       \
205
0
    VALUE_RD (pt.y, 0);                                                       \
206
0
    fprintf (dat->fh, "%s]%s", JSON_SPC, JSON_SPC);                           \
207
0
  }
208
#define VALUE_2DD(pt, def, dxf) VALUE_2RD (pt, dxf)
209
#define VALUE_3RD(pt, dxf)                                                    \
210
0
  {                                                                           \
211
0
    fprintf (dat->fh, "[%s", JSON_SPC);                                       \
212
0
    VALUE_RD (pt.x, 0);                                                       \
213
0
    fprintf (dat->fh, ",%s", JSON_SPC);                                       \
214
0
    VALUE_RD (pt.y, 0);                                                       \
215
0
    fprintf (dat->fh, ",%s", JSON_SPC);                                       \
216
0
    VALUE_RD (pt.z, 0);                                                       \
217
0
    fprintf (dat->fh, "%s]%s", JSON_SPC, JSON_SPC);                           \
218
0
  }
219
0
#define VALUE_3BD(pt, dxf) VALUE_3RD (pt, dxf)
220
#define VALUE_TV(nam, dxf)
221
222
#define FIELD(nam, type, dxf)                                                 \
223
0
  if (!memBEGINc (#nam, "num_"))                                              \
224
0
    {                                                                         \
225
0
      FIRSTPREFIX fprintf (dat->fh, JSON_KEY FORMAT_##type,                   \
226
0
                           _path_field (#nam), JSON_SPC, _obj->nam);          \
227
0
    }
228
#define _FIELD(nam, type, value)                                              \
229
0
  {                                                                           \
230
0
    FIRSTPREFIX fprintf (dat->fh, "\"" #nam "\":%s" FORMAT_##type, JSON_SPC,  \
231
0
                         obj->nam);                                           \
232
0
  }
233
#define ENT_FIELD(nam, type, value)                                           \
234
0
  {                                                                           \
235
0
    FIRSTPREFIX fprintf (dat->fh, JSON_KEY FORMAT_##type, _path_field (#nam), \
236
0
                         JSON_SPC, _ent->nam);                                \
237
0
  }
238
#define SUB_FIELD(o, nam, type, dxf)                                          \
239
0
  if (!memBEGINc (#nam, "num_"))                                              \
240
0
    {                                                                         \
241
0
      FIRSTPREFIX fprintf (dat->fh, JSON_KEY FORMAT_##type,                   \
242
0
                           _path_field (#nam), JSON_SPC, _obj->o.nam);        \
243
0
    }
244
0
#define FIELD_CAST(nam, type, cast, dxf) FIELD (nam, cast, dxf)
245
#define SUB_FIELD_CAST(o, nam, type, cast, dxf) SUB_FIELD (o, nam, cast, dxf)
246
#define FIELD_TRACE(nam, type)
247
#define FIELD_G_TRACE(nam, type, dxf)
248
#define FIELD_TEXT(nam, str)                                                  \
249
0
  {                                                                           \
250
0
    FIRSTPREFIX fprintf (dat->fh, JSON_KEY, _path_field (#nam), JSON_SPC);    \
251
0
    VALUE_TEXT ((char *)str)                                                  \
252
0
  }
253
254
// Converts to UTF-8
255
#define VALUE_TEXT(str)                                                       \
256
0
  {                                                                           \
257
0
    if (str)                                                                  \
258
0
      {                                                                       \
259
0
        const size_t len = strlen (str);                                      \
260
0
        if (len < 42)                                                         \
261
0
          {                                                                   \
262
0
            const size_t _len = 6 * len + 1;                                  \
263
0
            char _buf[256];                                                   \
264
0
            fprintf (dat->fh, "\"%s\"",                                       \
265
0
                     json_cquote (_buf, str, _len, dat->codepage));           \
266
0
          }                                                                   \
267
0
        else                                                                  \
268
0
          {                                                                   \
269
0
            const size_t _len = 6 * len + 1;                                  \
270
0
            char *_buf = (char *)malloc (_len);                               \
271
0
            fprintf (dat->fh, "\"%s\"",                                       \
272
0
                     json_cquote (_buf, str, _len, dat->codepage));           \
273
0
            free (_buf);                                                      \
274
0
          }                                                                   \
275
0
      }                                                                       \
276
0
    else                                                                      \
277
0
      {                                                                       \
278
0
        fprintf (dat->fh, "\"%s\"", str ? str : "");                          \
279
0
      }                                                                       \
280
0
  }
281
282
// Converts to UTF-8
283
#ifdef HAVE_NATIVE_WCHAR2
284
#  define VALUE_TEXT_TU(wstr)                                                 \
285
    if (wstr)                                                                 \
286
      {                                                                       \
287
        wchar_t *_buf = malloc (6 * wcslen ((wchar_t *)wstr) + 2);            \
288
        fprintf (dat->fh, "\"%ls\"", wcquote (_buf, (wchar_t *)wstr));        \
289
        free (_buf);                                                          \
290
      }                                                                       \
291
    else                                                                      \
292
      {                                                                       \
293
        fprintf (dat->fh, "\"%ls\"", wstr ? (wchar_t *)wstr : L"");           \
294
      }
295
#else
296
0
#  define VALUE_TEXT_TU(wstr) print_wcquote (dat, (BITCODE_TU)wstr)
297
#endif
298
#define FIELD_TEXT_TU(nam, wstr)                                              \
299
0
  {                                                                           \
300
0
    KEY (nam);                                                                \
301
0
    VALUE_TEXT_TU ((BITCODE_TU)wstr);                                         \
302
0
  }
303
// may be downgraded from TV, thus shorter
304
#define FIELD_TFv(nam, len, dxf)                                              \
305
0
  {                                                                           \
306
0
    FIRSTPREFIX fprintf (dat->fh, JSON_KEY, _path_field (#nam), JSON_SPC);    \
307
0
    json_write_TFv (dat, (const BITCODE_TF)_obj->nam, len);                   \
308
0
  }
309
#define FIELD_TF(nam, len, dxf)                                               \
310
0
  {                                                                           \
311
0
    FIRSTPREFIX fprintf (dat->fh, JSON_KEY, _path_field (#nam), JSON_SPC);    \
312
0
    json_write_TF (dat, (const BITCODE_TF)_obj->nam, len);                    \
313
0
  }
314
0
#define FIELD_TFF(nam, len, dxf) FIELD_TF (nam, len, dxf)
315
316
#define FIELD_VALUE(nam) _obj->nam
317
#define ANYCODE -1
318
// todo: only the name, not the ref
319
#define VALUE_HANDLE(hdlptr, nam, handle_code, dxf)                           \
320
0
  if (hdlptr)                                                                 \
321
0
    {                                                                         \
322
0
      PRE (R_13b1)                                                            \
323
0
      {                                                                       \
324
0
        fprintf (dat->fh, FORMAT_HREF11 "", ARGS_HREF11 (hdlptr));            \
325
0
      }                                                                       \
326
0
      LATER_VERSIONS                                                          \
327
0
      {                                                                       \
328
0
        fprintf (dat->fh, FORMAT_HREF "", ARGS_HREF (hdlptr));                \
329
0
      }                                                                       \
330
0
    }                                                                         \
331
0
  else                                                                        \
332
0
    {                                                                         \
333
0
      fprintf (dat->fh, "[0,0,0]");                                           \
334
0
    }
335
0
#define VALUE_H(hdl, dxf) fprintf (dat->fh, FORMAT_H "", ARGS_H (hdl))
336
#define FIELD_HANDLE(nam, handle_code, dxf)                                   \
337
0
  {                                                                           \
338
0
    if (_obj->nam)                                                            \
339
0
      {                                                                       \
340
0
        PRE (R_13b1)                                                          \
341
0
        {                                                                     \
342
0
          FIRSTPREFIX fprintf (dat->fh, JSON_KEY FORMAT_HREF11 "",            \
343
0
                               _path_field (#nam), JSON_SPC,                  \
344
0
                               ARGS_HREF11 (_obj->nam));                      \
345
0
        }                                                                     \
346
0
        LATER_VERSIONS                                                        \
347
0
        {                                                                     \
348
0
          FIRSTPREFIX fprintf (dat->fh, JSON_KEY FORMAT_HREF "",              \
349
0
                               _path_field (#nam), JSON_SPC,                  \
350
0
                               ARGS_HREF (_obj->nam));                        \
351
0
        }                                                                     \
352
0
      }                                                                       \
353
0
    else                                                                      \
354
0
      {                                                                       \
355
0
        FIRSTPREFIX fprintf (dat->fh, JSON_KEY "[0,%s0]", _path_field (#nam), \
356
0
                             JSON_SPC, JSON_SPC);                             \
357
0
      }                                                                       \
358
0
  }
359
#define SUB_FIELD_HANDLE(o, nam, handle_code, dxf)                            \
360
0
  {                                                                           \
361
0
    if (_obj->o.nam)                                                          \
362
0
      {                                                                       \
363
0
        FIRSTPREFIX fprintf (dat->fh, JSON_KEY FORMAT_HREF "",                \
364
0
                             _path_field (#nam), JSON_SPC,                    \
365
0
                             ARGS_HREF (_obj->o.nam));                        \
366
0
      }                                                                       \
367
0
    else                                                                      \
368
0
      {                                                                       \
369
0
        FIRSTPREFIX fprintf (dat->fh, JSON_KEY "[0,%s0]", _path_field (#nam), \
370
0
                             JSON_SPC, JSON_SPC);                             \
371
0
      }                                                                       \
372
0
  }
373
0
#define FIELD_DATAHANDLE(nam, code, dxf) FIELD_HANDLE (nam, code, dxf)
374
#define FIELD_HANDLE_N(nam, vcount, handle_code, dxf)                         \
375
0
  PRINTFIRST;                                                                 \
376
0
  if (_obj->nam)                                                              \
377
0
    {                                                                         \
378
0
      PRE (R_13b1)                                                            \
379
0
      {                                                                       \
380
0
        PREFIX fprintf (dat->fh, FORMAT_HREF11 "", ARGS_HREF11 (_obj->nam));  \
381
0
      }                                                                       \
382
0
      LATER_VERSIONS                                                          \
383
0
      {                                                                       \
384
0
        PREFIX fprintf (dat->fh, FORMAT_HREF "", ARGS_HREF (_obj->nam));      \
385
0
      }                                                                       \
386
0
    }                                                                         \
387
0
  else                                                                        \
388
0
    {                                                                         \
389
0
      PREFIX fprintf (dat->fh, "[0,%s0]", JSON_SPC);                          \
390
0
    }
391
#define SUB_FIELD_HANDLE_N(o, nam, handle_code, dxf)                          \
392
0
  PRINTFIRST;                                                                 \
393
0
  if (_obj->o.nam)                                                            \
394
0
    {                                                                         \
395
0
      PREFIX fprintf (dat->fh, FORMAT_HREF "", ARGS_HREF (_obj->o.nam));      \
396
0
    }                                                                         \
397
0
  else                                                                        \
398
0
    {                                                                         \
399
0
      PREFIX fprintf (dat->fh, "[0,%s0]", JSON_SPC);                          \
400
0
    }
401
#define VALUE_BINARY(buf, len, dxf)                                           \
402
0
  {                                                                           \
403
0
    fprintf (dat->fh, "\"");                                                  \
404
0
    if (buf && len)                                                           \
405
0
      {                                                                       \
406
0
        for (long _j = 0; _j < (long)len; _j++)                               \
407
0
          {                                                                   \
408
0
            fprintf (dat->fh, "%02X", ((BITCODE_RC *)buf)[_j]);               \
409
0
          }                                                                   \
410
0
      }                                                                       \
411
0
    fprintf (dat->fh, "\"");                                                  \
412
0
  }
413
#define FIELD_BINARY(nam, size, dxf)                                          \
414
0
  {                                                                           \
415
0
    KEY (nam);                                                                \
416
0
    fprintf (dat->fh, "\"");                                                  \
417
0
    if (_obj->nam)                                                            \
418
0
      {                                                                       \
419
0
        for (long _j = 0; _j < (long)size; _j++)                              \
420
0
          {                                                                   \
421
0
            fprintf (dat->fh, "%02X", ((BITCODE_RC *)_obj->nam)[_j]);         \
422
0
          }                                                                   \
423
0
      }                                                                       \
424
0
    fprintf (dat->fh, "\"");                                                  \
425
0
  }
426
427
0
#define FIELD_B(nam, dxf) FIELD (nam, B, dxf)
428
0
#define FIELD_BB(nam, dxf) FIELD (nam, BB, dxf)
429
#define FIELD_3B(nam, dxf) FIELD (nam, 3B, dxf)
430
0
#define FIELD_BS(nam, dxf) FIELD (nam, BS, dxf)
431
0
#define FIELD_BSd(nam, dxf) FIELD (nam, BSd, dxf)
432
0
#define FIELD_BL(nam, dxf) FIELD (nam, BL, dxf)
433
0
#define FIELD_BLd(nam, dxf) FIELD (nam, BLd, dxf)
434
0
#define FIELD_BLL(nam, dxf) FIELD (nam, BLL, dxf)
435
#ifdef IS_RELEASE
436
#  define FIELD_BD(nam, dxf)                                                  \
437
0
    {                                                                         \
438
0
      if (!bit_isnan (_obj->nam))                                             \
439
0
        {                                                                     \
440
0
          FIRSTPREFIX fprintf (dat->fh, JSON_KEY, _path_field (#nam),         \
441
0
                               JSON_SPC);                                     \
442
0
          _VALUE_RD (_obj->nam, dxf);                                         \
443
0
        }                                                                     \
444
0
    }
445
#  define FIELD_2RD(nam, dxf)                                                 \
446
0
    {                                                                         \
447
0
      if (!bit_isnan (_obj->nam.x) && !bit_isnan (_obj->nam.y))               \
448
0
        {                                                                     \
449
0
          FIRSTPREFIX fprintf (dat->fh, "\"" #nam "\":%s", JSON_SPC);         \
450
0
          VALUE_2RD (_obj->nam, dxf);                                         \
451
0
        }                                                                     \
452
0
    }
453
#  define FIELD_3RD(nam, dxf)                                                 \
454
0
    {                                                                         \
455
0
      if (!bit_isnan (_obj->nam.x) && !bit_isnan (_obj->nam.y)                \
456
0
          && !bit_isnan (_obj->nam.z))                                        \
457
0
        {                                                                     \
458
0
          FIRSTPREFIX fprintf (dat->fh, "\"" #nam "\":%s", JSON_SPC);         \
459
0
          VALUE_3RD (_obj->nam, dxf);                                         \
460
0
        }                                                                     \
461
0
    }
462
#  define SUB_FIELD_BD(o, nam, dxf)                                           \
463
0
    {                                                                         \
464
0
      if (!bit_isnan (_obj->o.nam))                                           \
465
0
        {                                                                     \
466
0
          FIRSTPREFIX fprintf (dat->fh, JSON_KEY, _path_field (#nam),         \
467
0
                               JSON_SPC);                                     \
468
0
          _VALUE_RD (_obj->o.nam, dxf);                                       \
469
0
        }                                                                     \
470
0
    }
471
#else /* IS_RELEASE */
472
#  define FIELD_BD(nam, dxf)                                                  \
473
    {                                                                         \
474
      FIRSTPREFIX fprintf (dat->fh, JSON_KEY, _path_field (#nam), JSON_SPC);  \
475
      _VALUE_RD (_obj->nam, dxf);                                             \
476
    }
477
#  define FIELD_2RD(nam, dxf)                                                 \
478
    {                                                                         \
479
      FIRSTPREFIX fprintf (dat->fh, "\"" #nam "\":%s", JSON_SPC);             \
480
      VALUE_2RD (_obj->nam, dxf);                                             \
481
    }
482
#  define FIELD_3RD(nam, dxf)                                                 \
483
    {                                                                         \
484
      FIRSTPREFIX fprintf (dat->fh, "\"" #nam "\":%s", JSON_SPC);             \
485
      VALUE_3RD (_obj->nam, dxf);                                             \
486
    }
487
#  define SUB_FIELD_BD(o, nam, dxf)                                           \
488
    {                                                                         \
489
      FIRSTPREFIX fprintf (dat->fh, JSON_KEY, _path_field (#nam), JSON_SPC);  \
490
      _VALUE_RD (_obj->o.nam, dxf);                                           \
491
    }
492
#endif
493
494
0
#define FIELD_RC(nam, dxf) FIELD (nam, RC, dxf)
495
#define FIELD_RCx(nam, dxf) FIELD (nam, RC, dxf)
496
0
#define FIELD_RS(nam, dxf) FIELD (nam, RS, dxf)
497
0
#define FIELD_RSd(nam, dxf) FIELD (nam, RSd, dxf)
498
0
#define FIELD_RD(nam, dxf) FIELD_BD (nam, dxf)
499
0
#define FIELD_RL(nam, dxf) FIELD (nam, RL, dxf)
500
0
#define FIELD_RLd(nam, dxf) FIELD (nam, RLd, dxf)
501
0
#define FIELD_RLL(nam, dxf) FIELD (nam, RLL, dxf)
502
0
#define FIELD_HV(nam, dxf) FIELD (nam, RLL, dxf)
503
#define FIELD_MC(nam, dxf) FIELD (nam, MC, dxf)
504
#define FIELD_MS(nam, dxf) FIELD (nam, MS, dxf)
505
// #define FIELD_TF(nam, len, dxf) FIELD_TEXT (nam, _obj->nam)
506
// #define FIELD_TFF(nam, len, dxf) FIELD_TEXT (nam, (const char*)_obj->nam)
507
0
#define FIELD_TFFx(nam, len, dxf) FIELD_BINARY (nam, len, dxf)
508
0
#define FIELD_TV(nam, dxf) FIELD_TEXT (nam, _obj->nam)
509
0
#define FIELD_TU(nam, dxf) FIELD_TEXT_TU (nam, (BITCODE_TU)_obj->nam)
510
0
#define FIELD_T16(nam, dxf) FIELD_T (nam, dxf)
511
#define FIELD_TU16(nam, dxf) FIELD_TU (nam, dxf)
512
0
#define FIELD_T32(nam, dxf) FIELD_T (nam, dxf)
513
#define FIELD_T(nam, dxf)                                                     \
514
0
  {                                                                           \
515
0
    if (IS_FROM_TU (dat))                                                     \
516
0
      {                                                                       \
517
0
        FIELD_TU (nam, dxf);                                                  \
518
0
      }                                                                       \
519
0
    else                                                                      \
520
0
      {                                                                       \
521
0
        FIELD_TV (nam, dxf);                                                  \
522
0
      }                                                                       \
523
0
  }
524
#define _FIELD_T(nam, str)                                                    \
525
  {                                                                           \
526
    if (IS_FROM_TU (dat))                                                     \
527
      {                                                                       \
528
        FIELD_TEXT_TU (nam, str);                                             \
529
      }                                                                       \
530
    else                                                                      \
531
      {                                                                       \
532
        FIELD_TEXT (nam, str);                                                \
533
      }                                                                       \
534
  }
535
#define VALUE_T(str)                                                          \
536
0
  {                                                                           \
537
0
    if (IS_FROM_TU (dat))                                                     \
538
0
      {                                                                       \
539
0
        VALUE_TEXT_TU (str);                                                  \
540
0
      }                                                                       \
541
0
    else                                                                      \
542
0
      {                                                                       \
543
0
        VALUE_TEXT (str)                                                      \
544
0
      }                                                                       \
545
0
  }
546
#define _FIELD_TV_ALPHA(nam, str)                                             \
547
0
  if ((str) && isalpha (*(str)))                                              \
548
0
    {                                                                         \
549
0
      FIELD_TEXT (nam, str)                                                   \
550
0
    }
551
0
#define FIELD_BT(nam, dxf) FIELD (nam, BT, dxf);
552
0
#define FIELD_4BITS(nam, dxf) FIELD (nam, 4BITS, dxf)
553
0
#define FIELD_BE(nam, dxf) FIELD_3RD (nam, dxf)
554
0
#define FIELD_DD(nam, _default, dxf) FIELD_BD (nam, dxf)
555
#define FIELD_2BD(nam, dxf) FIELD_2RD (nam, dxf)
556
0
#define FIELD_2BD_1(nam, dxf) FIELD_2RD (nam, dxf)
557
0
#define FIELD_2DD(nam, def, dxf) FIELD_2RD (nam, dxf)
558
0
#define FIELD_3DD(nam, def, dxf) FIELD_3RD (nam, dxf)
559
0
#define FIELD_3BD(nam, dxf) FIELD_3RD (nam, dxf)
560
0
#define FIELD_3BD_1(nam, dxf) FIELD_3RD (nam, dxf)
561
0
#define FIELD_3DPOINT(nam, dxf) FIELD_3BD (nam, dxf)
562
563
#define SUB_FIELD_T(o, nam, dxf)                                              \
564
0
  {                                                                           \
565
0
    KEY (nam);                                                                \
566
0
    VALUE_T (_obj->o.nam);                                                    \
567
0
  }
568
0
#define SUB_FIELD_B(o, nam, dxf) SUB_FIELD (o, nam, B, dxf)
569
#define SUB_FIELD_BB(o, nam, dxf) SUB_FIELD (o, nam, BB, dxf)
570
#define SUB_FIELD_3B(o, nam, dxf) SUB_FIELD (o, nam, 3B, dxf)
571
0
#define SUB_FIELD_BS(o, nam, dxf) SUB_FIELD (o, nam, BS, dxf)
572
0
#define SUB_FIELD_BSd(o, nam, dxf) SUB_FIELD (o, nam, BSd, dxf)
573
0
#define SUB_FIELD_BL(o, nam, dxf) SUB_FIELD (o, nam, BL, dxf)
574
0
#define SUB_FIELD_BLx(o, nam, dxf) SUB_FIELD (o, nam, BLx, dxf)
575
0
#define SUB_FIELD_BLd(o, nam, dxf) SUB_FIELD (o, nam, BLd, dxf)
576
0
#define SUB_FIELD_RC(o, nam, dxf) SUB_FIELD (o, nam, RC, dxf)
577
0
#define SUB_FIELD_RCd(o, nam, dxf) SUB_FIELD (o, nam, RCd, dxf)
578
0
#define SUB_FIELD_RS(o, nam, dxf) SUB_FIELD (o, nam, RS, dxf)
579
0
#define SUB_FIELD_RL(o, nam, dxf) SUB_FIELD (o, nam, RL, dxf)
580
#define SUB_FIELD_BLL(o, nam, dxf) SUB_FIELD (o, nam, BLL, dxf)
581
0
#define SUB_FIELD_RLL(o, nam, dxf) SUB_FIELD (o, nam, RLL, dxf)
582
583
0
#define SUB_FIELD_RD(o, nam, dxf) SUB_FIELD_BD (o, nam, dxf)
584
#define SUB_FIELD_3BD_inl(o, nam, dxf)                                        \
585
0
  SUB_FIELD_RD (o, x, dxf);                                                   \
586
0
  SUB_FIELD_RD (o, y, dxf);                                                   \
587
0
  SUB_FIELD_RD (o, z, dxf)
588
#define SUB_FIELD_2BD(o, nam, dxf)                                            \
589
  KEY (nam);                                                                  \
590
  VALUE_2RD (_obj->o.nam, dxf)
591
#define SUB_FIELD_2BD_1(o, nam, dxf)                                          \
592
0
  KEY (nam);                                                                  \
593
0
  VALUE_2RD (_obj->o.nam, dxf)
594
#define SUB_FIELD_2RD(o, nam, dxf)                                            \
595
0
  KEY (nam);                                                                  \
596
0
  VALUE_2RD (_obj->o.nam, dxf)
597
#define SUB_FIELD_3RD(o, nam, dxf)                                            \
598
  KEY (nam);                                                                  \
599
  VALUE_3RD (_obj->o.nam, dxf)
600
#define SUB_FIELD_3BD(o, nam, dxf)                                            \
601
0
  KEY (nam);                                                                  \
602
0
  VALUE_3RD (_obj->o.nam, dxf)
603
#define SUB_FIELD_3DPOINT(o, nam, dxf)                                        \
604
0
  KEY (nam);                                                                  \
605
0
  VALUE_3RD (_obj->o.nam, dxf)
606
607
static void
608
field_cmc (Bit_Chain *dat, const char *restrict key,
609
           const Dwg_Color *restrict _obj)
610
0
{
611
0
  if (dat->version >= R_2004)
612
0
    {
613
0
      KEYs (_path_field (key));
614
0
      HASH;
615
0
      if (_obj->index)
616
0
        {
617
0
          FIELD_BS (index, 62);
618
0
        }
619
0
      FIRSTPREFIX fprintf (dat->fh, "\"rgb\":%s\"%06x\"", JSON_SPC,
620
0
                           (unsigned)_obj->rgb);
621
0
      if (_obj->flag)
622
0
        {
623
0
          FIELD_BS (flag, 0);
624
0
        }
625
0
      if (_obj->flag > 0 && _obj->flag < 8)
626
0
        {
627
0
          if (_obj->flag & 1)
628
0
            _FIELD_TV_ALPHA (name, _obj->name)
629
0
          if (_obj->flag & 2)
630
0
            _FIELD_TV_ALPHA (book_name, _obj->book_name)
631
0
        }
632
0
      ENDHASH;
633
0
    }
634
0
  else
635
0
    {
636
0
      FIRSTPREFIX fprintf (dat->fh, JSON_KEY FORMAT_RSd, _path_field (key),
637
0
                           JSON_SPC, _obj->index);
638
0
    }
639
0
}
640
641
0
#define FIELD_CMC(color, dxf) field_cmc (dat, #color, &_obj->color)
642
0
#define SUB_FIELD_CMC(o, color, dxf) field_cmc (dat, #color, &_obj->o.color)
643
644
#define FIELD_TIMEBLL(nam, dxf)                                               \
645
0
  FIRSTPREFIX fprintf (                                                       \
646
0
      dat->fh, "\"" #nam "\":%s[%s" FORMAT_BL ",%s" FORMAT_BL "%s]",          \
647
0
      JSON_SPC, JSON_SPC, _obj->nam.days, JSON_SPC, _obj->nam.ms, JSON_SPC)
648
0
#define FIELD_TIMERLL(nam, dxf) FIELD_TIMEBLL (nam, dxf)
649
650
// FIELD_VECTOR_N(nam, type, size):
651
// reads data of the type indicated by 'type' 'size' times and stores
652
// it all in the vector called 'nam'.
653
#define FIELD_VECTOR_N(nam, type, size, dxf)                                  \
654
0
  KEY (nam);                                                                  \
655
0
  ARRAY;                                                                      \
656
0
  if (_obj->nam)                                                              \
657
0
    {                                                                         \
658
0
      for (vcount = 0; vcount < (BITCODE_BL)size; vcount++)                   \
659
0
        {                                                                     \
660
0
          FIRSTPREFIX fprintf (dat->fh, FORMAT_##type, _obj->nam[vcount]);    \
661
0
        }                                                                     \
662
0
    }                                                                         \
663
0
  else                                                                        \
664
0
    FIRSTPREFIX                                                               \
665
0
  ENDARRAY;
666
#define SUB_FIELD_VECTOR_N(o, nam, type, size, dxf)                           \
667
0
  KEY (nam);                                                                  \
668
0
  ARRAY;                                                                      \
669
0
  if (_obj->o.nam)                                                            \
670
0
    {                                                                         \
671
0
      for (vcount = 0; vcount < (BITCODE_BL)size; vcount++)                   \
672
0
        {                                                                     \
673
0
          FIRSTPREFIX fprintf (dat->fh, FORMAT_##type, _obj->o.nam[vcount]);  \
674
0
        }                                                                     \
675
0
    }                                                                         \
676
0
  else                                                                        \
677
0
    FIRSTPREFIX                                                               \
678
0
  ENDARRAY;
679
#define FIELD_VECTOR_T(nam, type, size, dxf)                                  \
680
0
  KEY (nam);                                                                  \
681
0
  ARRAY;                                                                      \
682
0
  if (_obj->nam)                                                              \
683
0
    {                                                                         \
684
0
      BITCODE_BL _size = (BITCODE_BL)_obj->size;                              \
685
0
      if (IS_FROM_TU (dat))                                                   \
686
0
        {                                                                     \
687
0
          for (vcount = 0; vcount < _size; vcount++)                          \
688
0
            {                                                                 \
689
0
              FIRSTPREFIX VALUE_TEXT_TU (_obj->nam[vcount]);                  \
690
0
            }                                                                 \
691
0
        }                                                                     \
692
0
      else                                                                    \
693
0
        {                                                                     \
694
0
          for (vcount = 0; vcount < _size; vcount++)                          \
695
0
            {                                                                 \
696
0
              FIRSTPREFIX VALUE_TEXT (_obj->nam[vcount])                      \
697
0
            }                                                                 \
698
0
        }                                                                     \
699
0
    }                                                                         \
700
0
  else                                                                        \
701
0
    FIRSTPREFIX                                                               \
702
0
  ENDARRAY;
703
704
#define SUB_FIELD_VECTOR_TYPESIZE(o, nam, size, typesize, dxf)                \
705
0
  KEY (nam);                                                                  \
706
0
  ARRAY;                                                                      \
707
0
  if (_obj->o.size && _obj->o.nam)                                            \
708
0
    {                                                                         \
709
0
      for (vcount = 0; vcount < (BITCODE_BL)_obj->o.size; vcount++)           \
710
0
        {                                                                     \
711
0
          switch (typesize)                                                   \
712
0
            {                                                                 \
713
0
            case 0:                                                           \
714
0
              break;                                                          \
715
0
            case 1:                                                           \
716
0
              FIRSTPREFIX fprintf (dat->fh, FORMAT_RC,                        \
717
0
                                   (BITCODE_RC)_obj->o.nam[vcount]);          \
718
0
              break;                                                          \
719
0
            case 2:                                                           \
720
0
              FIRSTPREFIX fprintf (dat->fh, FORMAT_RS,                        \
721
0
                                   (BITCODE_RS)_obj->o.nam[vcount]);          \
722
0
              break;                                                          \
723
0
            case 4:                                                           \
724
0
              FIRSTPREFIX fprintf (dat->fh, FORMAT_RL,                        \
725
0
                                   (BITCODE_RL)_obj->o.nam[vcount]);          \
726
0
              break;                                                          \
727
0
            case 8:                                                           \
728
0
              FIRSTPREFIX fprintf (dat->fh, FORMAT_RLL,                       \
729
0
                                   (BITCODE_RLL)_obj->o.nam[vcount]);         \
730
0
              break;                                                          \
731
0
            default:                                                          \
732
0
              LOG_ERROR ("Unknown SUB_FIELD_VECTOR_TYPESIZE " #nam            \
733
0
                         " typesize %d",                                      \
734
0
                         typesize);                                           \
735
0
              break;                                                          \
736
0
            }                                                                 \
737
0
        }                                                                     \
738
0
    }                                                                         \
739
0
  else                                                                        \
740
0
    FIRSTPREFIX                                                               \
741
0
  ENDARRAY;
742
743
#define FIELD_VECTOR(nam, type, size, dxf)                                    \
744
0
  FIELD_VECTOR_N (nam, type, _obj->size, dxf)
745
#define FIELD_VECTOR_INL(nam, type, size, dxf)                                \
746
0
  FIELD_VECTOR_N (nam, type, size, dxf)
747
#define SUB_FIELD_VECTOR(o, nam, type, size, dxf)                             \
748
0
  SUB_FIELD_VECTOR_N (o, nam, type, _obj->o.size, dxf)
749
750
#define FIELD_2RD_VECTOR(nam, size, dxf)                                      \
751
0
  if (_obj->nam)                                                              \
752
0
    {                                                                         \
753
0
      KEY (nam);                                                              \
754
0
      ARRAY;                                                                  \
755
0
      for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++)             \
756
0
        {                                                                     \
757
0
          FIRSTPREFIX VALUE_2RD (FIELD_VALUE (nam[vcount]), dxf);             \
758
0
        }                                                                     \
759
0
      ENDARRAY;                                                               \
760
0
    }
761
762
#define FIELD_2DD_VECTOR(nam, size, dxf)                                      \
763
0
  if (_obj->nam)                                                              \
764
0
    {                                                                         \
765
0
      KEY (nam);                                                              \
766
0
      ARRAY;                                                                  \
767
0
      for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++)             \
768
0
        {                                                                     \
769
0
          FIRSTPREFIX VALUE_2RD (_obj->nam[vcount], dxf);                     \
770
0
        }                                                                     \
771
0
      ENDARRAY;                                                               \
772
0
    }
773
774
#define FIELD_3DPOINT_VECTOR(nam, size, dxf)                                  \
775
0
  if (_obj->nam)                                                              \
776
0
    {                                                                         \
777
0
      KEY (nam);                                                              \
778
0
      ARRAY;                                                                  \
779
0
      for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++)             \
780
0
        {                                                                     \
781
0
          FIRSTPREFIX VALUE_3BD (FIELD_VALUE (nam[vcount]), dxf);             \
782
0
        }                                                                     \
783
0
      ENDARRAY;                                                               \
784
0
    }
785
786
#define HANDLE_VECTOR_N(nam, size, code, dxf)                                 \
787
0
  if (_obj->nam)                                                              \
788
0
    {                                                                         \
789
0
      KEY (nam);                                                              \
790
0
      ARRAY;                                                                  \
791
0
      for (vcount = 0; vcount < (BITCODE_BL)size; vcount++)                   \
792
0
        {                                                                     \
793
0
          FIELD_HANDLE_N (nam[vcount], vcount, code, dxf);                    \
794
0
        }                                                                     \
795
0
      ENDARRAY;                                                               \
796
0
    }
797
798
#define HANDLE_VECTOR(nam, sizefield, code, dxf)                              \
799
0
  HANDLE_VECTOR_N (nam, FIELD_VALUE (sizefield), code, dxf)
800
801
#define SUB_HANDLE_VECTOR(o, nam, size, code, dxf)                            \
802
0
  KEY (nam);                                                                  \
803
0
  if (_obj->o.nam)                                                            \
804
0
    {                                                                         \
805
0
      ARRAY;                                                                  \
806
0
      for (vcount = 0; vcount < (BITCODE_BL)_obj->o.size; vcount++)           \
807
0
        {                                                                     \
808
0
          SUB_FIELD_HANDLE_N (o, nam[vcount], code, dxf);                     \
809
0
        }                                                                     \
810
0
      ENDARRAY;                                                               \
811
0
    }                                                                         \
812
0
  else                                                                        \
813
0
    {                                                                         \
814
0
      ARRAY;                                                                  \
815
0
      ENDARRAY;                                                               \
816
0
    }
817
818
#define REACTORS(code)                                                        \
819
0
  if (dat->version >= R_13b1 && obj->tio.object->num_reactors                 \
820
0
      && obj->tio.object->reactors)                                           \
821
0
    {                                                                         \
822
0
      KEY (reactors);                                                         \
823
0
      ARRAY;                                                                  \
824
0
      for (vcount = 0; vcount < obj->tio.object->num_reactors; vcount++)      \
825
0
        {                                                                     \
826
0
          FIRSTPREFIX VALUE_HANDLE (obj->tio.object->reactors[vcount],        \
827
0
                                    reactors, code, 330);                     \
828
0
        }                                                                     \
829
0
      ENDARRAY;                                                               \
830
0
    }
831
#define ENT_REACTORS(code)                                                    \
832
0
  if (dat->version >= R_13b1 && _ent->num_reactors && _ent->reactors)         \
833
0
    {                                                                         \
834
0
      KEY (reactors);                                                         \
835
0
      ARRAY;                                                                  \
836
0
      for (vcount = 0; vcount < _ent->num_reactors; vcount++)                 \
837
0
        {                                                                     \
838
0
          FIRSTPREFIX VALUE_HANDLE (_ent->reactors[vcount], reactors, code,   \
839
0
                                    330);                                     \
840
0
        }                                                                     \
841
0
      ENDARRAY;                                                               \
842
0
    }
843
844
// violates duplicate keys
845
#define SUBCLASS(name)                                                        \
846
0
  SINCE (R_13b1)                                                              \
847
0
  {                                                                           \
848
0
    FIRSTPREFIX fprintf (dat->fh, "\"_subclass\":%s\"" #name "\"", JSON_SPC); \
849
0
  }
850
851
// FIXME: for KEY not the complete nam path, only the field.
852
// e.g. verts[rcount1].lines[rcount2].segparms
853
#define _REPEAT_N(times, nam, type, idx)                                      \
854
0
  if (_obj->nam)                                                              \
855
0
    {                                                                         \
856
0
      KEY (nam);                                                              \
857
0
      ARRAY;                                                                  \
858
0
      for (rcount##idx = 0; rcount##idx < (BITCODE_BL)times; rcount##idx++)   \
859
0
        {
860
0
#define REPEAT_N(times, nam, type) _REPEAT_N (times, nam, type, 1)
861
0
#define REPEAT_CN(times, nam, type) REPEAT_N (times, nam, type)
862
#define _REPEAT_C(times, nam, type, idx)                                      \
863
  _REPEAT_N (_obj->times, nam, type, idx)
864
0
#define _REPEAT(times, nam, type, idx) _REPEAT_N (_obj->times, nam, type, idx)
865
0
#define REPEAT(times, nam, type) _REPEAT (times, nam, type, 1)
866
0
#define REPEAT2(times, nam, type) _REPEAT (times, nam, type, 2)
867
0
#define REPEAT3(times, nam, type) _REPEAT (times, nam, type, 3)
868
0
#define REPEAT4(times, nam, type) _REPEAT (times, nam, type, 4)
869
#define REPEAT_C(times, nam, type) _REPEAT_C (times, nam, type, 1)
870
#define REPEAT2_C(times, nam, type) _REPEAT_C (times, nam, type, 2)
871
#define REPEAT3_C(times, nam, type) _REPEAT_C (times, nam, type, 3)
872
#define REPEAT4_C(times, nam, type) _REPEAT_C (times, nam, type, 4)
873
0
#define _REPEAT_CN(times, nam, type, idx) _REPEAT_N (times, nam, type, idx)
874
#define _REPEAT_CNF(times, nam, type, idx) _REPEAT_N (times, nam, type, idx)
875
0
#define _REPEAT_NF(times, nam, type, idx) _REPEAT_N (times, nam, type, idx)
876
#define REPEAT_F(times, size, nam, type)                                      \
877
0
  if (_obj->times > (BITCODE_BL)size)                                         \
878
0
    {                                                                         \
879
0
      LOG_WARN ("Invalid %s " FORMAT_BL " > %u", #nam,                        \
880
0
                (BITCODE_BL)_obj->times, (unsigned)size);                     \
881
0
      _obj->times = (BITCODE_BL)size;                                         \
882
0
    }                                                                         \
883
0
  _REPEAT_N (_obj->times, nam, type, 1)
884
#undef REPEAT_BLOCK
885
0
#define REPEAT_BLOCK FIRSTPREFIX HASH;
886
#undef END_REPEAT_BLOCK
887
0
#define END_REPEAT_BLOCK ENDHASH;
888
#undef END_REPEAT
889
#define END_REPEAT(nam)                                                       \
890
0
  }                                                                           \
891
0
  ENDARRAY;                                                                   \
892
0
  }
893
#undef END_REPEAT_F
894
0
#define END_REPEAT_F(nam) END_REPEAT (nam)
895
896
#define FIELD_NUM_INSERTS(num_inserts, type, dxf)                             \
897
0
  FIELD (num_inserts, type, dxf)
898
899
0
#define FIELD_XDATA(nam, size) error |= json_xdata (dat, _obj)
900
901
#define XDICOBJHANDLE(code)                                                   \
902
0
  if ((dat->version < R_2004 || obj->tio.object->is_xdic_missing == 0)        \
903
0
      && (obj->tio.object->xdicobjhandle != NULL)                             \
904
0
      && (obj->tio.object->xdicobjhandle->handleref.value != 0))              \
905
0
    {                                                                         \
906
0
      KEY (xdicobjhandle);                                                    \
907
0
      VALUE_HANDLE (obj->tio.object->xdicobjhandle, xdicobjhandle, code, -3); \
908
0
    }
909
#define ENT_XDICOBJHANDLE(code)                                               \
910
0
  if ((dat->version < R_2004 || _ent->is_xdic_missing == 0)                   \
911
0
      && (_ent->xdicobjhandle != NULL)                                        \
912
0
      && (_ent->xdicobjhandle->handleref.value != 0))                         \
913
0
    {                                                                         \
914
0
      KEY (xdicobjhandle);                                                    \
915
0
      VALUE_HANDLE (_ent->xdicobjhandle, xdicobjhandle, code, -3);            \
916
0
    }
917
918
#define COMMON_ENTITY_HANDLE_DATA
919
#define SECTION_STRING_STREAM
920
#define START_STRING_STREAM
921
#define END_STRING_STREAM
922
#define START_HANDLE_STREAM
923
#define START_OBJECT_HANDLE_STREAM
924
#define CONTROL_HANDLE_STREAM
925
926
#define DWG_ENTITY(token)                                                     \
927
  static int dwg_json_##token##_private (Bit_Chain *dat, Bit_Chain *hdl_dat,  \
928
                                         Bit_Chain *str_dat,                  \
929
                                         Dwg_Object *restrict obj);           \
930
  GCC30_DIAG_IGNORE (-Wshadow)                                                \
931
  static int dwg_json_##token (Bit_Chain *restrict dat,                       \
932
                               Dwg_Object *restrict obj)                      \
933
0
  {                                                                           \
934
0
    int error = 0;                                                            \
935
0
    Bit_Chain *str_dat = dat;                                                 \
936
0
    Bit_Chain *hdl_dat = dat;                                                 \
937
0
    Dwg_Data *dwg = obj->parent;                                              \
938
0
    Dwg_Entity_##token *ent, *_obj;                                           \
939
0
    Dwg_Object_Entity *_ent;                                                  \
940
0
    const char *name = #token;                                                \
941
0
    LOG_INFO ("Entity " #token ":\n")                                         \
942
0
    _ent = obj->tio.entity;                                                   \
943
0
    if (!_ent || !_ent->tio.token)                                            \
944
0
      return DWG_ERR_INTERNALERROR;                                           \
945
0
    _obj = ent = _ent->tio.token;                                             \
946
0
    if (*name == '_')                                                         \
947
0
      FIELD_TEXT (entity, &name[1])                                           \
948
0
    else                                                                      \
949
0
      FIELD_TEXT (entity, name)                                               \
950
0
    if (obj->dxfname && strNE (obj->dxfname, #token))                         \
951
0
      FIELD_TEXT (dxfname, obj->dxfname);                                     \
952
0
    _FIELD (index, RL, 0);                                                    \
953
0
    _FIELD (type, RSd, 0);                                                    \
954
0
    SINCE (R_13b1)                                                            \
955
0
    {                                                                         \
956
0
      KEY (handle);                                                           \
957
0
      VALUE_H (obj->handle, 5);                                               \
958
0
    }                                                                         \
959
0
    _FIELD (size, RL, 0);                                                     \
960
0
    SINCE (R_13b1)                                                            \
961
0
    {                                                                         \
962
0
      _FIELD (bitsize, BL, 0);                                                \
963
0
      if (_ent->preview_exists)                                               \
964
0
        ENT_FIELD (preview_exists, B, 0);                                     \
965
0
    }                                                                         \
966
0
    error |= json_common_entity_data (dat, obj);                              \
967
0
    return error | dwg_json_##token##_private (dat, hdl_dat, str_dat, obj);   \
968
0
  }                                                                           \
969
  static int dwg_json_##token##_private (Bit_Chain *dat, Bit_Chain *hdl_dat,  \
970
                                         Bit_Chain *str_dat,                  \
971
                                         Dwg_Object *restrict obj)            \
972
0
  {                                                                           \
973
0
    int error = 0;                                                            \
974
0
    BITCODE_BL vcount, rcount3, rcount4;                                      \
975
0
    Dwg_Data *dwg = obj->parent;                                              \
976
0
    Dwg_Object_Entity *_ent = obj->tio.entity;                                \
977
0
    Dwg_Entity_##token *_obj = _ent->tio.token;
978
979
#define DWG_ENTITY_END                                                        \
980
0
  if (obj->num_unknown_rest)                                                  \
981
0
    UNKNOWN_BITS_REST                                                         \
982
0
  return error;                                                               \
983
0
  }
984
985
#define DWG_OBJECT(token)                                                     \
986
  static int dwg_json_##token##_private (Bit_Chain *dat, Bit_Chain *hdl_dat,  \
987
                                         Bit_Chain *str_dat,                  \
988
                                         Dwg_Object *restrict obj);           \
989
  GCC30_DIAG_IGNORE (-Wshadow)                                                \
990
  static int dwg_json_##token (Bit_Chain *restrict dat,                       \
991
                               Dwg_Object *restrict obj)                      \
992
0
  {                                                                           \
993
0
    int error = 0;                                                            \
994
0
    Bit_Chain *str_dat = dat;                                                 \
995
0
    Bit_Chain *hdl_dat = dat;                                                 \
996
0
    const char *name = #token;                                                \
997
0
    Dwg_Object_##token *_obj;                                                 \
998
0
    LOG_INFO ("Object " #token ":\n")                                         \
999
0
    if (!obj->tio.object || !obj->tio.object->tio.token)                      \
1000
0
      return DWG_ERR_INTERNALERROR;                                           \
1001
0
    _obj = obj->tio.object->tio.token;                                        \
1002
0
    if (*name == '_')                                                         \
1003
0
      FIELD_TEXT (object, &name[1])                                           \
1004
0
    else                                                                      \
1005
0
      FIELD_TEXT (object, name)                                               \
1006
0
    if (obj->dxfname && strNE (obj->dxfname, #token))                         \
1007
0
      FIELD_TEXT (dxfname, obj->dxfname);                                     \
1008
0
    _FIELD (index, RL, 0);                                                    \
1009
0
    _FIELD (type, RL, 0);                                                     \
1010
0
    KEY (handle);                                                             \
1011
0
    VALUE_H (obj->handle, 5);                                                 \
1012
0
    _FIELD (size, RL, 0);                                                     \
1013
0
    SINCE (R_13b1)                                                            \
1014
0
    {                                                                         \
1015
0
      _FIELD (bitsize, BL, 0);                                                \
1016
0
    }                                                                         \
1017
0
    error |= json_eed (dat, obj->tio.object);                                 \
1018
0
    error |= json_common_object_handle_data (dat, obj);                       \
1019
0
    return error | dwg_json_##token##_private (dat, hdl_dat, str_dat, obj);   \
1020
0
  }                                                                           \
1021
  static int dwg_json_##token##_private (Bit_Chain *dat, Bit_Chain *hdl_dat,  \
1022
                                         Bit_Chain *str_dat,                  \
1023
                                         Dwg_Object *restrict obj)            \
1024
0
  {                                                                           \
1025
0
    int error = 0;                                                            \
1026
0
    BITCODE_BL vcount, rcount3, rcount4;                                      \
1027
0
    Dwg_Data *dwg = obj->parent;                                              \
1028
0
    Dwg_Object_##token *_obj = obj->tio.object->tio.token;
1029
1030
#define DWG_OBJECT_END                                                        \
1031
0
  if (obj->num_unknown_rest)                                                  \
1032
0
    UNKNOWN_BITS_REST                                                         \
1033
0
  return error;                                                               \
1034
0
  }
1035
1036
#undef JSON_3DSOLID
1037
0
#define JSON_3DSOLID json_3dsolid (dat, obj, (Dwg_Entity_3DSOLID *)_obj);
1038
1039
static void
1040
_prefix (Bit_Chain *dat)
1041
0
{
1042
0
  if (!IS_MINJS)
1043
0
    {
1044
0
      for (int _i = 0; _i < dat->bit; _i++)
1045
0
        {
1046
0
          fprintf (dat->fh, "  ");
1047
0
        }
1048
0
    }
1049
0
}
1050
1051
static char *
1052
_path_field (const char *path)
1053
0
{
1054
0
  const char *s = strrchr (path, ']');
1055
0
  if (s && s[1] == '.')
1056
0
    {
1057
0
      return (char *)&s[2];
1058
0
    }
1059
0
  return (char *)path;
1060
0
}
1061
1062
static int
1063
json_eed (Bit_Chain *restrict dat, const Dwg_Object_Object *restrict obj)
1064
0
{
1065
0
  int error = 0;
1066
0
  if (!obj->num_eed)
1067
0
    return 0;
1068
0
  KEY (eed);
1069
0
  ARRAY;
1070
0
  for (BITCODE_BL i = 0; i < obj->num_eed; i++)
1071
0
    {
1072
0
      const Dwg_Eed *_obj = &obj->eed[i];
1073
0
      FIRSTPREFIX HASH;
1074
0
      if (_obj->size)
1075
0
        {
1076
0
          FIELD (size, RS, 0);
1077
0
          KEY (handle);
1078
0
          fprintf (dat->fh, FORMAT_H, ARGS_H (_obj->handle));
1079
0
        }
1080
0
      if (_obj->data)
1081
0
        {
1082
0
          const Dwg_Eed_Data *data = _obj->data;
1083
0
          KEY (code);
1084
0
          VALUE_RC (data->code, 0);
1085
0
          KEY (value);
1086
0
          switch (data->code)
1087
0
            {
1088
0
            case 0:
1089
0
              if (!data->u.eed_0.is_tu)
1090
0
                VALUE_TEXT (data->u.eed_0.string)
1091
0
              else
1092
0
                {
1093
0
                  VALUE_TEXT_TU (data->u.eed_0_r2007.string);
1094
0
                }
1095
0
              break;
1096
0
            case 1:
1097
0
              VALUE_RS (data->u.eed_1.appid_index, 0);
1098
0
              break;
1099
0
            case 2:
1100
0
              VALUE_RC (data->u.eed_2.close, 0);
1101
0
              break;
1102
0
            case 3:
1103
0
              VALUE_RLL (data->u.eed_3.layer, 0);
1104
0
              break;
1105
0
            case 4:
1106
0
              VALUE_BINARY (data->u.eed_4.data, data->u.eed_4.length, 0);
1107
0
              break;
1108
0
            case 5:
1109
0
              fprintf (dat->fh, FORMAT_H "", 5, 8, data->u.eed_5.entity);
1110
0
              break;
1111
0
            case 10:
1112
0
            case 11:
1113
0
            case 12:
1114
0
            case 13:
1115
0
            case 14:
1116
0
            case 15:
1117
0
              VALUE_3RD (data->u.eed_10.point, 0);
1118
0
              break;
1119
0
            case 40:
1120
0
            case 41:
1121
0
            case 42:
1122
0
              VALUE_RD (data->u.eed_40.real, 0);
1123
0
              break;
1124
0
            case 70:
1125
0
              VALUE_RS (data->u.eed_70.rs, 0);
1126
0
              break;
1127
0
            case 71:
1128
0
              VALUE_RL (data->u.eed_71.rl, 0);
1129
0
              break;
1130
0
            default:
1131
0
              VALUE_RC (0, 0);
1132
0
            }
1133
0
        }
1134
0
      ENDHASH
1135
0
    }
1136
0
  ENDARRAY;
1137
0
  return error;
1138
0
}
1139
1140
static int
1141
json_xdata (Bit_Chain *restrict dat, const Dwg_Object_XRECORD *restrict obj)
1142
0
{
1143
0
  int error = 0;
1144
0
  Dwg_Resbuf *rbuf = obj->xdata;
1145
0
  KEY (xdata);
1146
0
  ARRAY;
1147
0
  for (BITCODE_BL i = 0; i < obj->num_xdata; i++)
1148
0
    {
1149
0
      enum RESBUF_VALUE_TYPE type;
1150
0
      FIRSTPREFIX ARRAY;
1151
0
      FIRSTPREFIX VALUE_RS (rbuf->type, 0);
1152
0
      FIRSTPREFIX
1153
0
      type = dwg_resbuf_value_type (rbuf->type);
1154
0
      switch (type)
1155
0
        {
1156
0
        case DWG_VT_STRING:
1157
0
          if (!rbuf->value.str.is_tu)
1158
0
            {
1159
0
              VALUE_TEXT (rbuf->value.str.u.data);
1160
0
              LOG_TRACE ("xdata[%u]: \"%s\" [TV %d]\n", i,
1161
0
                         rbuf->value.str.u.data, rbuf->type);
1162
0
            }
1163
0
          else
1164
0
            {
1165
0
              VALUE_TEXT_TU (rbuf->value.str.u.data);
1166
0
              LOG_TRACE_TU ("xdata", rbuf->value.str.u.data, rbuf->type);
1167
0
            }
1168
0
          break;
1169
0
        case DWG_VT_BINARY:
1170
0
          VALUE_BINARY (rbuf->value.str.u.data, rbuf->value.str.size, 0);
1171
0
          LOG_TRACE ("xdata[%u]: \"%s\" [TF %d]\n", i, rbuf->value.str.u.data,
1172
0
                     rbuf->type);
1173
0
          break;
1174
0
        case DWG_VT_REAL:
1175
0
          VALUE_RD (rbuf->value.dbl, 0);
1176
0
          LOG_TRACE ("xdata[%u]: %f [RD %d]\n", i, rbuf->value.dbl,
1177
0
                     rbuf->type);
1178
0
          break;
1179
0
        case DWG_VT_BOOL:
1180
0
        case DWG_VT_INT8:
1181
0
          VALUE_RC (rbuf->value.i8, 0);
1182
0
          LOG_TRACE ("xdata[%u]: %d [RC %d]\n", i, (int)rbuf->value.i8,
1183
0
                     rbuf->type);
1184
0
          break;
1185
0
        case DWG_VT_INT16:
1186
0
          VALUE_RSd (rbuf->value.i16, 0);
1187
0
          LOG_TRACE ("xdata[%u]: %d [RSd %d]\n", i, (int)rbuf->value.i16,
1188
0
                     rbuf->type);
1189
0
          break;
1190
0
        case DWG_VT_INT32:
1191
0
          VALUE_RLd (rbuf->value.i32, 0);
1192
0
          LOG_TRACE ("xdata[%u]: %d [RLd %d]\n", i, (int)rbuf->value.i32,
1193
0
                     rbuf->type);
1194
0
          break;
1195
0
        case DWG_VT_INT64:
1196
0
          VALUE_RLLd (rbuf->value.i64, 0);
1197
0
          LOG_TRACE ("xdata[%u]: %ld [RLLd %d]\n", i, (long)rbuf->value.i64,
1198
0
                     rbuf->type);
1199
0
          break;
1200
0
        case DWG_VT_POINT3D:
1201
0
          fprintf (dat->fh, "[" FORMAT_RD "," FORMAT_RD "," FORMAT_RD "]",
1202
0
                   rbuf->value.pt[0], rbuf->value.pt[1], rbuf->value.pt[2]);
1203
0
          LOG_TRACE ("xdata[%u]: (%f,%f,%f) [3RD %d]\n", i, rbuf->value.pt[0],
1204
0
                     rbuf->value.pt[1], rbuf->value.pt[2], rbuf->type);
1205
0
          break;
1206
0
        case DWG_VT_HANDLE:
1207
0
        case DWG_VT_OBJECTID:
1208
0
          VALUE_RLL (rbuf->value.absref, 0);
1209
0
          LOG_TRACE ("xdata[%u]: " FORMAT_HV " [H %d]\n", i,
1210
0
                     rbuf->value.absref, rbuf->type);
1211
0
          break;
1212
0
        case DWG_VT_INVALID:
1213
0
        default:
1214
0
          break;
1215
0
        }
1216
0
      rbuf = rbuf->nextrb;
1217
0
      ENDARRAY
1218
0
    }
1219
0
  ENDARRAY;
1220
0
  return error;
1221
0
}
1222
1223
static int
1224
json_common_entity_data (Bit_Chain *restrict dat,
1225
                         const Dwg_Object *restrict obj)
1226
0
{
1227
0
  Dwg_Object_Entity *_ent, *_obj;
1228
  // Dwg_Data *dwg = obj->parent;
1229
0
  int error = 0;
1230
0
  BITCODE_BL vcount = 0;
1231
0
  _ent = obj->tio.entity;
1232
0
  _obj = _ent;
1233
1234
0
  error |= json_eed (dat, (Dwg_Object_Object *)_ent);
1235
1236
  // clang-format off
1237
0
  #include "common_entity_handle_data.spec"
1238
0
  PRE (R_13)
1239
0
    FIELD_BB (entmode, 0); // also needed for preR13, to detect BLOCKS
1240
0
  #include "common_entity_data.spec"
1241
  // clang-format on
1242
1243
0
  return error;
1244
0
}
1245
1246
static int
1247
json_common_object_handle_data (Bit_Chain *restrict dat,
1248
                                const Dwg_Object *restrict obj)
1249
0
{
1250
0
  Dwg_Object_Object *_obj;
1251
0
  Dwg_Data *dwg = obj->parent;
1252
0
  int error = 0;
1253
0
  BITCODE_BL vcount = 0;
1254
0
  _obj = obj->tio.object;
1255
1256
  // clang-format off
1257
0
  #include "common_object_handle_data.spec"
1258
  // clang-format on
1259
0
  return error;
1260
0
}
1261
1262
#include "dwg.spec"
1263
1264
static int
1265
ishex (int c)
1266
0
{
1267
0
  return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
1268
0
          || (c >= 'A' && c <= 'F'));
1269
0
}
1270
// Usage: hex(c >> 4), hex(c & 0xf)
1271
static int
1272
hex (unsigned char c)
1273
0
{
1274
0
  c &= 0xf; // 0-15
1275
0
  return c >= 10 ? 'a' + c - 10 : '0' + c;
1276
0
}
1277
1278
#ifndef HAVE_NATIVE_WCHAR2
1279
1280
static void
1281
print_wcquote (Bit_Chain *restrict dat, dwg_wchar_t *restrict wstr)
1282
0
{
1283
0
  BITCODE_TU ws = (BITCODE_TU)wstr;
1284
0
  uint16_t c;
1285
0
  if (!ws)
1286
0
    {
1287
0
      fprintf (dat->fh, "\"\"");
1288
0
      return;
1289
0
    }
1290
0
  fprintf (dat->fh, "\"");
1291
0
  while (1)
1292
0
    {
1293
#  ifdef HAVE_ALIGNED_ACCESS_REQUIRED
1294
      // for strict alignment CPU's like sparc only. also for UBSAN.
1295
      if ((uintptr_t)wstr % SIZEOF_SIZE_T)
1296
        {
1297
          unsigned char *b = (unsigned char *)ws;
1298
          c = TU_to_int (b);
1299
          ws++;
1300
        }
1301
      else
1302
#  endif
1303
0
        c = *ws++;
1304
0
      if (!c)
1305
0
        break;
1306
0
      if (c == L'"')
1307
0
        {
1308
0
          fprintf (dat->fh, "\\\"");
1309
0
        }
1310
0
      else if (c == L'\\' && ws[0] == L'U' && ws[1] == L'+' && ishex (ws[2])
1311
0
               && ishex (ws[3]) && ishex (ws[4]) && ishex (ws[5]))
1312
0
        {
1313
0
          fprintf (dat->fh, "\\u");
1314
0
          ws += 2;
1315
0
        }
1316
0
      else if (c == L'\\')
1317
0
        {
1318
0
          fprintf (dat->fh, "\\\\");
1319
0
        }
1320
0
      else if (c == L'\n')
1321
0
        {
1322
0
          fprintf (dat->fh, "\\n");
1323
0
        }
1324
0
      else if (c == L'\r')
1325
0
        {
1326
0
          fprintf (dat->fh, "\\r");
1327
0
        }
1328
      // convert to utf-8
1329
0
      else if (c < 0x1f || c > 0xff)
1330
0
        {
1331
0
          if (c < 0x80)
1332
0
            {
1333
0
              fprintf (dat->fh, "\\u%04x", c);
1334
0
            }
1335
0
          else if (c < 0x800)
1336
0
            {
1337
0
              fprintf (dat->fh, "%c%c", (c >> 6) | 0xC0, (c & 0x3F) | 0x80);
1338
0
            }
1339
0
          else /* if (c < 0x10000) */
1340
0
            {
1341
0
              fprintf (dat->fh, "%c%c%c", (c >> 12) | 0xE0,
1342
0
                       ((c >> 6) & 0x3F) | 0x80, (c & 0x3F) | 0x80);
1343
0
            }
1344
#  if 0
1345
          // FIXME: handle surrogate pairs properly
1346
          if (c >= 0xd800 && c < 0xdc00)
1347
            {
1348
              fprintf (dat->fh, "\\u%04x", c - 0x1000);
1349
            }
1350
          else if (c >= 0xdc00 && c < 0xe000)
1351
            ;
1352
          else
1353
            fprintf (dat->fh, "\\u%04x", c);
1354
#  endif
1355
0
        }
1356
0
      else
1357
0
        fprintf (dat->fh, "%c", (char)(c & 0xff));
1358
0
    }
1359
0
  fprintf (dat->fh, "\"");
1360
0
}
1361
1362
#else
1363
1364
static wchar_t *
1365
wcquote (wchar_t *restrict dest, const wchar_t *restrict src)
1366
{
1367
  wchar_t c;
1368
  wchar_t *d = dest;
1369
  wchar_t *s = (wchar_t *)src;
1370
  while ((c = *s++))
1371
    {
1372
      if (c == L'"')
1373
        {
1374
          *dest++ = L'\\';
1375
          *dest++ = c;
1376
        }
1377
      else if (c == L'\\' && s[0] == L'U' && s[1] == L'+' && ishex (s[2])
1378
               && ishex (s[3]) && ishex (s[4]) && ishex (s[5]))
1379
        {
1380
          *dest++ = '\\';
1381
          *dest++ = 'u';
1382
          s += 2;
1383
        }
1384
      else if (c == L'\\')
1385
        {
1386
          *dest++ = L'\\';
1387
          *dest++ = c;
1388
        }
1389
      else if (c == L'\n')
1390
        {
1391
          *dest++ = L'\\';
1392
          *dest++ = L'n';
1393
        }
1394
      else if (c == L'\r')
1395
        {
1396
          *dest++ = L'\\';
1397
          *dest++ = L'r';
1398
        }
1399
      else if (c < 0x1f)
1400
        {
1401
          *dest++ = L'\\';
1402
          *dest++ = L'u';
1403
          *dest++ = L'0';
1404
          *dest++ = L'0';
1405
          *dest++ = hex (c >> 4);
1406
          *dest++ = hex (c & 0xf);
1407
        }
1408
      else
1409
        *dest++ = c;
1410
    }
1411
  *dest = 0; // add final delim, skipped above
1412
  return d;
1413
}
1414
1415
#endif /* HAVE_NATIVE_WCHAR2 */
1416
1417
/* Don't write past the strlen.
1418
   TODO: convert to utf8.
1419
*/
1420
void
1421
json_write_TFv (Bit_Chain *restrict dat, const BITCODE_TF restrict src,
1422
                const size_t len)
1423
0
{
1424
0
  const size_t slen = src ? strlen ((char *)src) : 0;
1425
0
  fputc ('"', dat->fh);
1426
0
  if (!slen)
1427
0
    {
1428
0
      fputc ('"', dat->fh);
1429
0
      return;
1430
0
    }
1431
0
  for (size_t i = 0; i < MIN (slen, len); i++)
1432
0
    {
1433
0
      const unsigned char c = src[i];
1434
0
      if (c == '\r' || c == '\n' || c == '"' || c == '\\')
1435
0
        {
1436
0
          fputc ('\\', dat->fh);
1437
0
          if (c == '\r')
1438
0
            fputc ('r', dat->fh);
1439
0
          else if (c == '\n')
1440
0
            fputc ('n', dat->fh);
1441
0
          else
1442
0
            fputc (c, dat->fh);
1443
0
        }
1444
0
      else if (c == '\\' && i + 6 < len && src[i] == 'U' && src[i + 1] == '+'
1445
0
               && ishex (src[i + 2]) && ishex (src[i + 3])
1446
0
               && ishex (src[i + 4]) && ishex (src[i + 5]))
1447
0
        {
1448
0
          fputc ('\\', dat->fh);
1449
0
          fputc ('u', dat->fh);
1450
0
          i += 3;
1451
0
        }
1452
0
      else if (c < 0x1f)
1453
0
        fprintf (dat->fh, "\\u00%02x", c);
1454
0
      else
1455
0
        fputc (c, dat->fh);
1456
0
    }
1457
0
  fputc ('"', dat->fh);
1458
0
}
1459
1460
/* Write even past the \0, to keep existing slack.
1461
   TODO: convert to utf8.
1462
*/
1463
void
1464
json_write_TF (Bit_Chain *restrict dat, const BITCODE_TF restrict src,
1465
               const size_t len)
1466
0
{
1467
0
  const size_t slen = src ? strlen ((char *)src) : 0;
1468
0
  bool has_slack = false;
1469
0
  fputc ('"', dat->fh);
1470
0
  if (!slen)
1471
0
    {
1472
0
      fputc ('"', dat->fh);
1473
0
      return;
1474
0
    }
1475
0
  for (size_t i = 0; i < len; i++)
1476
0
    {
1477
0
      const unsigned char c = src[i];
1478
0
      if (c == '\r' || c == '\n' || c == '"' || c == '\\')
1479
0
        {
1480
0
          fputc ('\\', dat->fh);
1481
0
          if (c == '\r')
1482
0
            fputc ('r', dat->fh);
1483
0
          else if (c == '\n')
1484
0
            fputc ('n', dat->fh);
1485
0
          else
1486
0
            fputc (c, dat->fh);
1487
0
        }
1488
0
      else if (c == '\\' && i + 6 < len && src[i] == 'U' && src[i + 1] == '+'
1489
0
               && ishex (src[i + 2]) && ishex (src[i + 3])
1490
0
               && ishex (src[i + 4]) && ishex (src[i + 5]))
1491
0
        {
1492
0
          fputc ('\\', dat->fh);
1493
0
          fputc ('u', dat->fh);
1494
0
          i += 3;
1495
0
        }
1496
0
      else if (c == '\0')
1497
0
        {
1498
          // see if there's slack after the NUL terminator
1499
0
          if (!has_slack && i == slen)
1500
0
            {
1501
0
              for (size_t j = i; j < len; j++)
1502
0
                if (src[j])
1503
0
                  {
1504
0
                    has_slack = true;
1505
0
                    break;
1506
0
                  }
1507
0
            }
1508
0
          if (has_slack)
1509
0
            fprintf (dat->fh, "\\u0000");
1510
0
          else
1511
0
            {
1512
0
              fputc ('"', dat->fh);
1513
0
              return;
1514
0
            }
1515
0
        }
1516
0
      else if (c < 0x1f)
1517
0
        fprintf (dat->fh, "\\u00%02x", c);
1518
0
      else
1519
0
        fputc (c, dat->fh);
1520
0
    }
1521
0
  fputc ('"', dat->fh);
1522
0
}
1523
1524
// also converts from codepage to utf8
1525
char *
1526
json_cquote (char *restrict dest, const char *restrict src, const size_t len,
1527
             const BITCODE_RS codepage)
1528
0
{
1529
0
  unsigned char c;
1530
0
  unsigned char *s = (unsigned char *)src;
1531
0
  const char *endp = dest + len;
1532
0
  char *d = dest;
1533
0
  char *tmp = NULL;
1534
1535
0
  if (!src)
1536
0
    return (char *)"";
1537
0
  if (strlen (src) && codepage > CP_US_ASCII && codepage <= CP_ANSI_1258)
1538
0
    {
1539
      // may malloc
1540
0
      tmp = bit_TV_to_utf8 ((char *restrict)src, codepage);
1541
0
      if (tmp)
1542
0
        s = (unsigned char *)tmp;
1543
      // else conversion failed. ignore
1544
0
    }
1545
0
  while ((c = *s++))
1546
0
    {
1547
0
      if (dest >= endp)
1548
0
        {
1549
0
          *dest = 0;
1550
0
          if (tmp && tmp != src)
1551
0
            free (tmp);
1552
0
          return d;
1553
0
        }
1554
0
      if (c == '"' && dest + 1 < endp)
1555
0
        {
1556
0
          *dest++ = '\\';
1557
0
          *dest++ = c;
1558
0
        }
1559
0
      else if (c == '\\' && dest + 2 < endp)
1560
0
        {
1561
0
          if (dest + 5 < endp && s[0] == 'U' && s[1] == '+' && ishex (s[2])
1562
0
              && ishex (s[3]) && ishex (s[4]) && ishex (s[5]))
1563
0
            {
1564
0
              *dest++ = '\\';
1565
0
              *dest++ = 'u';
1566
0
              s += 2;
1567
0
            }
1568
0
          else
1569
0
            {
1570
0
              *dest++ = '\\';
1571
0
              *dest++ = c;
1572
0
            }
1573
0
        }
1574
0
      else if (c == '\n' && dest + 1 < endp)
1575
0
        {
1576
0
          *dest++ = '\\';
1577
0
          *dest++ = 'n';
1578
0
        }
1579
0
      else if (c == '\r' && dest + 1 < endp)
1580
0
        {
1581
0
          *dest++ = '\\';
1582
0
          *dest++ = 'r';
1583
0
        }
1584
0
      else if (c < 0x1f && dest + 5 < endp)
1585
0
        {
1586
0
          *dest++ = '\\';
1587
0
          *dest++ = 'u';
1588
0
          *dest++ = '0';
1589
0
          *dest++ = '0';
1590
0
          *dest++ = hex (c >> 4);
1591
0
          *dest++ = hex (c & 0xf);
1592
0
        }
1593
0
      else
1594
0
        *dest++ = c;
1595
0
    }
1596
0
  *dest = 0; // add final delim, skipped above
1597
0
  if (tmp && tmp != src)
1598
0
    free (tmp);
1599
0
  return d;
1600
0
}
1601
1602
static int
1603
json_3dsolid (Bit_Chain *restrict dat, const Dwg_Object *restrict obj,
1604
              Dwg_Entity_3DSOLID *restrict _obj)
1605
0
{
1606
0
  Dwg_Data *dwg = obj->parent;
1607
0
  BITCODE_BL vcount;
1608
0
  BITCODE_BL i;
1609
0
  int error = 0;
1610
1611
0
  FIELD_B (acis_empty, 0);
1612
0
  if (!FIELD_VALUE (acis_empty))
1613
0
    {
1614
0
      char *s, *p;
1615
0
      FIELD_B (unknown, 0);
1616
0
      FIELD_BS (version, 70);
1617
0
      KEY (acis_data);
1618
0
      ARRAY;
1619
0
      s = p = (char *)_obj->acis_data;
1620
0
      if (!p)
1621
0
        {
1622
0
          FIRSTPREFIX fprintf (dat->fh, "\"\"");
1623
0
        }
1624
0
      else if (_obj->version < 2)
1625
0
        { // split lines by \n
1626
0
          for (; *p; p++)
1627
0
            {
1628
0
              char buf[256]; // acis lines are not much longer
1629
              // and skip the final ^M
1630
0
              if ((*p == '\r' || *p == '\n') && p - s < 256)
1631
0
                {
1632
0
                  FIRSTPREFIX fprintf (dat->fh, "\"%.*s\"", (int)(p - s), s);
1633
                  // json_cquote (buf, s, p - s, dat->codepage));
1634
0
                  if (*p == '\r' && *(p + 1) == '\n')
1635
0
                    p++;
1636
0
                  s = p + 1;
1637
0
                }
1638
0
            }
1639
          // the remainder
1640
0
          if (s != p && *s)
1641
0
            {
1642
0
              FIRSTPREFIX VALUE_TEXT (s);
1643
0
            }
1644
0
        }
1645
0
      else // version 2, SAB. split into two lines for easier identification
1646
0
        {
1647
0
          FIRSTPREFIX fprintf (dat->fh, "\"%.*s\"", 15, _obj->acis_data);
1648
0
          FIRSTPREFIX VALUE_BINARY (&_obj->acis_data[15], _obj->sab_size - 15,
1649
0
                                    1);
1650
0
        }
1651
0
      ENDARRAY;
1652
0
      if (_obj->encr_sat_data) // dxfin/out may create this for SAB
1653
0
        {
1654
0
          KEY (encr_sat_data);
1655
0
          ARRAY;
1656
0
          for (i = 0; i < FIELD_VALUE (num_blocks); i++)
1657
0
            {
1658
0
              FIRSTPREFIX VALUE_BINARY (FIELD_VALUE (encr_sat_data[i]),
1659
0
                                        FIELD_VALUE (block_size[i]), 1);
1660
0
            }
1661
0
          ENDARRAY;
1662
0
        }
1663
1664
0
      COMMON_ENTITY_HANDLE_DATA;
1665
0
      if (FIELD_VALUE (version) > 1)
1666
0
        {
1667
0
          SINCE (R_2007a)
1668
0
          {
1669
0
            FIELD_HANDLE (history_id, 0, 350);
1670
0
          }
1671
0
        }
1672
0
    }
1673
0
  return error;
1674
0
}
1675
1676
/* returns 0 on success
1677
 */
1678
static int
1679
dwg_json_variable_type (Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
1680
                        Dwg_Object *restrict obj)
1681
{
1682
  int i;
1683
  Dwg_Class *klass;
1684
  int is_entity;
1685
1686
  i = obj->type - 500;
1687
  if (i < 0 || i >= (int)dwg->num_classes)
1688
    return DWG_ERR_INVALIDTYPE;
1689
  if (obj->fixedtype == DWG_TYPE_UNKNOWN_ENT
1690
      || obj->fixedtype == DWG_TYPE_UNKNOWN_OBJ)
1691
    return DWG_ERR_UNHANDLEDCLASS;
1692
1693
  klass = &dwg->dwg_class[i];
1694
  if (!klass || !klass->dxfname)
1695
    return DWG_ERR_INTERNALERROR;
1696
  is_entity = dwg_class_is_entity (klass);
1697
1698
  // clang-format off
1699
  #include "classes.inc"
1700
  // clang-format on
1701
1702
  return DWG_ERR_UNHANDLEDCLASS;
1703
}
1704
1705
static int
1706
dwg_json_object (Bit_Chain *restrict dat, Dwg_Object *restrict obj)
1707
0
{
1708
0
  int error = 0;
1709
0
  unsigned int type;
1710
1711
0
  if (!obj || !obj->parent || !obj->tio.entity)
1712
0
    return DWG_ERR_INTERNALERROR;
1713
0
  type = (unsigned int)obj->fixedtype;
1714
0
  switch (obj->fixedtype)
1715
0
    {
1716
0
    case DWG_TYPE_TEXT:
1717
0
      return dwg_json_TEXT (dat, obj);
1718
0
    case DWG_TYPE_ATTRIB:
1719
0
      return dwg_json_ATTRIB (dat, obj);
1720
0
    case DWG_TYPE_ATTDEF:
1721
0
      return dwg_json_ATTDEF (dat, obj);
1722
0
    case DWG_TYPE_BLOCK:
1723
0
      return dwg_json_BLOCK (dat, obj);
1724
0
    case DWG_TYPE_ENDBLK:
1725
0
      return dwg_json_ENDBLK (dat, obj);
1726
0
    case DWG_TYPE_SEQEND:
1727
0
      return dwg_json_SEQEND (dat, obj);
1728
0
    case DWG_TYPE_INSERT:
1729
0
      return dwg_json_INSERT (dat, obj);
1730
0
    case DWG_TYPE_MINSERT:
1731
0
      return dwg_json_MINSERT (dat, obj);
1732
0
    case DWG_TYPE_VERTEX_2D:
1733
0
      return dwg_json_VERTEX_2D (dat, obj);
1734
0
    case DWG_TYPE_VERTEX_3D:
1735
0
      return dwg_json_VERTEX_3D (dat, obj);
1736
0
    case DWG_TYPE_VERTEX_MESH:
1737
0
      return dwg_json_VERTEX_MESH (dat, obj);
1738
0
    case DWG_TYPE_VERTEX_PFACE:
1739
0
      return dwg_json_VERTEX_PFACE (dat, obj);
1740
0
    case DWG_TYPE_VERTEX_PFACE_FACE:
1741
0
      return dwg_json_VERTEX_PFACE_FACE (dat, obj);
1742
0
    case DWG_TYPE_POLYLINE_2D:
1743
0
      return dwg_json_POLYLINE_2D (dat, obj);
1744
0
    case DWG_TYPE_POLYLINE_3D:
1745
0
      return dwg_json_POLYLINE_3D (dat, obj);
1746
0
    case DWG_TYPE_ARC:
1747
0
      return dwg_json_ARC (dat, obj);
1748
0
    case DWG_TYPE_CIRCLE:
1749
0
      return dwg_json_CIRCLE (dat, obj);
1750
0
    case DWG_TYPE_LINE:
1751
0
      return dwg_json_LINE (dat, obj);
1752
0
    case DWG_TYPE_DIMENSION_ORDINATE:
1753
0
      return dwg_json_DIMENSION_ORDINATE (dat, obj);
1754
0
    case DWG_TYPE_DIMENSION_LINEAR:
1755
0
      return dwg_json_DIMENSION_LINEAR (dat, obj);
1756
0
    case DWG_TYPE_DIMENSION_ALIGNED:
1757
0
      return dwg_json_DIMENSION_ALIGNED (dat, obj);
1758
0
    case DWG_TYPE_DIMENSION_ANG3PT:
1759
0
      return dwg_json_DIMENSION_ANG3PT (dat, obj);
1760
0
    case DWG_TYPE_DIMENSION_ANG2LN:
1761
0
      return dwg_json_DIMENSION_ANG2LN (dat, obj);
1762
0
    case DWG_TYPE_DIMENSION_RADIUS:
1763
0
      return dwg_json_DIMENSION_RADIUS (dat, obj);
1764
0
    case DWG_TYPE_DIMENSION_DIAMETER:
1765
0
      return dwg_json_DIMENSION_DIAMETER (dat, obj);
1766
0
    case DWG_TYPE_POINT:
1767
0
      return dwg_json_POINT (dat, obj);
1768
0
    case DWG_TYPE__3DFACE:
1769
0
      return dwg_json__3DFACE (dat, obj);
1770
0
    case DWG_TYPE_POLYLINE_PFACE:
1771
0
      return dwg_json_POLYLINE_PFACE (dat, obj);
1772
0
    case DWG_TYPE_POLYLINE_MESH:
1773
0
      return dwg_json_POLYLINE_MESH (dat, obj);
1774
0
    case DWG_TYPE_SOLID:
1775
0
      return dwg_json_SOLID (dat, obj);
1776
0
    case DWG_TYPE_TRACE:
1777
0
      return dwg_json_TRACE (dat, obj);
1778
0
    case DWG_TYPE_SHAPE:
1779
0
      return dwg_json_SHAPE (dat, obj);
1780
0
    case DWG_TYPE_VIEWPORT:
1781
0
      return dwg_json_VIEWPORT (dat, obj);
1782
0
    case DWG_TYPE_ELLIPSE:
1783
0
      return dwg_json_ELLIPSE (dat, obj);
1784
0
    case DWG_TYPE_SPLINE:
1785
0
      return dwg_json_SPLINE (dat, obj);
1786
0
    case DWG_TYPE_REGION:
1787
0
      return dwg_json_REGION (dat, obj);
1788
0
    case DWG_TYPE__3DSOLID:
1789
0
      return dwg_json__3DSOLID (dat, obj);
1790
0
    case DWG_TYPE_BODY:
1791
0
      return dwg_json_BODY (dat, obj);
1792
0
    case DWG_TYPE_RAY:
1793
0
      return dwg_json_RAY (dat, obj);
1794
0
    case DWG_TYPE_XLINE:
1795
0
      return dwg_json_XLINE (dat, obj);
1796
0
    case DWG_TYPE_DICTIONARY:
1797
0
      return dwg_json_DICTIONARY (dat, obj);
1798
0
    case DWG_TYPE_MTEXT:
1799
0
      return dwg_json_MTEXT (dat, obj);
1800
0
    case DWG_TYPE_LEADER:
1801
0
      return dwg_json_LEADER (dat, obj);
1802
0
    case DWG_TYPE_TOLERANCE:
1803
0
      return dwg_json_TOLERANCE (dat, obj);
1804
0
    case DWG_TYPE_MLINE:
1805
0
      return dwg_json_MLINE (dat, obj);
1806
0
    case DWG_TYPE_BLOCK_CONTROL:
1807
0
      return dwg_json_BLOCK_CONTROL (dat, obj);
1808
0
    case DWG_TYPE_BLOCK_HEADER:
1809
      /*
1810
      if (dat->version <= R_12
1811
          && obj->tio.object
1812
          && obj->tio.object->tio.BLOCK_HEADER
1813
          && obj->tio.object->tio.BLOCK_HEADER->name
1814
          && strEQc (obj->tio.object->tio.BLOCK_HEADER->name, "*MODEL_SPACE"))
1815
        {
1816
          LOG_TRACE ("Skip *MODEL_SPACE\n");
1817
          return 0;
1818
        }
1819
      */
1820
0
      return dwg_json_BLOCK_HEADER (dat, obj);
1821
0
    case DWG_TYPE_LAYER_CONTROL:
1822
0
      return dwg_json_LAYER_CONTROL (dat, obj);
1823
0
    case DWG_TYPE_LAYER:
1824
0
      return dwg_json_LAYER (dat, obj);
1825
0
    case DWG_TYPE_STYLE_CONTROL:
1826
0
      return dwg_json_STYLE_CONTROL (dat, obj);
1827
0
    case DWG_TYPE_STYLE:
1828
0
      return dwg_json_STYLE (dat, obj);
1829
0
    case DWG_TYPE_LTYPE_CONTROL:
1830
0
      return dwg_json_LTYPE_CONTROL (dat, obj);
1831
0
    case DWG_TYPE_LTYPE:
1832
0
      return dwg_json_LTYPE (dat, obj);
1833
0
    case DWG_TYPE_VIEW_CONTROL:
1834
0
      return dwg_json_VIEW_CONTROL (dat, obj);
1835
0
    case DWG_TYPE_VIEW:
1836
0
      return dwg_json_VIEW (dat, obj);
1837
0
    case DWG_TYPE_UCS_CONTROL:
1838
0
      return dwg_json_UCS_CONTROL (dat, obj);
1839
0
    case DWG_TYPE_UCS:
1840
0
      return dwg_json_UCS (dat, obj);
1841
0
    case DWG_TYPE_VPORT_CONTROL:
1842
0
      return dwg_json_VPORT_CONTROL (dat, obj);
1843
0
    case DWG_TYPE_VPORT:
1844
0
      return dwg_json_VPORT (dat, obj);
1845
0
    case DWG_TYPE_APPID_CONTROL:
1846
0
      return dwg_json_APPID_CONTROL (dat, obj);
1847
0
    case DWG_TYPE_APPID:
1848
0
      return dwg_json_APPID (dat, obj);
1849
0
    case DWG_TYPE_DIMSTYLE_CONTROL:
1850
0
      return dwg_json_DIMSTYLE_CONTROL (dat, obj);
1851
0
    case DWG_TYPE_DIMSTYLE:
1852
0
      return dwg_json_DIMSTYLE (dat, obj);
1853
0
    case DWG_TYPE_VX_CONTROL:
1854
0
      return dwg_json_VX_CONTROL (dat, obj);
1855
0
    case DWG_TYPE_VX_TABLE_RECORD:
1856
0
      return dwg_json_VX_TABLE_RECORD (dat, obj);
1857
0
    case DWG_TYPE_GROUP:
1858
0
      return dwg_json_GROUP (dat, obj);
1859
0
    case DWG_TYPE_MLINESTYLE:
1860
0
      return dwg_json_MLINESTYLE (dat, obj);
1861
0
    case DWG_TYPE_OLE2FRAME:
1862
0
      return dwg_json_OLE2FRAME (dat, obj);
1863
0
    case DWG_TYPE_DUMMY:
1864
0
      return dwg_json_DUMMY (dat, obj);
1865
0
    case DWG_TYPE_LONG_TRANSACTION:
1866
0
      return dwg_json_LONG_TRANSACTION (dat, obj);
1867
0
    case DWG_TYPE_LWPOLYLINE:
1868
0
      return dwg_json_LWPOLYLINE (dat, obj);
1869
0
    case DWG_TYPE_HATCH:
1870
0
      return dwg_json_HATCH (dat, obj);
1871
0
    case DWG_TYPE_XRECORD:
1872
0
      return dwg_json_XRECORD (dat, obj);
1873
0
    case DWG_TYPE_PLACEHOLDER:
1874
0
      return dwg_json_PLACEHOLDER (dat, obj);
1875
0
    case DWG_TYPE_PROXY_ENTITY:
1876
0
      return dwg_json_PROXY_ENTITY (dat, obj);
1877
0
    case DWG_TYPE_PROXY_OBJECT:
1878
0
      return dwg_json_PROXY_OBJECT (dat, obj);
1879
0
    case DWG_TYPE_OLEFRAME:
1880
0
      return dwg_json_OLEFRAME (dat, obj);
1881
0
    case DWG_TYPE_VBA_PROJECT:
1882
0
      LOG_ERROR ("Unhandled Object VBA_PROJECT. Has its own section\n");
1883
      // dwg_json_VBA_PROJECT(dat, obj);
1884
0
      break;
1885
0
    case DWG_TYPE_REPEAT:
1886
0
      return dwg_json_REPEAT (dat, obj);
1887
0
    case DWG_TYPE_ENDREP:
1888
0
      return dwg_json_ENDREP (dat, obj);
1889
0
    case DWG_TYPE__3DLINE:
1890
0
      return dwg_json__3DLINE (dat, obj);
1891
0
    case DWG_TYPE_LOAD:
1892
0
      return dwg_json_LOAD (dat, obj);
1893
0
    case DWG_TYPE_JUMP:
1894
0
      return dwg_json_JUMP (dat, obj);
1895
0
    case DWG_TYPE_LAYOUT:
1896
0
      return dwg_json_LAYOUT (dat, obj);
1897
0
    default:
1898
0
      if (obj->type != 0 && obj->type == obj->parent->layout_type)
1899
0
        {
1900
0
          return dwg_json_LAYOUT (dat, obj);
1901
0
        }
1902
      /* > 500 */
1903
0
      else if (DWG_ERR_UNHANDLEDCLASS
1904
0
               & (error = dwg_json_variable_type (obj->parent, dat, obj)))
1905
0
        {
1906
0
          Dwg_Data *dwg = obj->parent;
1907
0
          int is_entity = 0;
1908
0
          int i = obj->type - 500;
1909
0
          Dwg_Class *klass = NULL;
1910
0
          int num_bytes = obj->num_unknown_bits / 8;
1911
0
          if (obj->num_unknown_bits & 8)
1912
0
            num_bytes++;
1913
1914
0
          if (obj->fixedtype == DWG_TYPE_FREED)
1915
0
            goto invalid_type;
1916
0
          if (i >= 0 && i < (int)dwg->num_classes
1917
0
              && obj->fixedtype < DWG_TYPE_FREED)
1918
0
            {
1919
0
              klass = &dwg->dwg_class[i];
1920
0
              is_entity = dwg_class_is_entity (klass);
1921
0
            }
1922
0
          else
1923
0
            {
1924
0
              if (obj->fixedtype == DWG_TYPE_UNKNOWN_ENT)
1925
0
                is_entity = 1;
1926
0
            }
1927
          // properly dwg_decode_object/_entity for eed, reactors, xdic
1928
0
          if (!is_entity)
1929
0
            {
1930
0
              error |= dwg_json_UNKNOWN_OBJ (dat, obj);
1931
0
              return error;
1932
0
            }
1933
0
          else
1934
0
            {
1935
0
              error |= dwg_json_UNKNOWN_ENT (dat, obj);
1936
0
              return error;
1937
0
            }
1938
0
        }
1939
0
      else
1940
0
        return 0;
1941
0
    }
1942
0
invalid_type:
1943
0
  LOG_WARN ("Unknown object, skipping eed/reactors/xdic/...");
1944
0
  FIELD_TEXT (object, obj->name);
1945
0
  if (obj->dxfname && strNE (obj->dxfname, obj->name))
1946
0
    FIELD_TEXT (dxfname, obj->dxfname);
1947
0
  _FIELD (index, RL, 0);
1948
0
  _FIELD (type, RL, 0);
1949
0
  KEY (handle);
1950
0
  VALUE_H (obj->handle, 5);
1951
0
  _FIELD (size, RL, 0);
1952
0
  _FIELD (bitsize, BL, 0);
1953
0
  return DWG_ERR_INVALIDTYPE;
1954
0
}
1955
1956
static int
1957
json_fileheader_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1958
0
{
1959
0
  Dwg_Header *_obj = &dwg->header;
1960
0
  Dwg_Object *obj = NULL;
1961
0
  int i;
1962
1963
0
  RECORD (FILEHEADER); // single hash
1964
0
  KEY (version);
1965
0
  fprintf (dat->fh, "\"%s\"", dwg_version_codes (dwg->header.version));
1966
  // clang-format off
1967
0
  #include "header.spec"
1968
  // clang-format on
1969
0
  ENDRECORD ();
1970
0
  return 0;
1971
0
}
1972
1973
AFL_GCC_TOOBIG
1974
static int
1975
json_preR13_header_write_private (Bit_Chain *restrict dat,
1976
                                  Dwg_Data *restrict dwg)
1977
0
{
1978
0
  Dwg_Header_Variables *_obj = &dwg->header_vars;
1979
0
  Dwg_Object *obj = NULL;
1980
0
  char buf[4096];
1981
0
  double ms;
1982
0
  int error = 0;
1983
0
  const char *codepage = "ANSI_1252";
1984
1985
  // clang-format off
1986
0
  #include "header_variables_r11.spec"
1987
  // clang-format on
1988
0
  return error;
1989
0
}
1990
1991
static int
1992
json_header_write_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1993
0
{
1994
0
  Dwg_Header_Variables *_obj = &dwg->header_vars;
1995
0
  Dwg_Object *obj = NULL;
1996
0
  char buf[4096];
1997
0
  double ms;
1998
0
  int error = 0;
1999
0
  const char *codepage
2000
0
      = (dwg->header.codepage == 30 || dwg->header.codepage == 0) ? "ANSI_1252"
2001
0
        : (dwg->header.version >= R_2007)                         ? "UTF-8"
2002
0
                                          : "ANSI_1252";
2003
2004
  // clang-format off
2005
0
  #include "header_variables.spec"
2006
  // clang-format on
2007
0
  return error;
2008
0
}
2009
AFL_GCC_POP
2010
2011
static int
2012
json_header_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2013
0
{
2014
0
  int error = 0;
2015
0
  RECORD (HEADER); // single hash
2016
  // separate funcs to catch the return, and end with ENDRECORD
2017
0
  PRE (R_13b1)
2018
0
  {
2019
    // if (dat->from_version >= R_13b1)
2020
    //   downgrade_preR13_header_variables (dat, dwg);
2021
0
    error = json_preR13_header_write_private (dat, dwg);
2022
0
  }
2023
0
  LATER_VERSIONS
2024
0
  {
2025
0
    error = json_header_write_private (dat, dwg);
2026
0
  }
2027
0
  ENDRECORD ();
2028
0
  return error;
2029
0
}
2030
2031
static int
2032
json_classes_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2033
0
{
2034
0
  BITCODE_BS i;
2035
2036
0
  SECTION (CLASSES); // list of classes
2037
0
  for (i = 0; i < dwg->num_classes; i++)
2038
0
    {
2039
0
      Dwg_Class *_obj = &dwg->dwg_class[i];
2040
0
      FIRSTPREFIX HASH;
2041
0
      FIELD_BS (number, 0);
2042
0
      FIELD_TV (dxfname, 1);
2043
0
      FIELD_T (cppname, 2);
2044
0
      FIELD_T (appname, 3);
2045
0
      FIELD_BS (proxyflag, 90);
2046
0
      FIELD_BL (num_instances, 91);
2047
0
      FIELD_B (is_zombie, 280);
2048
0
      FIELD_BS (item_class_id, 281);
2049
0
      ENDHASH
2050
0
      CLEARFIRST;
2051
0
    }
2052
0
  ENDSEC ();
2053
0
  return 0;
2054
0
}
2055
2056
// unused
2057
static int
2058
json_tables_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2059
0
{
2060
0
  int max_id = SECTION_VIEW;
2061
0
  VERSIONS (R_10, R_11)
2062
0
  {
2063
0
    max_id = SECTION_DIMSTYLE;
2064
0
  }
2065
0
  VERSIONS (R_11, R_13b1)
2066
0
  {
2067
0
    max_id = SECTION_VX;
2068
0
  }
2069
0
  CLEARFIRST;
2070
0
  SECTION (TABLES);
2071
  // FIXME __cplusplus
2072
0
  for (int id = SECTION_BLOCK; id <= max_id; id++)
2073
0
    {
2074
0
      int error;
2075
0
      Dwg_Section *tbl = &dwg->header.section[id];
2076
0
      BITCODE_RL num = tbl->objid_r11;
2077
2078
0
      switch (id)
2079
0
        {
2080
0
        case SECTION_BLOCK:
2081
0
          SECTION (BLOCK);
2082
0
          {
2083
0
            Dwg_Section *_obj = tbl;
2084
0
            FIELD_RL (size, 0);
2085
0
            FIELD_RL (number, 0);
2086
0
            PRE (R_13b1)
2087
0
            {
2088
0
              FIELD_RS (flags_r11, 0);
2089
0
            }
2090
0
            FIELD_RLL (address, 0);
2091
0
          }
2092
0
          for (BITCODE_RLd i = 0; i < (BITCODE_RLd)tbl->number; i++)
2093
0
            {
2094
0
              Dwg_Object *obj = &dwg->object[num + i];
2095
0
              Dwg_Object_BLOCK_HEADER *_obj
2096
0
                  = obj->tio.object->tio.BLOCK_HEADER;
2097
0
              if (!_obj || obj->fixedtype != DWG_TYPE_BLOCK_HEADER)
2098
0
                {
2099
0
                  LOG_ERROR ("Missing BLOCK_HEADER object at [%u]\n", num + i);
2100
0
                  return DWG_ERR_CRITICAL;
2101
0
                }
2102
0
              PRE (R_13b1)
2103
0
              {
2104
0
                if (strEQc (_obj->name, "*MODEL_SPACE"))
2105
0
                  {
2106
0
                    LOG_TRACE ("Skip *MODEL_SPACE\n");
2107
0
                    continue;
2108
0
                  }
2109
0
              }
2110
0
              RECORD (BLOCK_HEADER);
2111
0
              FIELD_RC (flag, 70);
2112
0
              FIELD_TFv (name, 32, 2);
2113
0
              SINCE (R_11)
2114
0
              {
2115
0
                FIELD_RSd (used, 0); // -1
2116
0
              }
2117
0
              PRE (R_13b1)
2118
0
              {
2119
0
                FIELD_RL (block_offset_r11, 0);
2120
0
              }
2121
0
              LATER_VERSIONS
2122
0
              {
2123
0
                FIELD_RC (block_scaling, 0);
2124
0
              }
2125
0
              SINCE (R_11)
2126
0
              {
2127
0
                FIELD_HANDLE (block_entity, 2, 0);
2128
0
                FIELD_RC (flag2, 0);
2129
0
                FIELD_RC (unknown_r11, 0);
2130
0
              }
2131
0
              ENDRECORD ();
2132
0
            }
2133
0
          ENDSEC ();
2134
0
          break;
2135
0
        case SECTION_LAYER:
2136
0
          SECTION (LAYER);
2137
0
          {
2138
0
            Dwg_Section *_obj = tbl;
2139
0
            FIELD_RL (size, 0);
2140
0
            FIELD_RL (number, 0);
2141
0
            PRE (R_13b1)
2142
0
            {
2143
0
              FIELD_RS (flags_r11, 0);
2144
0
            }
2145
0
            FIELD_RLL (address, 0);
2146
0
          }
2147
0
          for (BITCODE_RLd i = 0; i < (BITCODE_RLd)tbl->number; i++)
2148
0
            {
2149
0
              Dwg_Object *obj = &dwg->object[num + i];
2150
0
              Dwg_Object_LAYER *_obj = obj->tio.object->tio.LAYER;
2151
0
              RECORD (LAYER);
2152
0
              FIELD_RC (flag, 70);
2153
0
              FIELD_TFv (name, 32, 2);
2154
0
              FIELD_CMC (color, 62); // off if negative
2155
0
              FIELD_HANDLE (ltype, 2, 6);
2156
0
              ENDRECORD ();
2157
0
            }
2158
0
          ENDSEC ();
2159
0
          break;
2160
0
        case SECTION_STYLE:
2161
0
          SECTION (STYLE);
2162
0
          {
2163
0
            Dwg_Section *_obj = tbl;
2164
0
            FIELD_RL (size, 0);
2165
0
            FIELD_RL (number, 0);
2166
0
            PRE (R_13b1)
2167
0
            {
2168
0
              FIELD_RS (flags_r11, 0);
2169
0
            }
2170
0
            FIELD_RLL (address, 0);
2171
0
          }
2172
0
          for (BITCODE_RLd i = 0; i < (BITCODE_RLd)tbl->number; i++)
2173
0
            {
2174
0
              Dwg_Object *obj = &dwg->object[num + i];
2175
0
              Dwg_Object_STYLE *_obj = obj->tio.object->tio.STYLE;
2176
0
              RECORD (STYLE);
2177
0
              FIELD_RC (flag, 70);
2178
0
              FIELD_TFv (name, 32, 2);
2179
2180
0
              FIELD_RD (text_size, 40); // ok
2181
0
              FIELD_RD (width_factor, 41);
2182
0
              FIELD_RD (oblique_angle, 50);
2183
0
              FIELD_RC (generation, 71);
2184
0
              FIELD_RD (last_height, 42);
2185
0
              FIELD_TFv (font_file, 64, 3);    // 8ed
2186
0
              FIELD_TFv (bigfont_file, 64, 4); // 92d
2187
0
              ENDRECORD ();
2188
0
            }
2189
0
          ENDSEC ();
2190
0
          break;
2191
0
        case SECTION_LTYPE:
2192
0
          SECTION (LTYPE);
2193
0
          {
2194
0
            Dwg_Section *_obj = tbl;
2195
0
            FIELD_RL (size, 0);
2196
0
            FIELD_RL (number, 0);
2197
0
            PRE (R_13b1)
2198
0
            {
2199
0
              FIELD_RS (flags_r11, 0);
2200
0
            }
2201
0
            FIELD_RLL (address, 0);
2202
0
          }
2203
0
          for (BITCODE_RLd i = 0; i < (BITCODE_RLd)tbl->number; i++)
2204
0
            {
2205
0
              BITCODE_BL vcount;
2206
0
              Dwg_Object *obj = &dwg->object[num + i];
2207
0
              Dwg_Object_LTYPE *_obj = obj->tio.object->tio.LTYPE;
2208
0
              RECORD (LTYPE);
2209
0
              FIELD_RC (flag, 70);
2210
0
              FIELD_TFv (name, 32, 2);
2211
0
              FIELD_RS (used, 0);
2212
2213
0
              FIELD_TFv (description, 48, 3);
2214
0
              FIELD_RC (alignment, 72);
2215
0
              FIELD_RCu (numdashes, 73);
2216
0
              FIELD_RD (pattern_len, 40);
2217
0
              FIELD_VECTOR_INL (dashes_r11, RD, 12, 49);
2218
0
              ENDRECORD ();
2219
0
            }
2220
0
          ENDSEC ();
2221
0
          break;
2222
0
        case SECTION_VIEW:
2223
0
          SECTION (VIEW);
2224
0
          {
2225
0
            Dwg_Section *_obj = tbl;
2226
0
            FIELD_RL (size, 0);
2227
0
            FIELD_RL (number, 0);
2228
0
            PRE (R_13b1)
2229
0
            {
2230
0
              FIELD_RS (flags_r11, 0);
2231
0
            }
2232
0
            FIELD_RLL (address, 0);
2233
0
          }
2234
0
          for (BITCODE_RLd i = 0; i < (BITCODE_RLd)tbl->number; i++)
2235
0
            {
2236
0
              BITCODE_BL vcount;
2237
0
              Dwg_Object *obj = &dwg->object[num + i];
2238
0
              Dwg_Object_VIEW *_obj = obj->tio.object->tio.VIEW;
2239
0
              RECORD (VIEW);
2240
0
              FIELD_RC (flag, 70);
2241
0
              FIELD_TFv (name, 32, 2);
2242
0
              FIELD_RS (used, 0);
2243
2244
0
              FIELD_RD (VIEWSIZE, 40);
2245
0
              FIELD_2RD (VIEWCTR, 10);
2246
0
              FIELD_RD (view_width, 41);
2247
0
              FIELD_3RD (view_target, 12);
2248
0
              FIELD_3RD (VIEWDIR, 11);
2249
0
              FIELD_CAST (VIEWMODE, RS, 4BITS, 71);
2250
0
              FIELD_RD (lens_length, 42);
2251
0
              FIELD_RD (front_clip_z, 43);
2252
0
              FIELD_RD (back_clip_z, 44);
2253
0
              FIELD_RD (twist_angle, 50);
2254
0
              ENDRECORD ();
2255
0
            }
2256
0
          ENDSEC ();
2257
0
          break;
2258
0
        case SECTION_UCS:
2259
0
          SECTION (UCS);
2260
0
          {
2261
0
            Dwg_Section *_obj = tbl;
2262
0
            FIELD_RL (size, 0);
2263
0
            FIELD_RL (number, 0);
2264
0
            PRE (R_13b1)
2265
0
            {
2266
0
              FIELD_RS (flags_r11, 0);
2267
0
            }
2268
0
            FIELD_RLL (address, 0);
2269
0
          }
2270
0
          for (BITCODE_RLd i = 0; i < (BITCODE_RLd)tbl->number; i++)
2271
0
            {
2272
0
              BITCODE_BL vcount;
2273
0
              Dwg_Object *obj = &dwg->object[num + i];
2274
0
              Dwg_Object_UCS *_obj = obj->tio.object->tio.UCS;
2275
0
              RECORD (UCS);
2276
0
              FIELD_RC (flag, 70);
2277
0
              FIELD_TFv (name, 32, 2);
2278
0
              FIELD_RS (used, 0);
2279
2280
0
              FIELD_2RD (ucsorg, 10);
2281
0
              FIELD_2RD (ucsxdir, 11);
2282
0
              FIELD_2RD (ucsydir, 12);
2283
0
              ENDRECORD ();
2284
0
            }
2285
0
          ENDSEC ();
2286
0
          break;
2287
0
        default:
2288
0
          LOG_WARN ("Missing TABLE %u", id)
2289
0
        }
2290
0
      CLEARFIRST;
2291
0
    }
2292
0
  ENDSEC ();
2293
0
  return 0;
2294
0
}
2295
2296
static int
2297
json_objects_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2298
0
{
2299
0
  BITCODE_BL i;
2300
2301
0
  CLEARFIRST;
2302
0
  SECTION (OBJECTS);
2303
0
  for (i = 0; i < dwg->num_objects; i++)
2304
0
    {
2305
0
      int error;
2306
0
      Dwg_Object *obj = &dwg->object[i];
2307
0
      FIRSTPREFIX HASH;
2308
0
      error = dwg_json_object (dat, obj);
2309
0
      ENDHASH
2310
0
      CLEARFIRST;
2311
0
    }
2312
0
  ENDSEC ();
2313
0
  return 0;
2314
0
}
2315
2316
#if 0
2317
/* The object map/handles section */
2318
static int
2319
json_handles_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2320
{
2321
  BITCODE_BL j;
2322
  CLEARFIRST;
2323
  SECTION (HANDLES);
2324
  for (j = 0; j < dwg->num_objects; j++)
2325
    {
2326
      Dwg_Object *obj = &dwg->object[j];
2327
      // handle => abs. offset
2328
      // TODO: The real HANDLES section omap has handleoffset (deleted holes) and addressoffset
2329
      FIRSTPREFIX fprintf (dat->fh, "[%lu,%s%lu]", obj->handle.value, JSON_SPC, obj->address);
2330
    }
2331
  ENDSEC ();
2332
  return 0;
2333
}
2334
#endif
2335
2336
static int
2337
json_thumbnail_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2338
0
{
2339
0
  Bit_Chain *_obj = (Bit_Chain *)&dwg->thumbnail;
2340
0
  if (_obj->chain && _obj->size && _obj->size > 10)
2341
0
    {
2342
      /* SECTION_PREVIEW includes the sentinel.
2343
         _obj->byte is at the BMP offset, via dwg_bmp */
2344
0
      if (dwg->header.from_version >= R_2004)
2345
0
        _obj->chain += 16; /* skip the sentinel */
2346
0
      KEY (THUMBNAILIMAGE);
2347
0
      HASH;
2348
0
      FIRSTPREFIX fprintf (dat->fh, "\"size\":%s%" PRIuSIZE, JSON_SPC,
2349
0
                           _obj->size);
2350
0
      FIELD_BINARY (chain, _obj->size, 310);
2351
0
      if (dwg->header.from_version >= R_2004)
2352
0
        _obj->chain -= 16; /* undo for free */
2353
0
      ENDHASH;
2354
0
    }
2355
0
  return 0;
2356
0
}
2357
2358
static int
2359
json_section_r2004fileheader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2360
0
{
2361
0
  Dwg_R2004_Header *_obj = &dwg->fhdr.r2004_header;
2362
0
  Dwg_Object *obj = NULL;
2363
0
  int i;
2364
2365
0
  RECORD (R2004_Header); // single hash
2366
2367
  // clang-format off
2368
0
  #include "r2004_file_header.spec"
2369
  // clang-format on
2370
0
  ENDRECORD ();
2371
0
  return 0;
2372
0
}
2373
2374
static int
2375
json_section_r2007fileheader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2376
0
{
2377
0
  Dwg_R2007_Header *_obj = &dwg->fhdr.r2007_file_header;
2378
0
  Dwg_Object *obj = NULL;
2379
0
  int i;
2380
2381
0
  RECORD (R2007_Header); // single hash
2382
0
  FIELD_RLL (header_size, 0);
2383
0
  FIELD_RLL (file_size, 0);
2384
0
  FIELD_RLL (pages_map_crc_compressed, 0);
2385
0
  FIELD_RLL (pages_map_correction, 0);
2386
0
  FIELD_RLL (pages_map_crc_seed, 0);
2387
0
  FIELD_RLL (pages_map2_offset, 0);
2388
0
  FIELD_RLL (pages_map2_id, 0);
2389
0
  FIELD_RLL (pages_map_offset, 0);
2390
0
  FIELD_RLL (pages_map_id, 0);
2391
0
  FIELD_RLL (header2_offset, 0);
2392
0
  FIELD_RLL (pages_map_size_comp, 0);
2393
0
  FIELD_RLL (pages_map_size_uncomp, 0);
2394
0
  FIELD_RLL (pages_amount, 0);
2395
0
  FIELD_RLL (pages_maxid, 0);
2396
0
  FIELD_RLL (unknown1, 0);
2397
0
  FIELD_RLL (unknown2, 0);
2398
0
  FIELD_RLL (pages_map_crc_uncomp, 0);
2399
0
  FIELD_RLL (unknown3, 0);
2400
0
  FIELD_RLL (unknown4, 0);
2401
0
  FIELD_RLL (unknown5, 0);
2402
0
  FIELD_RLL (num_sections, 0);
2403
0
  FIELD_RLL (sections_map_crc_uncomp, 0);
2404
0
  FIELD_RLL (sections_map_size_comp, 0);
2405
0
  FIELD_RLL (sections_map2_id, 0);
2406
0
  FIELD_RLL (sections_map_id, 0);
2407
0
  FIELD_RLL (sections_map_size_uncomp, 0);
2408
0
  FIELD_RLL (sections_map_crc_comp, 0);
2409
0
  FIELD_RLL (sections_map_correction, 0);
2410
0
  FIELD_RLL (sections_map_crc_seed, 0);
2411
0
  FIELD_RLL (stream_version, 0);
2412
0
  FIELD_RLL (crc_seed, 0);
2413
0
  FIELD_RLL (crc_seed_encoded, 0);
2414
0
  FIELD_RLL (random_seed, 0);
2415
0
  FIELD_RLL (header_crc, 0);
2416
0
  ENDRECORD ();
2417
2418
0
  return 0;
2419
0
}
2420
2421
static int
2422
json_section_summary (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2423
0
{
2424
0
  Dwg_SummaryInfo *_obj = &dwg->summaryinfo;
2425
0
  Dwg_Object *obj = NULL;
2426
0
  int error = 0;
2427
2428
0
  RECORD (SummaryInfo); // single hash
2429
  // clang-format off
2430
0
  #include "summaryinfo.spec"
2431
  // clang-format on
2432
0
  ENDRECORD ();
2433
0
  return 0;
2434
0
}
2435
2436
static int
2437
json_section_vbaproject (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2438
0
{
2439
0
  Dwg_VBAProject *_obj = &dwg->vbaproject;
2440
0
  Dwg_Object *obj = NULL;
2441
0
  int error = 0;
2442
2443
0
  RECORD (VBAProject); // single hash
2444
0
  HASH;
2445
  // clang-format off
2446
  //#include "vbaproject.spec"
2447
  // clang-format on
2448
0
  ENDRECORD ();
2449
0
  return 0;
2450
0
}
2451
2452
static int
2453
json_section_appinfo (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2454
0
{
2455
0
  Dwg_AppInfo *_obj = &dwg->appinfo;
2456
0
  Dwg_Object *obj = NULL;
2457
0
  int error = 0;
2458
2459
0
  RECORD (AppInfo); // single hash
2460
2461
  // clang-format off
2462
0
  #include "appinfo.spec"
2463
  // clang-format on
2464
0
  ENDRECORD ();
2465
0
  return 0;
2466
0
}
2467
2468
static int
2469
json_section_appinfohistory (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2470
0
{
2471
0
  Dwg_AppInfoHistory *_obj = &dwg->appinfohistory;
2472
0
  Dwg_Object *obj = NULL;
2473
0
  int error = 0;
2474
2475
0
  RECORD (AppInfoHistory); // single hash
2476
0
  FIRSTPREFIX fprintf (dat->fh, "\"size\":%s%d", JSON_SPC, _obj->size);
2477
0
  FIELD_BINARY (unknown_bits, _obj->size, 0);
2478
  // clang-format off
2479
  //#include "appinfohistory.spec"
2480
  // clang-format on
2481
0
  ENDRECORD ();
2482
0
  return 0;
2483
0
}
2484
2485
static int
2486
json_section_filedeplist (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2487
0
{
2488
0
  Dwg_FileDepList *_obj = &dwg->filedeplist;
2489
0
  Dwg_Object *obj = NULL;
2490
0
  int error = 0;
2491
0
  BITCODE_RL vcount;
2492
2493
0
  RECORD (FileDepList); // single hash
2494
2495
  // clang-format off
2496
0
  #include "filedeplist.spec"
2497
  // clang-format on
2498
0
  ENDRECORD ();
2499
0
  return 0;
2500
0
}
2501
2502
static int
2503
json_section_security (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2504
0
{
2505
0
  Dwg_Security *_obj = &dwg->security;
2506
0
  Dwg_Object *obj = NULL;
2507
0
  int error = 0;
2508
2509
0
  RECORD (Security); // single hash
2510
2511
  // clang-format off
2512
0
  #include "security.spec"
2513
  // clang-format on
2514
0
  ENDRECORD ();
2515
0
  return 0;
2516
0
}
2517
2518
static int
2519
json_section_revhistory (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2520
0
{
2521
0
  Dwg_RevHistory *_obj = &dwg->revhistory;
2522
0
  Dwg_Object *obj = NULL;
2523
0
  int error = 0;
2524
0
  BITCODE_RL vcount;
2525
2526
0
  RECORD (RevHistory); // single hash
2527
0
  FIELD_RL (class_version, 0);
2528
0
  FIELD_RL (class_minor, 0);
2529
0
  FIELD_RL (num_histories, 0);
2530
0
  FIELD_VECTOR (histories, RL, num_histories, 0)
2531
0
  ENDRECORD ();
2532
0
  return 0;
2533
0
}
2534
2535
static int
2536
json_section_objfreespace (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2537
0
{
2538
0
  Dwg_ObjFreeSpace *_obj = &dwg->objfreespace;
2539
0
  Dwg_Object *obj = NULL;
2540
0
  int error = 0;
2541
2542
0
  RECORD (ObjFreeSpace); // single hash
2543
2544
  // clang-format off
2545
0
  #include "objfreespace.spec"
2546
  // clang-format on
2547
0
  ENDRECORD ();
2548
0
  return 0;
2549
0
}
2550
2551
static int
2552
json_section_acds (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2553
0
{
2554
0
  Dwg_AcDs *_obj = &dwg->acds;
2555
0
  Dwg_Object *obj = NULL;
2556
0
  int error = 0;
2557
0
  BITCODE_RL rcount3 = 0, rcount4, vcount;
2558
2559
0
  RECORD (AcDs); // single hash
2560
0
  {
2561
2562
    // clang-format off
2563
0
    #include "acds.spec"
2564
    // clang-format on
2565
0
  }
2566
0
  ENDRECORD ();
2567
0
  return 0;
2568
0
}
2569
2570
static int
2571
json_section_template (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2572
0
{
2573
0
  Dwg_Template *_obj = &dwg->Template;
2574
0
  Dwg_Object *obj = NULL;
2575
0
  int error = 0;
2576
2577
0
  RECORD (Template); // single hash. i.e MEASUREMENT metric/imperial
2578
2579
  // clang-format off
2580
0
  #include "template.spec"
2581
  // clang-format on
2582
0
  ENDRECORD ();
2583
0
  return 0;
2584
0
}
2585
2586
static int
2587
json_section_auxheader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2588
0
{
2589
0
  Dwg_AuxHeader *_obj = &dwg->auxheader;
2590
0
  Dwg_Object *obj = NULL;
2591
0
  int error = 0, i;
2592
0
  BITCODE_RL vcount;
2593
2594
0
  RECORD (AuxHeader); // single hash
2595
2596
  // clang-format off
2597
0
  #include "auxheader.spec"
2598
  // clang-format on
2599
0
  ENDRECORD ();
2600
0
  return 0;
2601
0
}
2602
2603
#if 0
2604
static int
2605
json_section_signature (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2606
{
2607
  struct Dwg_Signature *_obj = &dwg->signature;
2608
  Dwg_Object *obj = NULL;
2609
  int error = 0;
2610
2611
  RECORD (Signature); // single hash
2612
2613
  // clang-format off
2614
  #include "signature.spec"
2615
  // clang-format on
2616
  ENDRECORD ();
2617
  return 0;
2618
}
2619
#endif
2620
2621
static int
2622
json_section_2ndheader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2623
0
{
2624
0
  struct _dwg_secondheader *_obj = &dwg->secondheader;
2625
0
  Dwg_Object *obj = NULL;
2626
0
  BITCODE_BL vcount;
2627
0
  int error = 0;
2628
2629
0
  RECORD (SecondHeader); // single hash
2630
  // clang-format off
2631
0
  #include "2ndheader.spec"
2632
  // clang-format on
2633
0
  VERSIONS (R_14, R_2000)
2634
0
  {
2635
0
    FIELD_RLL (junk_r14, 0);
2636
0
  }
2637
0
  ENDRECORD ();
2638
0
  return 0;
2639
0
}
2640
2641
EXPORT int
2642
dwg_write_json (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2643
0
{
2644
0
  Dwg_Header *obj = &dwg->header;
2645
0
  int error = 0;
2646
2647
0
  if (!dat->version)
2648
0
    dat->version = dat->from_version;
2649
0
  if (!dat->codepage)
2650
0
    dat->codepage = dwg->header.codepage;
2651
0
  if (!dat->fh)
2652
0
    goto fail;
2653
0
  fprintf (dat->fh, "{%s%s%s\"created_by\":%s\"%s\"", JSON_NL, JSON_SPC,
2654
0
           JSON_SPC, JSON_SPC, PACKAGE_STRING);
2655
0
  dat->bit++; // ident
2656
2657
0
  json_fileheader_write (dat, dwg);
2658
2659
  // A minimal HEADER would require only $ACADVER, $HANDSEED, and then
2660
  // ENTITIES. But we do that only for DXF
2661
0
  json_header_write (dat, dwg);
2662
2663
0
  if (dat->version >= R_13b1)
2664
0
    {
2665
0
      if (json_classes_write (dat, dwg) >= DWG_ERR_CRITICAL)
2666
0
        goto fail;
2667
0
    }
2668
0
  if (dat->version < R_13b1 && 0)
2669
0
    {
2670
0
      if (json_tables_write (dat, dwg) >= DWG_ERR_CRITICAL)
2671
0
        goto fail;
2672
0
    }
2673
2674
0
  if (json_objects_write (dat, dwg) >= DWG_ERR_CRITICAL)
2675
0
    goto fail;
2676
2677
0
  if (dat->version >= R_13b1)
2678
0
    {
2679
0
      if (json_thumbnail_write (dat, dwg) >= DWG_ERR_CRITICAL)
2680
0
        goto fail;
2681
      /* the other sections */
2682
0
      if (dat->version <= R_2000)
2683
0
        {
2684
0
          if (dwg->header.sections >= 3 && dwg->objfreespace.numnums)
2685
0
            error |= json_section_objfreespace (dat, dwg); // 3
2686
0
          if (dwg->secondheader.num_sections)
2687
0
            error |= json_section_2ndheader (dat, dwg);
2688
0
          if (dwg->header.sections >= 4)
2689
0
            error |= json_section_template (dat, dwg); // 4 i.e. MEASUREMENT
2690
0
          if (dwg->header.sections >= 6)
2691
0
            error |= json_section_auxheader (dat, dwg); // 5
2692
0
        }
2693
0
      if (dat->version >= R_2004)
2694
0
        {
2695
0
          if (dat->version == R_2007)
2696
0
            error |= json_section_r2007fileheader (dat, dwg);
2697
0
          else
2698
0
            error |= json_section_r2004fileheader (dat, dwg);
2699
0
          if (dwg->header.summaryinfo_address)
2700
0
            error |= json_section_summary (dat, dwg);
2701
0
          if (dwg->header.vbaproj_address)
2702
0
            error |= json_section_vbaproject (dat, dwg);
2703
0
          error |= json_section_appinfo (dat, dwg);
2704
0
          error |= json_section_appinfohistory (dat, dwg);
2705
0
          error |= json_section_filedeplist (dat, dwg);
2706
0
          error |= json_section_security (dat, dwg);
2707
0
          error |= json_section_revhistory (dat, dwg);
2708
0
          error |= json_section_objfreespace (dat, dwg);
2709
          // error |= json_section_signature (dat, dwg);
2710
0
          error |= json_section_template (dat, dwg);
2711
0
          error |= json_section_acds (dat, dwg);
2712
0
        }
2713
0
    }
2714
2715
#if 0
2716
  /* object map */
2717
  if (dat->version >= R_13b1)
2718
    {
2719
      if (json_handles_write (dat, dwg) >= DWG_ERR_CRITICAL)
2720
        goto fail;
2721
    }
2722
#endif
2723
2724
0
  dat->bit--;
2725
0
  fprintf (dat->fh, "}%s", JSON_NL);
2726
0
  return 0;
2727
0
fail:
2728
0
  return 1;
2729
0
}