Coverage Report

Created: 2026-02-08 07:11

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