/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 | } |