1 /*****************************************************************************/
2 /* LibreDWG - free implementation of the DWG file format */
3 /* */
4 /* Copyright (C) 2018-2021 Free Software Foundation, Inc. */
5 /* */
6 /* This library is free software, licensed under the terms of the GNU */
7 /* General Public License as published by the Free Software Foundation, */
8 /* either version 3 of the License, or (at your option) any later version. */
9 /* You should have received a copy of the GNU General Public License */
10 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
11 /*****************************************************************************/
12
13 /*
14 * 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 #ifdef HAVE_CTYPE_H
24 # include <ctype.h>
25 #endif
26
27 #define IS_JSON
28 #include "common.h"
29 #include "bits.h"
30 #include "myalloca.h"
31 #include "dwg.h"
32 #include "decode.h"
33 #include "out_json.h"
34
35 #define DWG_LOGLEVEL DWG_LOGLEVEL_NONE
36 #include "logging.h"
37
38 /* the current version per spec block */
39 static unsigned int cur_ver = 0;
40 static BITCODE_BL rcount1, rcount2;
41
42 /* see also examples/unknown.c */
43 #ifdef HAVE_NATIVE_WCHAR2
44 static wchar_t *wcquote (wchar_t *restrict dest, const wchar_t *restrict src);
45 #else
46 static void print_wcquote (Bit_Chain *restrict dat,
47 dwg_wchar_t *restrict wstr);
48 #endif
49
50 static int json_3dsolid (Bit_Chain *restrict dat,
51 const Dwg_Object *restrict obj,
52 Dwg_Entity_3DSOLID *restrict _obj);
53 static void _prefix (Bit_Chain *dat);
54 static char *_path_field (const char *path);
55
56 /*--------------------------------------------------------------------------------
57 * MACROS
58 */
59
60 #define ACTION json
61
62 #define ISFIRST (dat->opts & DWG_OPTS_JSONFIRST)
63 #define SETFIRST dat->opts |= DWG_OPTS_JSONFIRST
64 #define CLEARFIRST dat->opts &= ~DWG_OPTS_JSONFIRST
65
66 #define PREFIX _prefix (dat);
67 #define PRINTFIRST \
68 { \
69 if (!ISFIRST) \
70 fprintf (dat->fh, ",\n"); \
71 else \
72 CLEARFIRST; \
73 }
74 #define FIRSTPREFIX PRINTFIRST PREFIX
75
76 #define KEYs(nam) FIRSTPREFIX fprintf (dat->fh, "\"%s\": ", nam)
77 // strip path to field only
78 #define KEY(nam) FIRSTPREFIX fprintf (dat->fh, "\"%s\": ", _path_field(#nam))
79
80 #define ARRAY \
81 { \
82 fprintf (dat->fh, "[\n"); \
83 SETFIRST; \
84 dat->bit++; \
85 }
86 #define ENDARRAY \
87 { \
88 fprintf (dat->fh, "\n"); \
89 dat->bit--; \
90 PREFIX fprintf (dat->fh, "]"); \
91 CLEARFIRST; \
92 }
93 #define HASH \
94 { \
95 fprintf (dat->fh, "{\n"); \
96 SETFIRST; \
97 dat->bit++; \
98 }
99 #define ENDHASH \
100 { \
101 fprintf (dat->fh, "\n"); \
102 dat->bit--; \
103 PREFIX fprintf (dat->fh, "}"); \
104 CLEARFIRST; \
105 }
106
107 #define TABLE(nam) \
108 KEY (nam); \
109 HASH
110 #define ENDTAB() \
111 ENDHASH
112 // a named hash
113 #define RECORD(nam) \
114 KEY (nam); \
115 HASH
116 #define ENDRECORD() \
117 ENDHASH
118 // a named list
119 #define SECTION(nam) \
120 KEY (nam); \
121 ARRAY
122 #define ENDSEC() ENDARRAY
123
124 #undef FORMAT_H
125 #undef FORMAT_RLL
126 #undef FORMAT_BLL
127 #undef FORMAT_RC
128 #undef FORMAT_RSx
129 #undef FORMAT_RLx
130 #undef FORMAT_BLx
131 #undef FORMAT_BLX
132 #undef FORMAT_4BITS
133 #undef ARGS_H
134 #define ARGS_H(hdl) hdl.code, hdl.value
135 #define FORMAT_H "[%u, %lu]"
136 #define ARGS_HREF(ref) ref->handleref.code, ref->handleref.size, ref->handleref.value, ref->absolute_ref
137 #undef FORMAT_RD
138 #undef FORMAT_BD
139 #define FORMAT_RD "%.14f"
140 #define FORMAT_BD FORMAT_RD
141 #define FORMAT_HREF "[%u, %u, %lu, %lu]"
142 #define FORMAT_RLL "%" PRIu64
143 #define FORMAT_BLL "%" PRIu64
144 #define FORMAT_RC "%d"
145 #define FORMAT_RSx FORMAT_RS
146 #define FORMAT_RLx FORMAT_RL
147 #define FORMAT_BLx FORMAT_BL
148 #define FORMAT_BLX FORMAT_BL
149 #define FORMAT_4BITS FORMAT_RC
150
151 #define VALUE(value, type, dxf) \
152 fprintf (dat->fh, FORMAT_##type, value)
153 #define VALUE_B(value, dxf) VALUE (value, B, dxf)
154 #define VALUE_RC(value, dxf) VALUE (value, RC, dxf)
155 #define VALUE_RS(value, dxf) VALUE (value, RS, dxf)
156 #define VALUE_RL(value, dxf) VALUE (value, RL, dxf)
157 #define VALUE_RLL(value, dxf) VALUE (value, RLL, dxf)
158 #ifdef IS_RELEASE
159 # define VALUE_RD(value, dxf) \
160 if (bit_isnan (value)) \
161 _VALUE_RD (0.0, dxf) \
162 else \
163 _VALUE_RD (value, dxf)
164 #else
165 # define VALUE_RD(value, dxf) _VALUE_RD (value, dxf)
166 #endif
167 #define _VALUE_RD(value, dxf) \
168 { \
169 char _buf[256]; \
170 int k; \
171 snprintf (_buf, 255, FORMAT_RD, value); \
172 k = strlen (_buf); \
173 if (strrchr (_buf, '.') && _buf[k - 1] == '0') \
174 { \
175 for (k--; k > 1 && _buf[k - 1] != '.' && _buf[k] == '0'; k--) \
176 _buf[k] = '\0'; \
177 } \
178 fprintf (dat->fh, "%s", _buf); \
179 }
180 #define VALUE_2RD(pt, dxf) \
181 { \
182 fprintf (dat->fh, "[ "); \
183 VALUE_RD (pt.x, 0); \
184 fprintf (dat->fh, ", "); \
185 VALUE_RD (pt.y, 0); \
186 fprintf (dat->fh, " ]"); \
187 }
188 #define VALUE_2DD(pt, def, dxf) VALUE_2RD (pt, dxf)
189 #define VALUE_3RD(pt, dxf) \
190 { \
191 fprintf (dat->fh, "[ "); \
192 VALUE_RD (pt.x, 0); \
193 fprintf (dat->fh, ", "); \
194 VALUE_RD (pt.y, 0); \
195 fprintf (dat->fh, ", "); \
196 VALUE_RD (pt.z, 0); \
197 fprintf (dat->fh, " ]"); \
198 }
199 #define VALUE_3BD(pt, dxf) VALUE_3RD (pt, dxf)
200 #define VALUE_TV(nam, dxf)
201
202 #define FIELD(nam, type, dxf) \
203 if (!memBEGINc (#nam, "num_")) \
204 { \
205 FIRSTPREFIX fprintf (dat->fh, "\"%s\": " FORMAT_##type, \
206 _path_field (#nam), _obj->nam); \
207 }
208 #define _FIELD(nam, type, value) \
209 { \
210 FIRSTPREFIX fprintf (dat->fh, "\"" #nam "\": " FORMAT_##type, obj->nam); \
211 }
212 #define ENT_FIELD(nam, type, value) \
213 { \
214 FIRSTPREFIX fprintf (dat->fh, "\"%s\": " FORMAT_##type, \
215 _path_field (#nam), _ent->nam); \
216 }
217 #define SUB_FIELD(o, nam, type, dxf) \
218 if (!memBEGINc (#nam, "num_")) \
219 { \
220 FIRSTPREFIX fprintf (dat->fh, "\"%s\": " FORMAT_##type, \
221 _path_field (#nam), _obj->o.nam); \
222 }
223 #define FIELD_CAST(nam, type, cast, dxf) FIELD (nam, cast, dxf)
224 #define SUB_FIELD_CAST(o, nam, type, cast, dxf) SUB_FIELD (o, nam, cast, dxf)
225 #define FIELD_TRACE(nam, type)
226 #define FIELD_G_TRACE(nam, type, dxf)
227 #define FIELD_TEXT(nam, str) \
228 { \
229 FIRSTPREFIX fprintf (dat->fh, "\"%s\": ", _path_field(#nam)); \
230 VALUE_TEXT ((char*)str) \
231 }
232
233 #define VALUE_TEXT(str) \
234 { \
235 if (str \
236 && (1 || strchr (str, '"') || strchr (str, '\\') \
237 || strchr (str, '\n'))) \
238 { \
239 const int len = strlen (str); \
240 if (len < 4096 / 6) \
241 { \
242 const int _len = 6 * len + 1; \
243 char *_buf = (char*)alloca (_len); \
244 fprintf (dat->fh, "\"%s\"", json_cquote (_buf, str, _len)); \
245 freea (_buf); \
246 } \
247 else \
248 { \
249 const int _len = 6 * len + 1; \
250 char *_buf = (char*)malloc (_len); \
251 fprintf (dat->fh, "\"%s\"", json_cquote (_buf, str, _len)); \
252 free (_buf); \
253 } \
254 } \
255 else \
256 { \
257 fprintf (dat->fh, "\"%s\"", str ? str : ""); \
258 } \
259 }
260
261 #ifdef HAVE_NATIVE_WCHAR2
262 # define VALUE_TEXT_TU(wstr) \
263 if (wstr \
264 && (1 || wcschr ((wchar_t *)wstr, L'"') \
265 || wcschr ((wchar_t *)wstr, L'\\') \
266 || wcschr ((wchar_t *)wstr, L'\n'))) \
267 { \
268 wchar_t *_buf = malloc (6 * wcslen ((wchar_t *)wstr) + 2); \
269 fprintf (dat->fh, "\"%ls\"", wcquote (_buf, (wchar_t *)wstr)); \
270 free (_buf); \
271 } \
272 else \
273 { \
274 fprintf (dat->fh, "\"%ls\"", wstr ? (wchar_t *)wstr : L""); \
275 }
276 #else
277 # define VALUE_TEXT_TU(wstr) print_wcquote (dat, (BITCODE_TU)wstr)
278 #endif
279 #define FIELD_TEXT_TU(nam, wstr) \
280 { \
281 KEY (nam); \
282 VALUE_TEXT_TU ((BITCODE_TU)wstr); \
283 }
284
285 #define FIELD_VALUE(nam) _obj->nam
286 #define ANYCODE -1
287 // todo: only the name, not the ref
288 #define VALUE_HANDLE(hdlptr, nam, handle_code, dxf) \
289 if (hdlptr) \
290 { \
291 fprintf (dat->fh, FORMAT_HREF "", ARGS_HREF (hdlptr)); \
292 } \
293 else \
294 { \
295 fprintf (dat->fh, "[0, 0]"); \
296 }
297 #define VALUE_H(hdl, dxf) \
298 fprintf (dat->fh, FORMAT_H "", hdl.code, hdl.value)
299 #define FIELD_HANDLE(nam, handle_code, dxf) \
300 { \
301 if (_obj->nam) \
302 { \
303 FIRSTPREFIX fprintf (dat->fh, "\"%s\": " FORMAT_HREF "", \
304 _path_field (#nam), ARGS_HREF (_obj->nam)); \
305 } \
306 else \
307 { \
308 FIRSTPREFIX fprintf (dat->fh, "\"%s\": [0, 0]", _path_field (#nam)); \
309 } \
310 }
311 #define SUB_FIELD_HANDLE(o, nam, handle_code, dxf) \
312 { \
313 if (_obj->o.nam) \
314 { \
315 FIRSTPREFIX fprintf (dat->fh, "\"%s\": " FORMAT_HREF "", \
316 _path_field (#nam), ARGS_HREF (_obj->o.nam)); \
317 } \
318 else \
319 { \
320 FIRSTPREFIX fprintf (dat->fh, "\"%s\": [0, 0]", _path_field (#nam)); \
321 } \
322 }
323 #define FIELD_DATAHANDLE(nam, code, dxf) FIELD_HANDLE (nam, code, dxf)
324 #define FIELD_HANDLE_N(nam, vcount, handle_code, dxf) \
325 PRINTFIRST; \
326 if (_obj->nam) \
327 { \
328 PREFIX fprintf (dat->fh, FORMAT_HREF "", ARGS_HREF (_obj->nam)); \
329 } \
330 else \
331 { \
332 PREFIX fprintf (dat->fh, "[0, 0]"); \
333 }
334 #define SUB_FIELD_HANDLE_N(o, nam, handle_code, dxf) \
335 PRINTFIRST; \
336 if (_obj->o.nam) \
337 { \
338 PREFIX fprintf (dat->fh, FORMAT_HREF "", ARGS_HREF (_obj->o.nam)); \
339 } \
340 else \
341 { \
342 PREFIX fprintf (dat->fh, "[0, 0]"); \
343 }
344 #define VALUE_BINARY(buf, len, dxf) \
345 { \
346 fprintf (dat->fh, "\""); \
347 if (buf && len) \
348 { \
349 for (long _j = 0; _j < (long)len; _j++) \
350 { \
351 fprintf (dat->fh, "%02X", ((BITCODE_RC *)buf)[_j]); \
352 } \
353 } \
354 fprintf (dat->fh, "\""); \
355 }
356 #define FIELD_BINARY(nam, size, dxf) \
357 { \
358 KEY (nam); \
359 fprintf (dat->fh, "\""); \
360 if (_obj->nam) \
361 { \
362 for (long _j = 0; _j < (long)size; _j++) \
363 { \
364 fprintf (dat->fh, "%02X", ((BITCODE_RC *)_obj->nam)[_j]); \
365 } \
366 } \
367 fprintf (dat->fh, "\""); \
368 }
369
370 #define FIELD_B(nam, dxf) FIELD (nam, B, dxf)
371 #define FIELD_BB(nam, dxf) FIELD (nam, BB, dxf)
372 #define FIELD_3B(nam, dxf) FIELD (nam, 3B, dxf)
373 #define FIELD_BS(nam, dxf) FIELD (nam, BS, dxf)
374 #define FIELD_BL(nam, dxf) FIELD (nam, BL, dxf)
375 #define FIELD_BLL(nam, dxf) FIELD (nam, BLL, dxf)
376 #ifdef IS_RELEASE
377 # define FIELD_BD(nam, dxf) \
378 { \
379 if (!bit_isnan (_obj->nam)) \
380 { \
381 FIRSTPREFIX fprintf (dat->fh, "\"%s\": ", _path_field (#nam)); \
382 _VALUE_RD (_obj->nam, dxf); \
383 } \
384 }
385 # define FIELD_2RD(nam, dxf) \
386 { \
387 if (!bit_isnan (_obj->nam.x) && !bit_isnan (_obj->nam.y)) \
388 { \
389 FIRSTPREFIX fprintf (dat->fh, "\"" #nam "\": "); \
390 VALUE_2RD (_obj->nam, dxf); \
391 } \
392 }
393 # define FIELD_3RD(nam, dxf) \
394 { \
395 if (!bit_isnan (_obj->nam.x) && !bit_isnan (_obj->nam.y) \
396 && !bit_isnan (_obj->nam.z)) \
397 { \
398 FIRSTPREFIX fprintf (dat->fh, "\"" #nam "\": "); \
399 VALUE_3RD (_obj->nam, dxf); \
400 } \
401 }
402 # define SUB_FIELD_BD(o, nam, dxf) \
403 { \
404 if (!bit_isnan (_obj->o.nam)) \
405 { \
406 FIRSTPREFIX fprintf (dat->fh, "\"%s\": ", _path_field (#nam)); \
407 _VALUE_RD (_obj->o.nam, dxf); \
408 } \
409 }
410 #else /* IS_RELEASE */
411 # define FIELD_BD(nam, dxf) \
412 { \
413 FIRSTPREFIX fprintf (dat->fh, "\"%s\": ", _path_field (#nam)); \
414 _VALUE_RD (_obj->nam, dxf); \
415 }
416 # define FIELD_2RD(nam, dxf) \
417 { \
418 FIRSTPREFIX fprintf (dat->fh, "\"" #nam "\": "); \
419 VALUE_2RD (_obj->nam, dxf); \
420 }
421 # define FIELD_3RD(nam, dxf) \
422 { \
423 FIRSTPREFIX fprintf (dat->fh, "\"" #nam "\": "); \
424 VALUE_3RD (_obj->nam, dxf); \
425 }
426 # define SUB_FIELD_BD(o, nam, dxf) \
427 { \
428 FIRSTPREFIX fprintf (dat->fh, "\"%s\": ", _path_field (#nam)); \
429 _VALUE_RD (_obj->o.nam, dxf); \
430 }
431 #endif
432
433 #define FIELD_RC(nam, dxf) FIELD (nam, RC, dxf)
434 #define FIELD_RCx(nam, dxf) FIELD (nam, RC, dxf)
435 #define FIELD_RS(nam, dxf) FIELD (nam, RS, dxf)
436 #define FIELD_RD(nam, dxf) FIELD_BD (nam, dxf)
437 #define FIELD_RL(nam, dxf) FIELD (nam, RL, dxf)
438 #define FIELD_RLL(nam, dxf) FIELD (nam, RLL, dxf)
439 #define FIELD_MC(nam, dxf) FIELD (nam, MC, dxf)
440 #define FIELD_MS(nam, dxf) FIELD (nam, MS, dxf)
441 #define FIELD_TF(nam, len, dxf) FIELD_TEXT (nam, _obj->nam)
442 #define FIELD_TFF(nam, len, dxf) FIELD_TEXT (nam, (const char*)_obj->nam)
443 #define FIELD_TFFx(nam, len, dxf) FIELD_BINARY (nam, len, dxf)
444 #define FIELD_TV(nam, dxf) FIELD_TEXT (nam, _obj->nam)
445 #define FIELD_TU(nam, dxf) FIELD_TEXT_TU (nam, (BITCODE_TU)_obj->nam)
446 #define FIELD_T16(nam, dxf) FIELD_TV (nam, dxf)
447 #define FIELD_TU16(nam, dxf) FIELD_TU (nam, dxf)
448 #define FIELD_T32(nam, dxf) FIELD_T (nam, dxf)
449 #define FIELD_T(nam, dxf) \
450 { \
451 if (IS_FROM_TU (dat)) \
452 { \
453 FIELD_TU (nam, dxf); \
454 } \
455 else \
456 { \
457 FIELD_TV (nam, dxf); \
458 } \
459 }
460 #define _FIELD_T(nam, str) \
461 { \
462 if (IS_FROM_TU (dat)) \
463 { \
464 FIELD_TEXT_TU (nam, str); \
465 } \
466 else \
467 { \
468 FIELD_TEXT (nam, str); \
469 } \
470 }
471 #define VALUE_T(str) \
472 { \
473 if (IS_FROM_TU (dat)) \
474 { \
475 VALUE_TEXT_TU (str); \
476 } \
477 else \
478 { \
479 VALUE_TEXT (str) \
480 } \
481 }
482 #define _FIELD_TV_ALPHA(nam, str) \
483 if ((str) && isalpha (*(str))) \
484 { \
485 FIELD_TEXT (nam, str) \
486 }
487 #define FIELD_BT(nam, dxf) FIELD (nam, BT, dxf);
488 #define FIELD_4BITS(nam, dxf) FIELD (nam, 4BITS, dxf)
489 #define FIELD_BE(nam, dxf) FIELD_3RD (nam, dxf)
490 #define FIELD_DD(nam, _default, dxf) FIELD_BD (nam, dxf)
491 #define FIELD_2BD(nam, dxf) FIELD_2RD (nam, dxf)
492 #define FIELD_2BD_1(nam, dxf) FIELD_2RD (nam, dxf)
493 #define FIELD_2DD(nam, def, dxf) FIELD_2RD (nam, dxf)
494 #define FIELD_3DD(nam, def, dxf) FIELD_3RD (nam, dxf)
495 #define FIELD_3BD(nam, dxf) FIELD_3RD (nam, dxf)
496 #define FIELD_3BD_1(nam, dxf) FIELD_3RD (nam, dxf)
497 #define FIELD_3DPOINT(nam, dxf) FIELD_3BD (nam, dxf)
498
499 #define SUB_FIELD_T(o, nam, dxf) \
500 { \
501 if (IS_FROM_TU (dat)) \
502 { \
503 KEY (nam); \
504 VALUE_TEXT_TU ((BITCODE_TU)_obj->o.nam); \
505 } \
506 else \
507 { \
508 PRINTFIRST; \
509 PREFIX fprintf (dat->fh, "\"" #nam "\": \"%s\"", _obj->o.nam); \
510 } \
511 }
512 #define SUB_FIELD_B(o, nam, dxf) SUB_FIELD (o, nam, B, dxf)
513 #define SUB_FIELD_BB(o, nam, dxf) SUB_FIELD (o, nam, BB, dxf)
514 #define SUB_FIELD_3B(o, nam, dxf) SUB_FIELD (o, nam, 3B, dxf)
515 #define SUB_FIELD_BS(o, nam, dxf) SUB_FIELD (o, nam, BS, dxf)
516 #define SUB_FIELD_BSd(o, nam, dxf) SUB_FIELD (o, nam, BSd, dxf)
517 #define SUB_FIELD_BL(o, nam, dxf) SUB_FIELD (o, nam, BL, dxf)
518 #define SUB_FIELD_BLx(o, nam, dxf) SUB_FIELD (o, nam, BLx, dxf)
519 #define SUB_FIELD_BLd(o, nam, dxf) SUB_FIELD (o, nam, BLd, dxf)
520 #define SUB_FIELD_RC(o, nam, dxf) SUB_FIELD (o, nam, RC, dxf)
521 #define SUB_FIELD_RS(o, nam, dxf) SUB_FIELD (o, nam, RS, dxf)
522 #define SUB_FIELD_RL(o, nam, dxf) SUB_FIELD (o, nam, RL, dxf)
523 #define SUB_FIELD_BLL(o, nam, dxf) SUB_FIELD (o, nam, BLL, dxf)
524 #define SUB_FIELD_RLL(o, nam, dxf) SUB_FIELD (o, nam, RLL, dxf)
525
526 #define SUB_FIELD_RD(o, nam, dxf) SUB_FIELD_BD (o, nam, dxf)
527 #define SUB_FIELD_3BD_inl(o, nam, dxf) \
528 SUB_FIELD_RD (o, x, dxf); \
529 SUB_FIELD_RD (o, y, dxf); \
530 SUB_FIELD_RD (o, z, dxf)
531 #define SUB_FIELD_2BD(o, nam, dxf) \
532 KEY (nam); \
533 VALUE_2RD (_obj->o.nam, dxf)
534 #define SUB_FIELD_2BD_1(o, nam, dxf) \
535 KEY (nam); \
536 VALUE_2RD (_obj->o.nam, dxf)
537 #define SUB_FIELD_2RD(o, nam, dxf) \
538 KEY (nam); \
539 VALUE_2RD (_obj->o.nam, dxf)
540 #define SUB_FIELD_3RD(o, nam, dxf) \
541 KEY (nam); \
542 VALUE_3RD (_obj->o.nam, dxf)
543 #define SUB_FIELD_3BD(o, nam, dxf) \
544 KEY (nam); \
545 VALUE_3RD (_obj->o.nam, dxf)
546 #define SUB_FIELD_3DPOINT(o, nam, dxf) \
547 KEY (nam); \
548 VALUE_3RD (_obj->o.nam, dxf)
549
550 static void
field_cmc(Bit_Chain * dat,const char * restrict key,const Dwg_Color * restrict _obj)551 field_cmc (Bit_Chain *dat, const char *restrict key,
552 const Dwg_Color *restrict _obj)
553 {
554 if (dat->version >= R_2004)
555 {
556 KEYs (_path_field(key));
557 HASH;
558 if (_obj->index)
559 {
560 FIELD_BS (index, 62);
561 }
562 FIRSTPREFIX fprintf (dat->fh, "\"rgb\": \"%06x\"", (unsigned)_obj->rgb);
563 if (_obj->flag)
564 {
565 FIELD_BS (flag, 0);
566 }
567 if (_obj->flag > 0 && _obj->flag < 8)
568 {
569 if (_obj->flag & 1)
570 _FIELD_TV_ALPHA (name, _obj->name)
571 if (_obj->flag & 2)
572 _FIELD_TV_ALPHA (book_name, _obj->book_name)
573 }
574 ENDHASH;
575 }
576 else
577 {
578 FIRSTPREFIX fprintf (dat->fh, "\"%s\": %d", _path_field (key),
579 _obj->index);
580 }
581 }
582
583 #define FIELD_CMC(color, dxf) field_cmc (dat, #color, &_obj->color)
584 #define SUB_FIELD_CMC(o, color, dxf) \
585 field_cmc (dat, #color, &_obj->o.color)
586
587 #define FIELD_TIMEBLL(nam, dxf) \
588 FIRSTPREFIX fprintf (dat->fh, \
589 "\"" #nam "\": [ " FORMAT_BL ", " FORMAT_BL " ]", \
590 _obj->nam.days, _obj->nam.ms)
591 #define FIELD_TIMERLL(nam, dxf) FIELD_TIMEBLL (nam, dxf)
592
593 // FIELD_VECTOR_N(nam, type, size):
594 // reads data of the type indicated by 'type' 'size' times and stores
595 // it all in the vector called 'nam'.
596 #define FIELD_VECTOR_N(nam, type, size, dxf) \
597 KEY (nam); \
598 ARRAY; \
599 if (_obj->nam) \
600 { \
601 for (vcount = 0; vcount < (BITCODE_BL)size; vcount++) \
602 { \
603 FIRSTPREFIX fprintf (dat->fh, FORMAT_##type, _obj->nam[vcount]); \
604 } \
605 } \
606 else \
607 FIRSTPREFIX \
608 ENDARRAY;
609 #define SUB_FIELD_VECTOR_N(o, nam, type, size, dxf) \
610 KEY (nam); \
611 ARRAY; \
612 if (_obj->o.nam) \
613 { \
614 for (vcount = 0; vcount < (BITCODE_BL)size; vcount++) \
615 { \
616 FIRSTPREFIX fprintf (dat->fh, FORMAT_##type, _obj->o.nam[vcount]); \
617 } \
618 } \
619 else \
620 FIRSTPREFIX \
621 ENDARRAY;
622 #define FIELD_VECTOR_T(nam, type, size, dxf) \
623 KEY (nam); \
624 ARRAY; \
625 if (_obj->nam) \
626 { \
627 BITCODE_BL _size = (BITCODE_BL)_obj->size; \
628 if (IS_FROM_TU (dat)) \
629 { \
630 for (vcount = 0; vcount < _size; vcount++) \
631 { \
632 FIRSTPREFIX VALUE_TEXT_TU (_obj->nam[vcount]); \
633 } \
634 } \
635 else \
636 { \
637 for (vcount = 0; vcount < _size; vcount++) \
638 { \
639 FIRSTPREFIX VALUE_TEXT (_obj->nam[vcount]) \
640 } \
641 } \
642 } \
643 else \
644 FIRSTPREFIX \
645 ENDARRAY;
646
647 #define SUB_FIELD_VECTOR_TYPESIZE(o, nam, size, typesize, dxf) \
648 KEY (nam); \
649 ARRAY; \
650 if (_obj->o.size && _obj->o.nam) \
651 { \
652 for (vcount = 0; vcount < (BITCODE_BL)_obj->o.size; vcount++) \
653 { \
654 switch (typesize) \
655 { \
656 case 0: \
657 break; \
658 case 1: \
659 FIRSTPREFIX fprintf (dat->fh, FORMAT_RC, \
660 (BITCODE_RC)_obj->o.nam[vcount]); \
661 break; \
662 case 2: \
663 FIRSTPREFIX fprintf (dat->fh, FORMAT_RS, \
664 (BITCODE_RS)_obj->o.nam[vcount]); \
665 break; \
666 case 4: \
667 FIRSTPREFIX fprintf (dat->fh, FORMAT_RL, \
668 (BITCODE_RL)_obj->o.nam[vcount]); \
669 break; \
670 case 8: \
671 FIRSTPREFIX fprintf (dat->fh, FORMAT_RLL, \
672 (BITCODE_RLL)_obj->o.nam[vcount]); \
673 break; \
674 default: \
675 LOG_ERROR ("Unkown SUB_FIELD_VECTOR_TYPESIZE " #nam \
676 " typesize %d", typesize); \
677 break; \
678 } \
679 } \
680 } \
681 else \
682 FIRSTPREFIX \
683 ENDARRAY;
684
685 #define FIELD_VECTOR(nam, type, size, dxf) \
686 FIELD_VECTOR_N (nam, type, _obj->size, dxf)
687 #define FIELD_VECTOR_INL(nam, type, size, dxf) \
688 FIELD_VECTOR_N(nam, type, size, dxf)
689
690 #define FIELD_2RD_VECTOR(nam, size, dxf) \
691 if (_obj->nam) \
692 { \
693 KEY (nam); \
694 ARRAY; \
695 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
696 { \
697 FIRSTPREFIX VALUE_2RD (FIELD_VALUE (nam[vcount]), dxf); \
698 } \
699 ENDARRAY; \
700 }
701
702 #define FIELD_2DD_VECTOR(nam, size, dxf) \
703 if (_obj->nam) \
704 { \
705 KEY (nam); \
706 ARRAY; \
707 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
708 { \
709 FIRSTPREFIX VALUE_2RD (_obj->nam[vcount], dxf); \
710 } \
711 ENDARRAY; \
712 }
713
714 #define FIELD_3DPOINT_VECTOR(nam, size, dxf) \
715 if (_obj->nam) \
716 { \
717 KEY (nam); \
718 ARRAY; \
719 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
720 { \
721 FIRSTPREFIX VALUE_3BD (FIELD_VALUE (nam[vcount]), dxf); \
722 } \
723 ENDARRAY; \
724 }
725
726 #define HANDLE_VECTOR_N(nam, size, code, dxf) \
727 if (_obj->nam) \
728 { \
729 KEY (nam); \
730 ARRAY; \
731 for (vcount = 0; vcount < (BITCODE_BL)size; vcount++) \
732 { \
733 FIELD_HANDLE_N (nam[vcount], vcount, code, dxf); \
734 } \
735 ENDARRAY; \
736 }
737
738 #define HANDLE_VECTOR(nam, sizefield, code, dxf) \
739 HANDLE_VECTOR_N (nam, FIELD_VALUE (sizefield), code, dxf)
740
741 #define SUB_HANDLE_VECTOR(o, nam, size, code, dxf) \
742 KEY (nam); \
743 if (_obj->o.nam) \
744 { \
745 ARRAY; \
746 for (vcount = 0; vcount < (BITCODE_BL)_obj->o.size; vcount++) \
747 { \
748 SUB_FIELD_HANDLE_N (o, nam[vcount], code, dxf); \
749 } \
750 ENDARRAY; \
751 } \
752 else \
753 { \
754 ARRAY; \
755 ENDARRAY; \
756 }
757
758 #define REACTORS(code) \
759 if (dat->version >= R_13 && obj->tio.object->num_reactors \
760 && obj->tio.object->reactors) \
761 { \
762 KEY (reactors); \
763 ARRAY; \
764 for (vcount = 0; vcount < obj->tio.object->num_reactors; vcount++) \
765 { \
766 FIRSTPREFIX VALUE_HANDLE (obj->tio.object->reactors[vcount], reactors, \
767 code, 330); \
768 } \
769 ENDARRAY; \
770 }
771 #define ENT_REACTORS(code) \
772 if (dat->version >= R_13 && ent->num_reactors && ent->reactors) \
773 { \
774 KEY (reactors); \
775 ARRAY; \
776 for (vcount = 0; vcount < ent->num_reactors; vcount++) \
777 { \
778 FIRSTPREFIX VALUE_HANDLE (ent->reactors[vcount], reactors, code, 330); \
779 } \
780 ENDARRAY; \
781 }
782
783 // violates duplicate keys
784 #define SUBCLASS(name) \
785 FIRSTPREFIX fprintf (dat->fh, "\"_subclass\": \"" #name "\"");
786
787 // FIXME: for KEY not the complete nam path, only the field.
788 // e.g. verts[rcount1].lines[rcount2].segparms
789 #define _REPEAT_N(times, nam, type, idx) \
790 if (_obj->nam) \
791 { \
792 KEY (nam); \
793 ARRAY; \
794 for (rcount##idx = 0; rcount##idx < (BITCODE_BL)times; rcount##idx++) \
795 {
796 #define REPEAT_N(times, nam, type) _REPEAT_N(times, nam, type, 1)
797 #define REPEAT_CN(times, nam, type) REPEAT_N(times, nam, type)
798 #define _REPEAT_C(times, nam, type, idx) _REPEAT_N (_obj->times, nam, type, idx)
799 #define _REPEAT(times, nam, type, idx) _REPEAT_N (_obj->times, nam, type, idx)
800 #define REPEAT(times, nam, type) _REPEAT (times, nam, type, 1)
801 #define REPEAT2(times, nam, type) _REPEAT (times, nam, type, 2)
802 #define REPEAT3(times, nam, type) _REPEAT (times, nam, type, 3)
803 #define REPEAT4(times, nam, type) _REPEAT (times, nam, type, 4)
804 #define REPEAT_C(times, nam, type) _REPEAT_C (times, nam, type, 1)
805 #define REPEAT2_C(times, nam, type) _REPEAT_C (times, nam, type, 2)
806 #define REPEAT3_C(times, nam, type) _REPEAT_C (times, nam, type, 3)
807 #define REPEAT4_C(times, nam, type) _REPEAT_C (times, nam, type, 4)
808 #define _REPEAT_CN(times, nam, type, idx) _REPEAT_N (times, nam, type, idx)
809 #define _REPEAT_CNF(times, nam, type, idx) _REPEAT_N (times, nam, type, idx)
810 #define _REPEAT_NF(times, nam, type, idx) _REPEAT_N (times, nam, type, idx)
811
812 #undef REPEAT_BLOCK
813 #define REPEAT_BLOCK \
814 FIRSTPREFIX HASH;
815 #undef END_REPEAT_BLOCK
816 #define END_REPEAT_BLOCK \
817 ENDHASH;
818 #undef END_REPEAT
819 #define END_REPEAT(nam) \
820 } \
821 ENDARRAY; \
822 }
823
824 #define FIELD_NUM_INSERTS(num_inserts, type, dxf) \
825 FIELD (num_inserts, type, dxf)
826
827 #define FIELD_XDATA(nam, size) \
828 error |= json_xdata (dat, _obj)
829
830 #define XDICOBJHANDLE(code) \
831 if ((dat->version < R_2004 || obj->tio.object->is_xdic_missing != 0) \
832 && (obj->tio.object->xdicobjhandle != NULL) \
833 && (obj->tio.object->xdicobjhandle->handleref.value != 0)) \
834 { \
835 KEY (xdicobjhandle); \
836 VALUE_HANDLE (obj->tio.object->xdicobjhandle, xdicobjhandle, code, -3); \
837 }
838 #define ENT_XDICOBJHANDLE(code) \
839 if ((dat->version < R_2004 || (ent->is_xdic_missing != 0)) \
840 && (ent->xdicobjhandle != NULL) \
841 && (ent->xdicobjhandle->handleref.value != 0)) \
842 { \
843 KEY (xdicobjhandle); \
844 VALUE_HANDLE (ent->xdicobjhandle, xdicobjhandle, code, -3); \
845 }
846
847 #define COMMON_ENTITY_HANDLE_DATA
848 #define SECTION_STRING_STREAM
849 #define START_STRING_STREAM
850 #define END_STRING_STREAM
851 #define START_HANDLE_STREAM
852 #define START_OBJECT_HANDLE_STREAM
853 #define CONTROL_HANDLE_STREAM
854
855 static void
_prefix(Bit_Chain * dat)856 _prefix (Bit_Chain *dat)
857 {
858 for (int _i = 0; _i < dat->bit; _i++)
859 {
860 fprintf (dat->fh, " ");
861 }
862 }
863
864 #define DWG_ENTITY(token) \
865 static int dwg_json_##token##_private ( \
866 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
867 Dwg_Object *restrict obj); \
868 GCC30_DIAG_IGNORE (-Wshadow) \
869 static int dwg_json_##token (Bit_Chain *restrict dat, \
870 Dwg_Object *restrict obj) \
871 { \
872 int error = 0; \
873 Bit_Chain *str_dat = dat; \
874 Bit_Chain *hdl_dat = dat; \
875 Dwg_Data *dwg = obj->parent; \
876 Dwg_Entity_##token *ent, *_obj; \
877 Dwg_Object_Entity *_ent; \
878 const char *name = #token; \
879 LOG_INFO ("Entity " #token ":\n") \
880 _ent = obj->tio.entity; \
881 _obj = ent = _ent->tio.token; \
882 if (*name == '_') \
883 FIELD_TEXT (entity, &name[1]) \
884 else \
885 FIELD_TEXT (entity, name) \
886 if (obj->dxfname && strNE (obj->dxfname, #token)) \
887 FIELD_TEXT (dxfname, obj->dxfname); \
888 _FIELD (index, RL, 0); \
889 _FIELD (type, RL, 0); \
890 KEY (handle); \
891 VALUE_H (obj->handle, 5); \
892 _FIELD (size, RL, 0); \
893 _FIELD (bitsize, BL, 0); \
894 if (_ent->preview_exists) \
895 ENT_FIELD (preview_exists, B, 0); \
896 error |= json_common_entity_data (dat, obj); \
897 return error | dwg_json_##token##_private (dat, hdl_dat, str_dat, obj); \
898 } \
899 static int dwg_json_##token##_private ( \
900 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
901 Dwg_Object *restrict obj) \
902 { \
903 int error = 0; \
904 BITCODE_BL vcount, rcount3, rcount4; \
905 Dwg_Data *dwg = obj->parent; \
906 Dwg_Object_Entity *_ent = obj->tio.entity; \
907 Dwg_Entity_##token *_obj = _ent->tio.token;
908
909 #define DWG_ENTITY_END \
910 return error; \
911 }
912
913 #define DWG_OBJECT(token) \
914 static int dwg_json_##token##_private ( \
915 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
916 Dwg_Object *restrict obj); \
917 GCC30_DIAG_IGNORE (-Wshadow) \
918 static int dwg_json_##token (Bit_Chain *restrict dat, \
919 Dwg_Object *restrict obj) \
920 { \
921 int error = 0; \
922 Bit_Chain *str_dat = dat; \
923 Bit_Chain *hdl_dat = dat; \
924 const char *name = #token; \
925 Dwg_Object_##token *_obj; \
926 LOG_INFO ("Object "#token ":\n") \
927 _obj = obj->tio.object->tio.token; \
928 if (*name == '_') \
929 FIELD_TEXT (object, &name[1]) \
930 else \
931 FIELD_TEXT (object, name) \
932 if (obj->dxfname && strNE (obj->dxfname, #token)) \
933 FIELD_TEXT (dxfname, obj->dxfname); \
934 _FIELD (index, RL, 0); \
935 _FIELD (type, RL, 0); \
936 KEY (handle); \
937 VALUE_H (obj->handle, 5); \
938 _FIELD (size, RL, 0); \
939 _FIELD (bitsize, BL, 0); \
940 error |= json_eed (dat, obj->tio.object); \
941 error |= json_common_object_handle_data (dat, obj); \
942 return error | dwg_json_##token##_private (dat, hdl_dat, str_dat, obj); \
943 } \
944 static int dwg_json_##token##_private ( \
945 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
946 Dwg_Object *restrict obj) \
947 { \
948 int error = 0; \
949 BITCODE_BL vcount, rcount3, rcount4; \
950 Dwg_Data *dwg = obj->parent; \
951 Dwg_Object_##token *_obj = obj->tio.object->tio.token;
952
953 #define DWG_OBJECT_END \
954 return 0; \
955 }
956
957 #undef JSON_3DSOLID
958 #define JSON_3DSOLID json_3dsolid (dat, obj, (Dwg_Entity_3DSOLID *)_obj);
959
_path_field(const char * path)960 static char* _path_field(const char *path)
961 {
962 const char *s = strrchr (path, ']');
963 if (s && s[1] == '.')
964 {
965 return (char*)&s[2];
966 }
967 return (char*)path;
968 }
969
970 static int
json_eed(Bit_Chain * restrict dat,const Dwg_Object_Object * restrict obj)971 json_eed (Bit_Chain *restrict dat,
972 const Dwg_Object_Object *restrict obj)
973 {
974 int error = 0;
975 if (!obj->num_eed)
976 return 0;
977 KEY (eed);
978 ARRAY;
979 for (BITCODE_BL i = 0; i < obj->num_eed; i++)
980 {
981 const Dwg_Eed* _obj = &obj->eed[i];
982 FIRSTPREFIX HASH;
983 if (_obj->size)
984 {
985 FIELD (size, RS, 0);
986 KEY (handle);
987 fprintf (dat->fh, FORMAT_H, ARGS_H (_obj->handle));
988 }
989 if (_obj->data)
990 {
991 const Dwg_Eed_Data *data = _obj->data;
992 KEY (code); VALUE_RC (data->code, 0);
993 KEY (value);
994 switch (data->code)
995 {
996 case 0:
997 if (!data->u.eed_0.is_tu)
998 VALUE_TEXT (data->u.eed_0.string)
999 else {
1000 VALUE_TEXT_TU (data->u.eed_0_r2007.string);
1001 }
1002 break;
1003 case 2: VALUE_RC (data->u.eed_2.close, 0); break;
1004 case 3: VALUE_RLL (data->u.eed_3.layer, 0); break;
1005 case 4: VALUE_BINARY (data->u.eed_4.data, data->u.eed_4.length, 0); break;
1006 case 5: fprintf (dat->fh, FORMAT_H "", 5, data->u.eed_5.entity); break;
1007 case 10:
1008 case 11:
1009 case 12:
1010 case 13:
1011 case 14:
1012 case 15:
1013 VALUE_3RD (data->u.eed_10.point, 0); break;
1014 case 40:
1015 case 41:
1016 case 42:
1017 VALUE_RD (data->u.eed_40.real, 0); break;
1018 case 70: VALUE_RS (data->u.eed_70.rs, 0); break;
1019 case 71: VALUE_RL (data->u.eed_71.rl, 0); break;
1020 default: VALUE_RC (0, 0);
1021 }
1022 }
1023 ENDHASH
1024 }
1025 ENDARRAY;
1026 return error;
1027 }
1028
1029 static int
json_xdata(Bit_Chain * restrict dat,const Dwg_Object_XRECORD * restrict obj)1030 json_xdata (Bit_Chain *restrict dat, const Dwg_Object_XRECORD *restrict obj)
1031 {
1032 int error = 0;
1033 Dwg_Resbuf *rbuf = obj->xdata;
1034 KEY (xdata);
1035 ARRAY;
1036 for (BITCODE_BL i = 0; i < obj->num_xdata; i++)
1037 {
1038 enum RESBUF_VALUE_TYPE type;
1039 FIRSTPREFIX ARRAY;
1040 FIRSTPREFIX VALUE_RS (rbuf->type, 0);
1041 FIRSTPREFIX
1042 type = dwg_resbuf_value_type (rbuf->type);
1043 switch (type)
1044 {
1045 case DWG_VT_STRING:
1046 if (!rbuf->value.str.is_tu)
1047 {
1048 VALUE_TEXT (rbuf->value.str.u.data);
1049 LOG_TRACE ("xdata[%u]: \"%s\" [TV %d]\n", i, rbuf->value.str.u.data,
1050 rbuf->type);
1051 }
1052 else
1053 {
1054 VALUE_TEXT_TU (rbuf->value.str.u.data);
1055 LOG_TRACE_TU ("xdata", rbuf->value.str.u.data, rbuf->type);
1056 }
1057 break;
1058 case DWG_VT_BINARY:
1059 VALUE_BINARY (rbuf->value.str.u.data, rbuf->value.str.size, 0);
1060 LOG_TRACE ("xdata[%u]: \"%s\" [TF %d]\n", i, rbuf->value.str.u.data,
1061 rbuf->type);
1062 break;
1063 case DWG_VT_REAL:
1064 VALUE_RD (rbuf->value.dbl, 0);
1065 LOG_TRACE ("xdata[%u]: %f [RD %d]\n", i, rbuf->value.dbl,
1066 rbuf->type);
1067 break;
1068 case DWG_VT_BOOL:
1069 case DWG_VT_INT8:
1070 VALUE_RC (rbuf->value.i8, 0);
1071 LOG_TRACE ("xdata[%u]: %d [RC %d]\n", i, (int)rbuf->value.i8,
1072 rbuf->type);
1073 break;
1074 case DWG_VT_INT16:
1075 VALUE_RS (rbuf->value.i16, 0);
1076 LOG_TRACE ("xdata[%u]: %d [RS %d]\n", i, (int)rbuf->value.i16,
1077 rbuf->type);
1078 break;
1079 case DWG_VT_INT32:
1080 VALUE_RL (rbuf->value.i32, 0);
1081 LOG_TRACE ("xdata[%u]: %d [RL %d]\n", i, (int)rbuf->value.i32,
1082 rbuf->type);
1083 break;
1084 case DWG_VT_INT64:
1085 VALUE_RLL (rbuf->value.i64, 0);
1086 LOG_TRACE ("xdata[%u]: %ld [RLL %d]\n", i, (long)rbuf->value.i64,
1087 rbuf->type);
1088 break;
1089 case DWG_VT_POINT3D:
1090 fprintf (dat->fh, "[ " FORMAT_RD ", " FORMAT_RD ", " FORMAT_RD " ]",
1091 rbuf->value.pt[0], rbuf->value.pt[1], rbuf->value.pt[2]);
1092 LOG_TRACE ("xdata[%u]: (%f,%f,%f) [3RD %d]\n", i, rbuf->value.pt[0],
1093 rbuf->value.pt[1], rbuf->value.pt[2], rbuf->type);
1094 break;
1095 case DWG_VT_HANDLE:
1096 case DWG_VT_OBJECTID:
1097 fprintf (dat->fh, FORMAT_H "", ARGS_H (rbuf->value.h));
1098 break;
1099 case DWG_VT_INVALID:
1100 default:
1101 break;
1102 }
1103 rbuf = rbuf->nextrb;
1104 ENDARRAY
1105 }
1106 ENDARRAY;
1107 return error;
1108 }
1109
1110 static int
json_common_entity_data(Bit_Chain * restrict dat,const Dwg_Object * restrict obj)1111 json_common_entity_data (Bit_Chain *restrict dat,
1112 const Dwg_Object *restrict obj)
1113 {
1114 Dwg_Object_Entity *ent, *_obj;
1115 // Dwg_Data *dwg = obj->parent;
1116 int error = 0;
1117 BITCODE_BL vcount = 0;
1118 ent = obj->tio.entity;
1119 _obj = ent;
1120
1121 error |= json_eed (dat, (Dwg_Object_Object *)ent);
1122
1123 // clang-format off
1124 #include "common_entity_handle_data.spec"
1125 #include "common_entity_data.spec"
1126 // clang-format on
1127
1128 return error;
1129 }
1130
1131 static int
json_common_object_handle_data(Bit_Chain * restrict dat,const Dwg_Object * restrict obj)1132 json_common_object_handle_data (Bit_Chain *restrict dat,
1133 const Dwg_Object *restrict obj)
1134 {
1135 Dwg_Object_Object *_obj;
1136 Dwg_Data *dwg = obj->parent;
1137 int error = 0;
1138 BITCODE_BL vcount = 0;
1139 _obj = obj->tio.object;
1140
1141 // clang-format off
1142 #include "common_object_handle_data.spec"
1143 // clang-format on
1144 return error;
1145 }
1146
1147 #include "dwg.spec"
1148
ishex(int c)1149 static int ishex (int c)
1150 {
1151 return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
1152 || (c >= 'A' && c <= 'F'));
1153 }
1154 // Usage: hex(c >> 4), hex(c & 0xf)
hex(unsigned char c)1155 static int hex (unsigned char c)
1156 {
1157 c &= 0xf; // 0-15
1158 return c >= 10 ? 'a' + c - 10 : '0' + c;
1159 }
1160
1161 #ifndef HAVE_NATIVE_WCHAR2
1162
1163 static void
print_wcquote(Bit_Chain * restrict dat,dwg_wchar_t * restrict wstr)1164 print_wcquote (Bit_Chain *restrict dat, dwg_wchar_t *restrict wstr)
1165 {
1166 BITCODE_TU ws = (BITCODE_TU)wstr;
1167 uint16_t c;
1168 if (!ws)
1169 {
1170 fprintf (dat->fh, "\"\"");
1171 return;
1172 }
1173 fprintf (dat->fh, "\"");
1174 while (1)
1175 {
1176 #ifdef HAVE_ALIGNED_ACCESS_REQUIRED
1177 // for strict alignment CPU's like sparc only. also for UBSAN.
1178 if ((uintptr_t)wstr % SIZEOF_SIZE_T)
1179 {
1180 unsigned char *b = (unsigned char *)ws;
1181 c = TU_to_int(b);
1182 ws++;
1183 }
1184 else
1185 #endif
1186 c = *ws++;
1187 if (!c)
1188 break;
1189 if (c == L'"')
1190 {
1191 fprintf (dat->fh, "\\\"");
1192 }
1193 else if (c == L'\\' && ws[0] == L'U' && ws[1] == L'+' && ishex (ws[2])
1194 && ishex (ws[3]) && ishex (ws[4]) && ishex (ws[5]))
1195 {
1196 fprintf (dat->fh, "\\u");
1197 ws += 2;
1198 }
1199 else if (c == L'\\')
1200 {
1201 fprintf (dat->fh, "\\\\");
1202 }
1203 else if (c == L'\n')
1204 {
1205 fprintf (dat->fh, "\\n");
1206 }
1207 else if (c == L'\r')
1208 {
1209 fprintf (dat->fh, "\\r");
1210 }
1211 else if (c < 0x1f || c > 0xff)
1212 {
1213 // FIXME: handle surrogate pairs properly
1214 if (c >= 0xd800 && c < 0xdc00)
1215 {
1216 fprintf (dat->fh, "\\u%04x", c - 0x1000);
1217 }
1218 else if (c >= 0xdc00 && c < 0xe000)
1219 ;
1220 else
1221 fprintf (dat->fh, "\\u%04x", c);
1222 }
1223 else
1224 fprintf (dat->fh, "%c", (char)(c & 0xff));
1225 }
1226 fprintf (dat->fh, "\"");
1227 }
1228
1229 #else
1230
1231 static wchar_t *
wcquote(wchar_t * restrict dest,const wchar_t * restrict src)1232 wcquote (wchar_t *restrict dest, const wchar_t *restrict src)
1233 {
1234 wchar_t c;
1235 wchar_t *d = dest;
1236 wchar_t *s = (wchar_t *)src;
1237 while ((c = *s++))
1238 {
1239 if (c == L'"')
1240 {
1241 *dest++ = L'\\';
1242 *dest++ = c;
1243 }
1244 else if (c == L'\\' && s[0] == L'U' && s[1] == L'+' && ishex (s[2])
1245 && ishex (s[3]) && ishex (s[4]) && ishex (s[5]))
1246 {
1247 *dest++ = '\\';
1248 *dest++ = 'u';
1249 s += 2;
1250 }
1251 else if (c == L'\\')
1252 {
1253 *dest++ = L'\\';
1254 *dest++ = c;
1255 }
1256 else if (c == L'\n')
1257 {
1258 *dest++ = L'\\';
1259 *dest++ = L'n';
1260 }
1261 else if (c == L'\r')
1262 {
1263 *dest++ = L'\\';
1264 *dest++ = L'r';
1265 }
1266 else if (c < 0x1f)
1267 {
1268 *dest++ = L'\\';
1269 *dest++ = L'u';
1270 *dest++ = L'0';
1271 *dest++ = L'0';
1272 *dest++ = hex (c >> 4);
1273 *dest++ = hex (c & 0xf);
1274 }
1275 else
1276 *dest++ = c;
1277 }
1278 *dest = 0; // add final delim, skipped above
1279 return d;
1280 }
1281
1282 #endif /* HAVE_NATIVE_WCHAR2 */
1283
1284 char *
json_cquote(char * restrict dest,const char * restrict src,const int len)1285 json_cquote (char *restrict dest, const char *restrict src, const int len)
1286 {
1287 unsigned char c;
1288 unsigned char *s = (unsigned char *)src;
1289 const char* endp = dest + len;
1290 char *d = dest;
1291 while ((c = *s++))
1292 {
1293 if (dest >= endp)
1294 {
1295 *dest = 0;
1296 return d;
1297 }
1298 if (c == '"' && dest+1 < endp)
1299 {
1300 *dest++ = '\\';
1301 *dest++ = c;
1302 }
1303 else if (c == '\\' && dest+2 < endp)
1304 {
1305 if (dest+5 < endp && s[0] == 'U' && s[1] == '+' && ishex (s[2])
1306 && ishex (s[3]) && ishex (s[4]) && ishex (s[5]))
1307 {
1308 *dest++ = '\\';
1309 *dest++ = 'u';
1310 s += 2;
1311 }
1312 else
1313 {
1314 *dest++ = '\\';
1315 *dest++ = c;
1316 }
1317 }
1318 else if (c == '\n' && dest+1 < endp)
1319 {
1320 *dest++ = '\\';
1321 *dest++ = 'n';
1322 }
1323 else if (c == '\r' && dest+1 < endp)
1324 {
1325 *dest++ = '\\';
1326 *dest++ = 'r';
1327 }
1328 else if (c < 0x1f && dest+5 < endp)
1329 {
1330 *dest++ = '\\';
1331 *dest++ = 'u';
1332 *dest++ = '0';
1333 *dest++ = '0';
1334 *dest++ = hex (c >> 4);
1335 *dest++ = hex (c & 0xf);
1336 }
1337 else
1338 *dest++ = c;
1339 }
1340 *dest = 0; // add final delim, skipped above
1341 return d;
1342 }
1343
1344 static int
json_3dsolid(Bit_Chain * restrict dat,const Dwg_Object * restrict obj,Dwg_Entity_3DSOLID * restrict _obj)1345 json_3dsolid (Bit_Chain *restrict dat, const Dwg_Object *restrict obj,
1346 Dwg_Entity_3DSOLID *restrict _obj)
1347 {
1348 Dwg_Data *dwg = obj->parent;
1349 BITCODE_BL vcount;
1350 BITCODE_BL i;
1351 int error = 0;
1352
1353 FIELD_B (acis_empty, 0);
1354 if (!FIELD_VALUE (acis_empty))
1355 {
1356 char *s, *p;
1357 FIELD_B (unknown, 0);
1358 FIELD_BS (version, 70);
1359 KEY (acis_data);
1360 ARRAY;
1361 s = p = (char*)_obj->acis_data;
1362 if (!p)
1363 {
1364 FIRSTPREFIX fprintf (dat->fh, "\"\"");
1365 }
1366 else if (_obj->version < 2)
1367 { // split lines by \n
1368 for (; *p; p++)
1369 {
1370 char buf[256]; // acis lines are not much longer
1371 if (*p == '\n' && p - s < 256)
1372 {
1373 FIRSTPREFIX fprintf (dat->fh, "\"%s\"", json_cquote (buf, s, p - s));
1374 s = p + 1;
1375 }
1376 }
1377 // the remainder
1378 if (s != p && *s)
1379 {
1380 FIRSTPREFIX VALUE_TEXT (s);
1381 }
1382 }
1383 else // version 2, SAB. split into two lines for easier identification
1384 {
1385 FIRSTPREFIX fprintf (dat->fh, "\"%.*s\"", 15, _obj->acis_data);
1386 FIRSTPREFIX VALUE_BINARY (&_obj->acis_data[15], _obj->sab_size - 15, 1);
1387 }
1388 ENDARRAY;
1389 if (_obj->encr_sat_data) // dxfin/out may create this for SAB
1390 {
1391 KEY (encr_sat_data);
1392 ARRAY;
1393 for (i = 0; i < FIELD_VALUE (num_blocks); i++)
1394 {
1395 FIRSTPREFIX VALUE_BINARY (FIELD_VALUE (encr_sat_data[i]), FIELD_VALUE (block_size[i]), 1);
1396 }
1397 ENDARRAY;
1398 }
1399
1400 FIELD_B (wireframe_data_present, 0);
1401 if (FIELD_VALUE (wireframe_data_present))
1402 {
1403 FIELD_B (point_present, 0);
1404 if (FIELD_VALUE (point_present))
1405 {
1406 FIELD_3BD (point, 0);
1407 }
1408 FIELD_BL (isolines, 0);
1409 FIELD_B (isoline_present, 0);
1410 if (FIELD_VALUE (isoline_present))
1411 {
1412 FIELD_BL (num_wires, 0);
1413 REPEAT (num_wires, wires, Dwg_3DSOLID_wire)
1414 REPEAT_BLOCK
1415 WIRESTRUCT_fields (wires[rcount1])
1416 END_REPEAT_BLOCK
1417 SET_PARENT_OBJ (wires)
1418 END_REPEAT (wires);
1419 FIELD_BL (num_silhouettes, 0);
1420 REPEAT (num_silhouettes, silhouettes, Dwg_3DSOLID_silhouette)
1421 REPEAT_BLOCK
1422 SUB_FIELD_BL (silhouettes[rcount1], vp_id, 0);
1423 SUB_FIELD_3BD (silhouettes[rcount1], vp_target, 0);
1424 SUB_FIELD_3BD (silhouettes[rcount1], vp_dir_from_target, 0);
1425 SUB_FIELD_3BD (silhouettes[rcount1], vp_up_dir, 0);
1426 SUB_FIELD_B (silhouettes[rcount1], vp_perspective, 0);
1427 SUB_FIELD_B (silhouettes[rcount1], has_wires, 0);
1428 if (_obj->silhouettes[rcount1].has_wires)
1429 {
1430 SUB_FIELD_BL (silhouettes[rcount1], num_wires, 0);
1431 REPEAT2 (silhouettes[rcount1].num_wires, silhouettes[rcount1].wires, Dwg_3DSOLID_wire)
1432 REPEAT_BLOCK
1433 WIRESTRUCT_fields (silhouettes[rcount1].wires[rcount2])
1434 END_REPEAT_BLOCK
1435 SET_PARENT_OBJ (silhouettes[rcount1].wires)
1436 END_REPEAT (silhouettes[rcount1].wires);
1437 }
1438 END_REPEAT_BLOCK
1439 SET_PARENT_OBJ (silhouettes)
1440 END_REPEAT (silhouettes);
1441 }
1442 }
1443
1444 FIELD_B (acis_empty_bit, 0);
1445 if (FIELD_VALUE (version) > 1) {
1446 SINCE (R_2007) {
1447 FIELD_BL (num_materials, 0);
1448 REPEAT (num_materials, materials, Dwg_3DSOLID_material)
1449 REPEAT_BLOCK
1450 SUB_FIELD_BL (materials[rcount1], array_index, 0);
1451 SUB_FIELD_BL (materials[rcount1], mat_absref, 0); /* ?? */
1452 SUB_FIELD_HANDLE (materials[rcount1], material_handle, 5, 0);
1453 END_REPEAT_BLOCK
1454 SET_PARENT (materials, (Dwg_Entity__3DSOLID*)_obj)
1455 END_REPEAT (materials);
1456 }
1457 }
1458 SINCE (R_2013) {
1459 FIELD_B (has_revision_guid, 290);
1460 FIELD_BL (revision_major, 0);
1461 FIELD_BS (revision_minor1, 0);
1462 FIELD_BS (revision_minor2, 0);
1463 FIELD_TFFx (revision_bytes, 8, 0);
1464 dxf_3dsolid_revisionguid ((Dwg_Entity_3DSOLID*)_obj);
1465 FIELD_TV (revision_guid, 0);
1466 FIELD_BL (end_marker, 0);
1467 }
1468 COMMON_ENTITY_HANDLE_DATA;
1469 if (FIELD_VALUE (version) > 1)
1470 {
1471 SINCE (R_2007) { FIELD_HANDLE (history_id, 0, 350); }
1472 }
1473 }
1474 return error;
1475 }
1476
1477 /* returns 0 on success
1478 */
1479 static int
dwg_json_variable_type(Dwg_Data * restrict dwg,Bit_Chain * restrict dat,Dwg_Object * restrict obj)1480 dwg_json_variable_type (Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
1481 Dwg_Object *restrict obj)
1482 {
1483 int i;
1484 Dwg_Class *klass;
1485 int is_entity;
1486
1487 i = obj->type - 500;
1488 if (i < 0 || i >= (int)dwg->num_classes)
1489 return DWG_ERR_INVALIDTYPE;
1490
1491 klass = &dwg->dwg_class[i];
1492 if (!klass || !klass->dxfname)
1493 return DWG_ERR_INTERNALERROR;
1494 is_entity = dwg_class_is_entity (klass);
1495
1496 // clang-format off
1497 #include "classes.inc"
1498 // clang-format on
1499
1500 return DWG_ERR_UNHANDLEDCLASS;
1501 }
1502
1503 static int
dwg_json_object(Bit_Chain * restrict dat,Dwg_Object * restrict obj)1504 dwg_json_object (Bit_Chain *restrict dat, Dwg_Object *restrict obj)
1505 {
1506 int error = 0;
1507 switch (obj->type)
1508 {
1509 case DWG_TYPE_TEXT:
1510 return dwg_json_TEXT (dat, obj);
1511 case DWG_TYPE_ATTRIB:
1512 return dwg_json_ATTRIB (dat, obj);
1513 case DWG_TYPE_ATTDEF:
1514 return dwg_json_ATTDEF (dat, obj);
1515 case DWG_TYPE_BLOCK:
1516 return dwg_json_BLOCK (dat, obj);
1517 case DWG_TYPE_ENDBLK:
1518 return dwg_json_ENDBLK (dat, obj);
1519 case DWG_TYPE_SEQEND:
1520 return dwg_json_SEQEND (dat, obj);
1521 case DWG_TYPE_INSERT:
1522 return dwg_json_INSERT (dat, obj);
1523 case DWG_TYPE_MINSERT:
1524 return dwg_json_MINSERT (dat, obj);
1525 case DWG_TYPE_VERTEX_2D:
1526 return dwg_json_VERTEX_2D (dat, obj);
1527 case DWG_TYPE_VERTEX_3D:
1528 return dwg_json_VERTEX_3D (dat, obj);
1529 case DWG_TYPE_VERTEX_MESH:
1530 return dwg_json_VERTEX_MESH (dat, obj);
1531 case DWG_TYPE_VERTEX_PFACE:
1532 return dwg_json_VERTEX_PFACE (dat, obj);
1533 case DWG_TYPE_VERTEX_PFACE_FACE:
1534 return dwg_json_VERTEX_PFACE_FACE (dat, obj);
1535 case DWG_TYPE_POLYLINE_2D:
1536 return dwg_json_POLYLINE_2D (dat, obj);
1537 case DWG_TYPE_POLYLINE_3D:
1538 return dwg_json_POLYLINE_3D (dat, obj);
1539 case DWG_TYPE_ARC:
1540 return dwg_json_ARC (dat, obj);
1541 case DWG_TYPE_CIRCLE:
1542 return dwg_json_CIRCLE (dat, obj);
1543 case DWG_TYPE_LINE:
1544 return dwg_json_LINE (dat, obj);
1545 case DWG_TYPE_DIMENSION_ORDINATE:
1546 return dwg_json_DIMENSION_ORDINATE (dat, obj);
1547 case DWG_TYPE_DIMENSION_LINEAR:
1548 return dwg_json_DIMENSION_LINEAR (dat, obj);
1549 case DWG_TYPE_DIMENSION_ALIGNED:
1550 return dwg_json_DIMENSION_ALIGNED (dat, obj);
1551 case DWG_TYPE_DIMENSION_ANG3PT:
1552 return dwg_json_DIMENSION_ANG3PT (dat, obj);
1553 case DWG_TYPE_DIMENSION_ANG2LN:
1554 return dwg_json_DIMENSION_ANG2LN (dat, obj);
1555 case DWG_TYPE_DIMENSION_RADIUS:
1556 return dwg_json_DIMENSION_RADIUS (dat, obj);
1557 case DWG_TYPE_DIMENSION_DIAMETER:
1558 return dwg_json_DIMENSION_DIAMETER (dat, obj);
1559 case DWG_TYPE_POINT:
1560 return dwg_json_POINT (dat, obj);
1561 case DWG_TYPE__3DFACE:
1562 return dwg_json__3DFACE (dat, obj);
1563 case DWG_TYPE_POLYLINE_PFACE:
1564 return dwg_json_POLYLINE_PFACE (dat, obj);
1565 case DWG_TYPE_POLYLINE_MESH:
1566 return dwg_json_POLYLINE_MESH (dat, obj);
1567 case DWG_TYPE_SOLID:
1568 return dwg_json_SOLID (dat, obj);
1569 case DWG_TYPE_TRACE:
1570 return dwg_json_TRACE (dat, obj);
1571 case DWG_TYPE_SHAPE:
1572 return dwg_json_SHAPE (dat, obj);
1573 case DWG_TYPE_VIEWPORT:
1574 return dwg_json_VIEWPORT (dat, obj);
1575 case DWG_TYPE_ELLIPSE:
1576 return dwg_json_ELLIPSE (dat, obj);
1577 case DWG_TYPE_SPLINE:
1578 return dwg_json_SPLINE (dat, obj);
1579 case DWG_TYPE_REGION:
1580 return dwg_json_REGION (dat, obj);
1581 case DWG_TYPE__3DSOLID:
1582 return dwg_json__3DSOLID (dat, obj);
1583 case DWG_TYPE_BODY:
1584 return dwg_json_BODY (dat, obj);
1585 case DWG_TYPE_RAY:
1586 return dwg_json_RAY (dat, obj);
1587 case DWG_TYPE_XLINE:
1588 return dwg_json_XLINE (dat, obj);
1589 case DWG_TYPE_DICTIONARY:
1590 return dwg_json_DICTIONARY (dat, obj);
1591 case DWG_TYPE_MTEXT:
1592 return dwg_json_MTEXT (dat, obj);
1593 case DWG_TYPE_LEADER:
1594 return dwg_json_LEADER (dat, obj);
1595 case DWG_TYPE_TOLERANCE:
1596 return dwg_json_TOLERANCE (dat, obj);
1597 case DWG_TYPE_MLINE:
1598 return dwg_json_MLINE (dat, obj);
1599 case DWG_TYPE_BLOCK_CONTROL:
1600 return dwg_json_BLOCK_CONTROL (dat, obj);
1601 case DWG_TYPE_BLOCK_HEADER:
1602 return dwg_json_BLOCK_HEADER (dat, obj);
1603 case DWG_TYPE_LAYER_CONTROL:
1604 return dwg_json_LAYER_CONTROL (dat, obj);
1605 case DWG_TYPE_LAYER:
1606 return dwg_json_LAYER (dat, obj);
1607 case DWG_TYPE_STYLE_CONTROL:
1608 return dwg_json_STYLE_CONTROL (dat, obj);
1609 case DWG_TYPE_STYLE:
1610 return dwg_json_STYLE (dat, obj);
1611 case DWG_TYPE_LTYPE_CONTROL:
1612 return dwg_json_LTYPE_CONTROL (dat, obj);
1613 case DWG_TYPE_LTYPE:
1614 return dwg_json_LTYPE (dat, obj);
1615 case DWG_TYPE_VIEW_CONTROL:
1616 return dwg_json_VIEW_CONTROL (dat, obj);
1617 case DWG_TYPE_VIEW:
1618 return dwg_json_VIEW (dat, obj);
1619 case DWG_TYPE_UCS_CONTROL:
1620 return dwg_json_UCS_CONTROL (dat, obj);
1621 case DWG_TYPE_UCS:
1622 return dwg_json_UCS (dat, obj);
1623 case DWG_TYPE_VPORT_CONTROL:
1624 return dwg_json_VPORT_CONTROL (dat, obj);
1625 case DWG_TYPE_VPORT:
1626 return dwg_json_VPORT (dat, obj);
1627 case DWG_TYPE_APPID_CONTROL:
1628 return dwg_json_APPID_CONTROL (dat, obj);
1629 case DWG_TYPE_APPID:
1630 return dwg_json_APPID (dat, obj);
1631 case DWG_TYPE_DIMSTYLE_CONTROL:
1632 return dwg_json_DIMSTYLE_CONTROL (dat, obj);
1633 case DWG_TYPE_DIMSTYLE:
1634 return dwg_json_DIMSTYLE (dat, obj);
1635 case DWG_TYPE_VX_CONTROL:
1636 return dwg_json_VX_CONTROL (dat, obj);
1637 case DWG_TYPE_VX_TABLE_RECORD:
1638 return dwg_json_VX_TABLE_RECORD (dat, obj);
1639 case DWG_TYPE_GROUP:
1640 return dwg_json_GROUP (dat, obj);
1641 case DWG_TYPE_MLINESTYLE:
1642 return dwg_json_MLINESTYLE (dat, obj);
1643 case DWG_TYPE_OLE2FRAME:
1644 return dwg_json_OLE2FRAME (dat, obj);
1645 case DWG_TYPE_DUMMY:
1646 return dwg_json_DUMMY (dat, obj);
1647 case DWG_TYPE_LONG_TRANSACTION:
1648 return dwg_json_LONG_TRANSACTION (dat, obj);
1649 case DWG_TYPE_LWPOLYLINE:
1650 return dwg_json_LWPOLYLINE (dat, obj);
1651 case DWG_TYPE_HATCH:
1652 return dwg_json_HATCH (dat, obj);
1653 case DWG_TYPE_XRECORD:
1654 return dwg_json_XRECORD (dat, obj);
1655 case DWG_TYPE_PLACEHOLDER:
1656 return dwg_json_PLACEHOLDER (dat, obj);
1657 case DWG_TYPE_PROXY_ENTITY:
1658 return dwg_json_PROXY_ENTITY (dat, obj);
1659 case DWG_TYPE_PROXY_OBJECT:
1660 return dwg_json_PROXY_OBJECT (dat, obj);
1661 case DWG_TYPE_OLEFRAME:
1662 return dwg_json_OLEFRAME (dat, obj);
1663 case DWG_TYPE_VBA_PROJECT:
1664 LOG_ERROR ("Unhandled Object VBA_PROJECT. Has its own section\n");
1665 // dwg_json_VBA_PROJECT(dat, obj);
1666 break;
1667 case DWG_TYPE_LAYOUT:
1668 return dwg_json_LAYOUT (dat, obj);
1669 default:
1670 if (obj->type != 0 && obj->type == obj->parent->layout_type)
1671 {
1672 return dwg_json_LAYOUT (dat, obj);
1673 }
1674 /* > 500 */
1675 else if (DWG_ERR_UNHANDLEDCLASS
1676 & (error = dwg_json_variable_type (obj->parent, dat, obj)))
1677 {
1678 Dwg_Data *dwg = obj->parent;
1679 int is_entity;
1680 int i = obj->type - 500;
1681 Dwg_Class *klass = NULL;
1682 int num_bytes = obj->num_unknown_bits / 8;
1683 if (obj->num_unknown_bits & 8)
1684 num_bytes++;
1685
1686 if (i >= 0 && i < (int)dwg->num_classes)
1687 {
1688 klass = &dwg->dwg_class[i];
1689 is_entity = dwg_class_is_entity (klass);
1690 }
1691 // properly dwg_decode_object/_entity for eed, reactors, xdic
1692 if (klass && !is_entity)
1693 {
1694 error |= dwg_json_UNKNOWN_OBJ (dat, obj);
1695 KEY (num_unknown_bits);
1696 VALUE_RL (obj->num_unknown_bits, 0);
1697 KEY (unknown_bits);
1698 VALUE_BINARY (obj->unknown_bits, num_bytes, 0);
1699 return error;
1700 }
1701 else if (klass)
1702 {
1703 error |= dwg_json_UNKNOWN_ENT (dat, obj);
1704 KEY (num_unknown_bits);
1705 VALUE_RL (obj->num_unknown_bits, 0);
1706 KEY (unknown_bits);
1707 VALUE_BINARY (obj->unknown_bits, num_bytes, 0);
1708 return error;
1709 }
1710 else // not a class
1711 {
1712 goto invalid_type;
1713 }
1714 }
1715 else
1716 return 0;
1717 }
1718 invalid_type:
1719 LOG_WARN ("Unknown object, skipping eed/reactors/xdic/...");
1720 FIELD_TEXT (object, obj->name);
1721 if (obj->dxfname && strNE (obj->dxfname, obj->name))
1722 FIELD_TEXT (dxfname, obj->dxfname);
1723 _FIELD (index, RL, 0);
1724 _FIELD (type, RL, 0);
1725 KEY (handle);
1726 VALUE_H (obj->handle, 5);
1727 _FIELD (size, RL, 0);
1728 _FIELD (bitsize, BL, 0);
1729 return DWG_ERR_INVALIDTYPE;
1730 }
1731
1732 static int
json_fileheader_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1733 json_fileheader_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1734 {
1735 Dwg_Header *_obj = &dwg->header;
1736 Dwg_Object *obj = NULL;
1737 int i;
1738
1739 RECORD (FILEHEADER); // single hash
1740 KEY (version);
1741 fprintf (dat->fh, "\"%s\"", version_codes[dwg->header.version]);
1742 // clang-format off
1743 #include "header.spec"
1744 // clang-format on
1745 ENDRECORD ();
1746 return 0;
1747 }
1748
1749 static int
json_header_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1750 json_header_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1751 {
1752 Dwg_Header_Variables *_obj = &dwg->header_vars;
1753 Dwg_Object *obj = NULL;
1754 // const int minimal = 0;
1755 char buf[4096];
1756 double ms;
1757 const char *codepage
1758 = (dwg->header.codepage == 30 || dwg->header.codepage == 0)
1759 ? "ANSI_1252"
1760 : (dwg->header.version >= R_2007) ? "UTF-8" : "ANSI_1252";
1761
1762 RECORD (HEADER); // single hash
1763 // clang-format off
1764 #include "header_variables.spec"
1765 // clang-format on
1766 ENDRECORD ();
1767 return 0;
1768 }
1769
1770 static int
json_classes_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1771 json_classes_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1772 {
1773 BITCODE_BS i;
1774
1775 SECTION (CLASSES); // list of classes
1776 for (i = 0; i < dwg->num_classes; i++)
1777 {
1778 Dwg_Class *_obj = &dwg->dwg_class[i];
1779 FIRSTPREFIX HASH;
1780 FIELD_BS (number, 0);
1781 FIELD_TV (dxfname, 1);
1782 FIELD_T (cppname, 2);
1783 FIELD_T (appname, 3);
1784 FIELD_BS (proxyflag, 90);
1785 FIELD_BL (num_instances, 91);
1786 FIELD_B (is_zombie, 280);
1787 FIELD_BS (item_class_id, 281);
1788 ENDHASH
1789 CLEARFIRST;
1790 }
1791 ENDSEC ();
1792 return 0;
1793 }
1794
1795 static int
json_objects_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1796 json_objects_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1797 {
1798 BITCODE_BL i;
1799
1800 CLEARFIRST;
1801 SECTION (OBJECTS);
1802 for (i = 0; i < dwg->num_objects; i++)
1803 {
1804 int error;
1805 Dwg_Object *obj = &dwg->object[i];
1806 FIRSTPREFIX HASH;
1807 error = dwg_json_object (dat, obj);
1808 ENDHASH
1809 CLEARFIRST;
1810 }
1811 ENDSEC ();
1812 return 0;
1813 }
1814
1815 #if 0
1816 /* The object map/handles section */
1817 static int
1818 json_handles_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1819 {
1820 BITCODE_BL j;
1821 CLEARFIRST;
1822 SECTION (HANDLES);
1823 for (j = 0; j < dwg->num_objects; j++)
1824 {
1825 Dwg_Object *obj = &dwg->object[j];
1826 // handle => abs. offset
1827 // TODO: The real HANDLES section omap has handleoffset (deleted holes) and addressoffset
1828 FIRSTPREFIX fprintf (dat->fh, "[ %lu, %lu ]", obj->handle.value, obj->address);
1829 }
1830 ENDSEC ();
1831 return 0;
1832 }
1833 #endif
1834
1835 static int
json_thumbnail_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1836 json_thumbnail_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1837 {
1838 Bit_Chain *_obj = (Bit_Chain *)&dwg->thumbnail;
1839 if (_obj->chain && _obj->size && _obj->size > 10)
1840 {
1841 /* SECTION_PREVIEW includes the sentinel.
1842 _obj->byte is at the BMP offset, via dwg_bmp */
1843 if (dwg->header.from_version >= R_2004)
1844 _obj->chain += 16; /* skip the sentinel */
1845 KEY (THUMBNAILIMAGE);
1846 HASH;
1847 FIRSTPREFIX fprintf (dat->fh, "\"size\": %lu", _obj->size);
1848 FIELD_BINARY (chain, _obj->size, 310);
1849 if (dwg->header.from_version >= R_2004)
1850 _obj->chain -= 16; /* undo for free */
1851 ENDHASH;
1852 }
1853 return 0;
1854 }
1855
1856 static int
json_section_r2004fileheader(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1857 json_section_r2004fileheader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1858 {
1859 Dwg_R2004_Header *_obj = &dwg->r2004_header;
1860 Dwg_Object *obj = NULL;
1861 int i;
1862
1863 RECORD (R2004_Header); // single hash
1864 // clang-format off
1865 #include "r2004_file_header.spec"
1866 // clang-format on
1867 ENDRECORD ();
1868 return 0;
1869 }
1870
1871 static int
json_section_summary(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1872 json_section_summary (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1873 {
1874 Dwg_SummaryInfo *_obj = &dwg->summaryinfo;
1875 Dwg_Object *obj = NULL;
1876 int error = 0;
1877
1878 RECORD (SummaryInfo); // single hash
1879 // clang-format off
1880 #include "summaryinfo.spec"
1881 // clang-format on
1882 ENDRECORD ();
1883 return 0;
1884 }
1885
1886 static int
json_section_vbaproject(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1887 json_section_vbaproject (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1888 {
1889 Dwg_VBAProject *_obj = &dwg->vbaproject;
1890 Dwg_Object *obj = NULL;
1891 int error = 0;
1892
1893 RECORD (VBAProject); // single hash
1894 HASH;
1895 // clang-format off
1896 //#include "vbaproject.spec"
1897 // clang-format on
1898 ENDRECORD ();
1899 return 0;
1900 }
1901
1902 static int
json_section_appinfo(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1903 json_section_appinfo (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1904 {
1905 Dwg_AppInfo *_obj = &dwg->appinfo;
1906 Dwg_Object *obj = NULL;
1907 int error = 0;
1908
1909 RECORD (AppInfo); // single hash
1910 // clang-format off
1911 #include "appinfo.spec"
1912 // clang-format on
1913 ENDRECORD ();
1914 return 0;
1915 }
1916
1917 static int
json_section_appinfohistory(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1918 json_section_appinfohistory (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1919 {
1920 Dwg_AppInfoHistory *_obj = &dwg->appinfohistory;
1921 Dwg_Object *obj = NULL;
1922 int error = 0;
1923
1924 RECORD (AppInfoHistory); // single hash
1925 FIRSTPREFIX fprintf (dat->fh, "\"size\": %d", _obj->size);
1926 FIELD_BINARY (unknown_bits, _obj->size, 0);
1927 // clang-format off
1928 //#include "appinfohistory.spec"
1929 // clang-format on
1930 ENDRECORD ();
1931 return 0;
1932 }
1933
1934 static int
json_section_filedeplist(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1935 json_section_filedeplist (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1936 {
1937 Dwg_FileDepList *_obj = &dwg->filedeplist;
1938 Dwg_Object *obj = NULL;
1939 int error = 0;
1940 BITCODE_RL vcount;
1941
1942 RECORD (FileDepList); // single hash
1943 // clang-format off
1944 #include "filedeplist.spec"
1945 // clang-format on
1946 ENDRECORD ();
1947 return 0;
1948 }
1949
1950 static int
json_section_security(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1951 json_section_security (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1952 {
1953 Dwg_Security *_obj = &dwg->security;
1954 Dwg_Object *obj = NULL;
1955 int error = 0;
1956
1957 RECORD (Security); // single hash
1958 // clang-format off
1959 #include "security.spec"
1960 // clang-format on
1961 ENDRECORD ();
1962 return 0;
1963 }
1964
1965 static int
json_section_revhistory(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1966 json_section_revhistory (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1967 {
1968 Dwg_RevHistory *_obj = &dwg->revhistory;
1969 Dwg_Object *obj = NULL;
1970 int error = 0;
1971 BITCODE_RL vcount;
1972
1973 RECORD (RevHistory); // single hash
1974 FIELD_RL (class_version, 0);
1975 FIELD_RL (class_minor, 0);
1976 FIELD_RL (num_histories, 0);
1977 FIELD_VECTOR (histories, RL, num_histories, 0)
1978 ENDRECORD ();
1979 return 0;
1980 }
1981
1982 static int
json_section_objfreespace(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1983 json_section_objfreespace (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1984 {
1985 Dwg_ObjFreeSpace *_obj = &dwg->objfreespace;
1986 Dwg_Object *obj = NULL;
1987 int error = 0;
1988
1989 RECORD (ObjFreeSpace); // single hash
1990 // clang-format off
1991 #include "objfreespace.spec"
1992 // clang-format on
1993 ENDRECORD ();
1994 return 0;
1995 }
1996
1997 static int
json_section_acds(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1998 json_section_acds (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1999 {
2000 Dwg_AcDs *_obj = &dwg->acds;
2001 Dwg_Object *obj = NULL;
2002 int error = 0;
2003 BITCODE_RL rcount3 = 0, rcount4, vcount;
2004
2005 RECORD (AcDs); // single hash
2006 {
2007 // clang-format off
2008 #include "acds.spec"
2009 // clang-format on
2010 }
2011 ENDRECORD ();
2012 return 0;
2013 }
2014
2015 static int
json_section_template(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)2016 json_section_template (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2017 {
2018 Dwg_Template *_obj = &dwg->Template;
2019 Dwg_Object *obj = NULL;
2020 int error = 0;
2021
2022 RECORD (Template); // single hash. i.e MEASUREMENT metric/imperial
2023 // clang-format off
2024 #include "template.spec"
2025 // clang-format on
2026 ENDRECORD ();
2027 return 0;
2028 }
2029
2030 static int
json_section_auxheader(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)2031 json_section_auxheader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2032 {
2033 Dwg_AuxHeader *_obj = &dwg->auxheader;
2034 Dwg_Object *obj = NULL;
2035 int error = 0, i;
2036 BITCODE_RL vcount;
2037
2038 RECORD (AuxHeader); // single hash
2039 // clang-format off
2040 #include "auxheader.spec"
2041 // clang-format on
2042 ENDRECORD ();
2043 return 0;
2044 }
2045
2046 #if 0
2047 static int
2048 json_section_signature (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2049 {
2050 struct Dwg_Signature *_obj = &dwg->signature;
2051 Dwg_Object *obj = NULL;
2052 int error = 0;
2053
2054 RECORD (Signature); // single hash
2055 // clang-format off
2056 #include "signature.spec"
2057 // clang-format on
2058 ENDRECORD ();
2059 return 0;
2060 }
2061
2062 static int
2063 json_section_2ndheader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2064 {
2065 struct _dwg_second_header *_obj = &dwg->second_header;
2066 Dwg_Object *obj = NULL;
2067 int error = 0;
2068
2069 RECORD (SecondHeader); // single hash
2070 HASH;
2071 // clang-format off
2072 //#include "2ndheader.spec"
2073 // clang-format on
2074 ENDRECORD ();
2075 return 0;
2076 }
2077 #endif
2078
2079 EXPORT int
dwg_write_json(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)2080 dwg_write_json (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2081 {
2082 const int minimal = dwg->opts & DWG_OPTS_MINIMAL;
2083 Dwg_Header *obj = &dwg->header;
2084 int error = 0;
2085
2086 fprintf (dat->fh, "{\n \"created_by\": \"%s\"", PACKAGE_STRING);
2087 dat->bit++; // ident
2088
2089 if (!minimal)
2090 {
2091 json_fileheader_write (dat, dwg);
2092 }
2093
2094 // A minimal HEADER requires only $ACADVER, $HANDSEED, and then ENTITIES
2095 json_header_write (dat, dwg);
2096
2097 if (!minimal && dat->version >= R_13)
2098 {
2099 if (json_classes_write (dat, dwg) >= DWG_ERR_CRITICAL)
2100 goto fail;
2101 }
2102
2103 if (json_objects_write (dat, dwg) >= DWG_ERR_CRITICAL)
2104 goto fail;
2105
2106 if (!minimal && dat->version >= R_13)
2107 {
2108 if (json_thumbnail_write (dat, dwg) >= DWG_ERR_CRITICAL)
2109 goto fail;
2110 /* the other sections */
2111 if (dat->version <= R_2000)
2112 {
2113 error |= json_section_template (dat, dwg); // i.e. MEASUREMENT
2114 error |= json_section_auxheader (dat, dwg);
2115 //error |= json_section_2ndheader (dat, dwg);
2116 }
2117 if (dat->version >= R_2004)
2118 {
2119 error |= json_section_r2004fileheader (dat, dwg);
2120 if (dwg->header.summaryinfo_address)
2121 error |= json_section_summary (dat, dwg);
2122 if (dwg->header.vbaproj_address)
2123 error |= json_section_vbaproject (dat, dwg);
2124 error |= json_section_appinfo (dat, dwg);
2125 error |= json_section_appinfohistory (dat, dwg);
2126 error |= json_section_filedeplist (dat, dwg);
2127 error |= json_section_security (dat, dwg);
2128 error |= json_section_revhistory (dat, dwg);
2129 error |= json_section_objfreespace (dat, dwg);
2130 //error |= json_section_signature (dat, dwg);
2131 error |= json_section_template (dat, dwg);
2132 error |= json_section_acds (dat, dwg);
2133 }
2134 }
2135
2136 #if 0
2137 /* object map */
2138 if (!minimal && dat->version >= R_13)
2139 {
2140 if (json_handles_write (dat, dwg) >= DWG_ERR_CRITICAL)
2141 goto fail;
2142 }
2143 #endif
2144
2145 dat->bit--;
2146 fprintf (dat->fh, "}\n");
2147 return 0;
2148 fail:
2149 return 1;
2150 }
2151