Line | Count | Source |
1 | | /*****************************************************************************/ |
2 | | /* LibreDWG - free implementation of the DWG file format */ |
3 | | /* */ |
4 | | /* Copyright (C) 2009-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 | | * bits.c: low level read and write function prototypes |
15 | | * written by Felipe Castro |
16 | | * modified by Felipe CorrĂȘa da Silva Sances |
17 | | * modified by Rodrigo Rodrigues da Silva |
18 | | * modified by Reini Urban |
19 | | */ |
20 | | |
21 | | /** |
22 | | The position of bits within bytes is numerically ordered as depicted below: |
23 | | |
24 | | \code |
25 | | position: 01234567 01234567 01234567 ... |
26 | | bits: 76543210 76543210 76543210 ... |
27 | | \______/ \______/ \______/ |
28 | | byte 1 byte 2 byte 3 ... |
29 | | \endcode |
30 | | (i.e. little endian) |
31 | | */ |
32 | | |
33 | | #ifndef BITS_H |
34 | | #define BITS_H |
35 | | |
36 | | #include "config.h" |
37 | | #ifdef HAVE_WCHAR_H |
38 | | // cross-compilation problem: |
39 | | // /usr/lib/gcc/arm-linux-gnueabi/9/include-fixed/limits.h defines it as 1 |
40 | | # if defined(MB_LEN_MAX) && MB_LEN_MAX != 16 && MB_LEN_MAX != 32 |
41 | | # undef MB_LEN_MAX |
42 | | # define MB_LEN_MAX 16 |
43 | | # endif |
44 | | # include <wchar.h> |
45 | | #endif |
46 | | #include <stdio.h> |
47 | | #include <string.h> |
48 | | #include <stddef.h> |
49 | | #include <stdbool.h> |
50 | | #include "common.h" |
51 | | #include "dwg.h" |
52 | | |
53 | | // DWG size limitations, invalid sizes and offsets |
54 | | #if SIZEOF_SIZE_T == 8 |
55 | 1.69G | # define MAX_MEM_ALLOC 0x10000000000 |
56 | | #else |
57 | | # define MAX_MEM_ALLOC 0xF0000000 |
58 | | #endif |
59 | | |
60 | | // avoid double linkage on windows with unit-testing |
61 | | #if defined(BITS_TEST_C) || defined(DECODE_TEST_C) || defined(DXF_TEST_C) |
62 | | # undef EXPORT |
63 | | # define EXPORT |
64 | | #endif |
65 | | |
66 | | /** |
67 | | Structure for DWG-files raw data streams. |
68 | | */ |
69 | | typedef struct _bit_chain |
70 | | { |
71 | | unsigned char *chain; |
72 | | size_t size; |
73 | | size_t byte; |
74 | | unsigned char bit; |
75 | | unsigned char opts; // from dwg->opts, see DWG_OPTS_* |
76 | | Dwg_Version_Type version; |
77 | | Dwg_Version_Type from_version; |
78 | | FILE *fh; |
79 | | BITCODE_RS codepage; |
80 | | } Bit_Chain; |
81 | | |
82 | | #define EMPTY_CHAIN(size) \ |
83 | | { \ |
84 | | NULL, size, 0UL, 0, 0, R_INVALID, R_INVALID, NULL, 0 \ |
85 | | } |
86 | | |
87 | | // only if from r2007+ DWG. not JSON, DXF (FIXME TABLE.name). add API converts |
88 | | // to TU |
89 | | #define IS_FROM_TU(dat) \ |
90 | 7.05k | (dat->from_version >= R_2007) && !(dat->opts & DWG_OPTS_IN) |
91 | | #define IS_FROM_TU_DWG(dwg) \ |
92 | 43.7k | (dwg->header.from_version >= R_2007) && !(dwg->opts & DWG_OPTS_IN) |
93 | | #define TU_to_int(b) le16toh (((uint16_t)b[1] << 8) + b[0]) |
94 | | |
95 | | /* Functions for raw data manipulations. |
96 | | */ |
97 | | void bit_advance_position (Bit_Chain *dat, long advance); |
98 | | size_t bit_position (Bit_Chain *dat); |
99 | | void bit_set_position (Bit_Chain *dat, size_t bitpos); |
100 | | void bit_reset_chain (Bit_Chain *dat); |
101 | | |
102 | | BITCODE_B bit_read_B (Bit_Chain *dat); |
103 | | void bit_write_B (Bit_Chain *dat, unsigned char value); |
104 | | |
105 | | BITCODE_BB bit_read_BB (Bit_Chain *dat); |
106 | | void bit_write_BB (Bit_Chain *dat, unsigned char value); |
107 | | |
108 | | BITCODE_4BITS bit_read_4BITS (Bit_Chain *dat); |
109 | | void bit_write_4BITS (Bit_Chain *dat, unsigned char value); |
110 | | |
111 | | BITCODE_RC bit_read_RC (Bit_Chain *dat); |
112 | | void bit_write_RC (Bit_Chain *dat, unsigned char value); |
113 | | |
114 | | BITCODE_RS bit_read_RS (Bit_Chain *dat); |
115 | | void bit_write_RS (Bit_Chain *dat, BITCODE_RS value); |
116 | | BITCODE_BS bit_read_RS_BE (Bit_Chain *dat); |
117 | | void bit_write_RS_BE (Bit_Chain *dat, BITCODE_BS value); |
118 | | |
119 | | BITCODE_RL bit_read_RL (Bit_Chain *dat); |
120 | | BITCODE_RL bit_read_RL_BE (Bit_Chain *dat); |
121 | | void bit_write_RL (Bit_Chain *dat, BITCODE_RL value); |
122 | | void bit_write_RL_BE (Bit_Chain *dat, BITCODE_RL value); |
123 | | |
124 | | BITCODE_RLL bit_read_RLL (Bit_Chain *dat); |
125 | | BITCODE_RLL bit_read_RLL_BE (Bit_Chain *dat); |
126 | 0 | #define bit_read_RLLd(dat) (BITCODE_RLLd) bit_read_RLL (dat) |
127 | | void bit_write_RLL (Bit_Chain *dat, BITCODE_RLL value); |
128 | | #define bit_write_RLLd(dat, value) bit_write_RLL (dat, (BITCODE_RLL)value) |
129 | | void bit_write_RLL_BE (Bit_Chain *dat, BITCODE_RLL value); |
130 | | |
131 | | BITCODE_RD bit_read_RD (Bit_Chain *dat); |
132 | | void bit_write_RD (Bit_Chain *dat, BITCODE_RD value); |
133 | | |
134 | | /* Functions for manipulating compacted data |
135 | | */ |
136 | | BITCODE_BS bit_read_BS (Bit_Chain *dat); |
137 | | void bit_write_BS (Bit_Chain *dat, BITCODE_BS value); |
138 | | |
139 | | BITCODE_BL bit_read_BL (Bit_Chain *dat); |
140 | | void bit_write_BL (Bit_Chain *dat, BITCODE_BL value); |
141 | 0 | #define bit_read_BLd(dat) (BITCODE_BLd) bit_read_BL (dat) |
142 | | void bit_write_BLd (Bit_Chain *dat, BITCODE_BLd value); |
143 | | |
144 | | BITCODE_BS bit_read_BOT (Bit_Chain *dat); |
145 | | void bit_write_BOT (Bit_Chain *dat, BITCODE_BS value); |
146 | | |
147 | | BITCODE_BLL bit_read_BLL (Bit_Chain *dat); |
148 | | void bit_write_BLL (Bit_Chain *dat, BITCODE_BLL value); |
149 | | |
150 | | #if 0 |
151 | | BITCODE_3B bit_read_3B (Bit_Chain *dat); |
152 | | void bit_write_3B (Bit_Chain *dat, unsigned char value); |
153 | | BITCODE_BLL bit_read_3BLL (Bit_Chain *dat); /*unused but as documented*/ |
154 | | void bit_write_3BLL (Bit_Chain *dat, BITCODE_BLL value); |
155 | | #endif |
156 | | |
157 | | BITCODE_BD bit_read_BD (Bit_Chain *dat); |
158 | | void bit_write_BD (Bit_Chain *dat, BITCODE_BD value); |
159 | | |
160 | | BITCODE_MC bit_read_MC (Bit_Chain *dat); |
161 | | void bit_write_MC (Bit_Chain *dat, BITCODE_MC value); |
162 | | |
163 | | BITCODE_UMC bit_read_UMC (Bit_Chain *dat); |
164 | | void bit_write_UMC (Bit_Chain *dat, BITCODE_UMC value); |
165 | | |
166 | | BITCODE_MS bit_read_MS (Bit_Chain *dat); |
167 | | void bit_write_MS (Bit_Chain *dat, BITCODE_MS value); |
168 | | |
169 | | void bit_read_BE (Bit_Chain *restrict dat, double *restrict x, |
170 | | double *restrict y, double *restrict z); |
171 | | void bit_write_BE (Bit_Chain *dat, double x, double y, double z); |
172 | | void normalize_BE (BITCODE_3BD ext); |
173 | | |
174 | | BITCODE_DD bit_read_DD (Bit_Chain *dat, double default_value); |
175 | | BITCODE_BB bit_write_DD (Bit_Chain *dat, double value, double default_value); |
176 | | int bit_eq_DD (double value, double default_value); |
177 | | |
178 | | BITCODE_BT bit_read_BT (Bit_Chain *dat); |
179 | | void bit_write_BT (Bit_Chain *dat, double value); |
180 | | |
181 | | int bit_read_H (Bit_Chain *restrict dat, Dwg_Handle *restrict handle); |
182 | | void bit_write_H (Bit_Chain *restrict dat, Dwg_Handle *restrict handle); |
183 | | void bit_H_to_dat (Bit_Chain *restrict dat, Dwg_Handle *restrict handle); |
184 | | |
185 | | uint16_t bit_read_CRC (Bit_Chain *dat); |
186 | | |
187 | | int bit_check_CRC (Bit_Chain *dat, size_t start_address, const uint16_t seed); |
188 | | uint16_t bit_write_CRC (Bit_Chain *dat, size_t start_address, |
189 | | const uint16_t seed); |
190 | | // object-map only |
191 | | uint16_t bit_write_CRC_BE (Bit_Chain *dat, size_t start_address, |
192 | | const uint16_t seed); |
193 | | |
194 | | uint16_t bit_calc_CRC (const uint16_t seed, unsigned char *adr, size_t len); |
195 | | uint32_t bit_calc_CRC32 (const uint32_t seed, unsigned char *adr, size_t len); |
196 | | |
197 | | int bit_read_fixed (Bit_Chain *restrict dat, BITCODE_RC *restrict dest, |
198 | | size_t length); |
199 | | |
200 | | /* read fixed-length ASCII string */ |
201 | | BITCODE_TF bit_read_TF (Bit_Chain *dat, size_t length) ATTRIBUTE_MALLOC; |
202 | | BITCODE_TF bit_read_bits (Bit_Chain *dat, size_t bits) ATTRIBUTE_MALLOC; |
203 | | void bit_write_bits (Bit_Chain *restrict dat, BITCODE_TF restrict bits, |
204 | | size_t numbits); |
205 | | |
206 | | void bit_write_TF (Bit_Chain *restrict dat, BITCODE_TF restrict chain, |
207 | | size_t length); |
208 | | /** Write fixed-length text from variable length string |
209 | | (possibly downgraded from shorter string). |
210 | | */ |
211 | | void bit_write_TFv (Bit_Chain *restrict dat, BITCODE_TF restrict chain, |
212 | | size_t length); |
213 | | |
214 | | /* read ASCII string, with length as BS */ |
215 | | BITCODE_TV bit_read_TV (Bit_Chain *restrict dat); |
216 | | |
217 | | void bit_write_TV (Bit_Chain *restrict dat, BITCODE_TV restrict value); |
218 | | |
219 | | /* read UCS-2 string, with length as BS */ |
220 | | BITCODE_TU bit_read_TU (Bit_Chain *restrict dat) ATTRIBUTE_MALLOC; |
221 | | BITCODE_TU bit_read_TU_len (Bit_Chain *restrict dat, |
222 | | unsigned int *lenp) ATTRIBUTE_MALLOC; |
223 | | BITCODE_TU bit_read_TU_size (Bit_Chain *restrict dat, |
224 | | unsigned int len) ATTRIBUTE_MALLOC; |
225 | | |
226 | | /* read ASCII string, with length as RS */ |
227 | | BITCODE_T16 bit_read_T16 (Bit_Chain *restrict dat) ATTRIBUTE_MALLOC; |
228 | | /* read UCS-2 string, with length as RS */ |
229 | | BITCODE_TU bit_read_TU16 (Bit_Chain *restrict dat) ATTRIBUTE_MALLOC; |
230 | | /* read ASCII/UCS-2 string, with length as RL */ |
231 | | BITCODE_T32 bit_read_T32 (Bit_Chain *restrict dat) ATTRIBUTE_MALLOC; |
232 | | /* read ASCII/UCS-4 string, with length as RL */ |
233 | | BITCODE_TU32 bit_read_TU32 (Bit_Chain *restrict dat) ATTRIBUTE_MALLOC; |
234 | | |
235 | | void bit_write_TU (Bit_Chain *restrict dat, BITCODE_TU restrict value); |
236 | | void bit_write_TU16 (Bit_Chain *restrict dat, BITCODE_TU restrict value); |
237 | | void bit_write_T16 (Bit_Chain *restrict dat, BITCODE_T16 restrict value); |
238 | | void bit_write_T32 (Bit_Chain *restrict dat, BITCODE_T32 restrict value); |
239 | | void bit_write_TU32 (Bit_Chain *restrict dat, BITCODE_TU32 restrict value); |
240 | | |
241 | | BITCODE_T bit_read_T (Bit_Chain *restrict dat) ATTRIBUTE_MALLOC; |
242 | | void bit_write_T (Bit_Chain *restrict dat, BITCODE_T restrict chain); |
243 | | |
244 | | /* Converts UCS-2 to ASCII (with \U+XXXX), returning a copy. */ |
245 | | EXPORT char *bit_embed_TU (BITCODE_TU restrict wstr) ATTRIBUTE_MALLOC; |
246 | | EXPORT char *bit_embed_TU_size (BITCODE_TU restrict wstr, |
247 | | const int len) ATTRIBUTE_MALLOC; |
248 | | |
249 | | #ifdef HAVE_NATIVE_WCHAR2 |
250 | | # define bit_wcs2len(wstr) wcslen (wstr) |
251 | | # ifdef HAVE_WCSNLEN |
252 | | # define bit_wcs2nlen(wstr, maxlen) wcsnlen (wstr, maxlen) |
253 | | # else |
254 | | size_t bit_wcs2nlen (const BITCODE_TU restrict wstr, const size_t maxlen); |
255 | | # endif |
256 | | # define bit_wcs2cpy(dest, src) wcscpy (dest, src) |
257 | | # ifdef _WIN32 |
258 | | # define bit_wcs2dup(src) _wcsdup (src) |
259 | | # else |
260 | | # define bit_wcs2dup(src) wcsdup (src) |
261 | | # endif |
262 | | # define bit_wcs2cmp(dest, src) wcscmp (s1, s2) |
263 | | #else |
264 | | /* length of UCS-2 string */ |
265 | | size_t bit_wcs2len (const BITCODE_TU restrict wstr); |
266 | | /* bounded length of UCS-2 string. stops scanning at maxlen. |
267 | | Beware: might overflow to negative lengths */ |
268 | | size_t bit_wcs2nlen (const BITCODE_TU restrict wstr, const size_t maxlen); |
269 | | BITCODE_TU bit_wcs2cpy (BITCODE_TU restrict dest, |
270 | | const BITCODE_TU restrict src); |
271 | | BITCODE_TU bit_wcs2dup (const BITCODE_TU restrict src); |
272 | | int bit_wcs2cmp (BITCODE_TU restrict s1, const BITCODE_TU restrict s2); |
273 | | #endif |
274 | | |
275 | | #ifndef HAVE_STRNLEN |
276 | | size_t bit_strnlen (const char *restrict str, const size_t maxlen); |
277 | | # define strnlen(str, maxlen) bit_strnlen (str, maxlen) |
278 | | #endif |
279 | | |
280 | | /* Convert UCS-2LE to UTF-8, returning a copy. */ |
281 | | EXPORT char *bit_convert_TU (const BITCODE_TU restrict wstr) ATTRIBUTE_MALLOC; |
282 | | EXPORT char *bit_TU_to_utf8_len (const BITCODE_TU restrict wstr, |
283 | | const int len) ATTRIBUTE_MALLOC; |
284 | | |
285 | | /** Converts UTF-8 (dxf,json) to ASCII TV. |
286 | | \uxxxx or other unicode => \U+XXXX if not representable in this codepage. |
287 | | If cquoted unquotes \" to ", undo json_cquote(), |
288 | | Returns NULL if not enough room in dest. */ |
289 | | EXPORT char *bit_utf8_to_TV (char *restrict dest, |
290 | | const unsigned char *restrict src, |
291 | | const size_t destlen, const size_t srclen, |
292 | | const unsigned cquoted, |
293 | | const BITCODE_RS codepage); |
294 | | /** converts old codepage'd strings to UTF-8. |
295 | | convert \U+XXXX or \MnXXXX also if representable. |
296 | | returns NULL on errors, or the unchanged src string, or a copy. |
297 | | */ |
298 | | EXPORT |
299 | | char *bit_TV_to_utf8 (const char *restrict src, |
300 | | const BITCODE_RS codepage) ATTRIBUTE_MALLOC; |
301 | | |
302 | | /** Converts UTF-8 to UCS-2. Returns a copy. |
303 | | Needed by dwg importers, writers (e.g. dxf2dwg) |
304 | | cquoted is needed by in_json, to unquote \" |
305 | | */ |
306 | | EXPORT BITCODE_TU bit_utf8_to_TU (char *restrict str, |
307 | | const unsigned cquoted) ATTRIBUTE_MALLOC; |
308 | | // convert all \\U+XXXX and \\M+nXXXX sequences to UTF-8 |
309 | | const char *bit_u_expand (const char *src); |
310 | | |
311 | | /* compare an ASCII/TU string to ASCII name */ |
312 | | int bit_eq_T (Bit_Chain *restrict dat, const BITCODE_T restrict str1, |
313 | | const char *restrict str2); |
314 | | /* compare an ASCII/utf-8 string to a r2007+ name */ |
315 | | int bit_eq_TU (const char *str, BITCODE_TU restrict wstr); |
316 | | /* check if the string (ascii or unicode) is empty */ |
317 | | int bit_empty_T (Bit_Chain *restrict dat, BITCODE_T restrict str); |
318 | | BITCODE_T bit_set_T (Bit_Chain *restrict dat, const char *restrict src); |
319 | | |
320 | | BITCODE_TIMEBLL bit_read_TIMEBLL (Bit_Chain *dat); |
321 | | void bit_write_TIMEBLL (Bit_Chain *dat, BITCODE_TIMEBLL date); |
322 | | |
323 | | BITCODE_TIMERLL bit_read_TIMERLL (Bit_Chain *dat); |
324 | | void bit_write_TIMERLL (Bit_Chain *dat, BITCODE_TIMERLL date); |
325 | | |
326 | | int bit_read_CMC (Bit_Chain *dat, Bit_Chain *str_dat, |
327 | | Dwg_Color *restrict color); |
328 | | void bit_write_CMC (Bit_Chain *dat, Bit_Chain *str_dat, |
329 | | Dwg_Color *restrict color); |
330 | | // Convert from truecolor (r2004+) to palette (-r2000) |
331 | | void bit_downconvert_CMC (Bit_Chain *dat, Dwg_Color *restrict color); |
332 | | void bit_upconvert_CMC (Bit_Chain *dat, Dwg_Color *restrict color); |
333 | | |
334 | | void bit_read_ENC (Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, |
335 | | Dwg_Color *restrict color); |
336 | | void bit_write_ENC (Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, |
337 | | Dwg_Color *restrict color); |
338 | | |
339 | | int bit_search_sentinel (Bit_Chain *dat, const unsigned char sentinel[16]); |
340 | | |
341 | | void bit_chain_init (Bit_Chain *dat, const size_t size); |
342 | | void bit_chain_init_dat (Bit_Chain *restrict dat, const size_t size, |
343 | | const Bit_Chain *restrict from_dat); |
344 | | void bit_chain_alloc (Bit_Chain *dat); |
345 | | void bit_chain_alloc_size (Bit_Chain *dat, const size_t size); |
346 | | void bit_chain_free (Bit_Chain *dat); |
347 | | // after bit_chain_init |
348 | | #define bit_chain_set_version(to, from) \ |
349 | 2.85k | (to)->opts = (from)->opts; \ |
350 | 2.85k | (to)->version = (from)->version; \ |
351 | 2.85k | (to)->from_version = (from)->from_version; \ |
352 | 2.85k | (to)->fh = (from)->fh; \ |
353 | 2.85k | (to)->codepage = (from)->codepage |
354 | | |
355 | | void bit_print (Bit_Chain *dat, size_t size); |
356 | | |
357 | | void bit_write_bits1 (Bit_Chain *restrict dat, const char *restrict bits); |
358 | | long bit_write_hexbits (Bit_Chain *restrict dat, const char *restrict bytes); |
359 | | void bit_print_bits (unsigned char *bits, size_t bitsize); |
360 | | void bit_fprint_bits (FILE *fp, unsigned char *bits, size_t bitsize); |
361 | | void bit_explore_chain (Bit_Chain *dat, size_t from, size_t size); |
362 | | |
363 | | BITCODE_BD bit_nan (void); |
364 | | int bit_isnan (BITCODE_BD number); |
365 | | |
366 | | // which would require different text sizes and recalc. |
367 | | bool does_cross_unicode_datversion (Bit_Chain *restrict dat); |
368 | | /* Copy the whole content of tmp_data to dat, and reset tmp_dat */ |
369 | | void bit_copy_chain (Bit_Chain *restrict orig_dat, |
370 | | Bit_Chain *restrict tmp_dat); |
371 | | |
372 | | // for in_dxf and in_json |
373 | | size_t in_hex2bin (unsigned char *restrict dest, char *restrict src, |
374 | | size_t destlen) __nonnull_all; |
375 | | |
376 | | // if there's a high char (> 0x7f) |
377 | | bool bit_TF_contains_high (char *s, size_t len); |
378 | | |
379 | | #endif // BITS_H |