Line data Source code
1 : /*******************************************************************************
2 : * Project: libopencad
3 : * Purpose: OpenSource CAD formats support library
4 : * Author: Alexandr Borzykh, mush3d at gmail.com
5 : * Author: Dmitry Baryshnikov, bishop.dev@gmail.com
6 : * Language: C++
7 : *******************************************************************************
8 : * The MIT License (MIT)
9 : *
10 : * Copyright (c) 2016 Alexandr Borzykh
11 : * Copyright (c) 2016 NextGIS, <info@nextgis.com>
12 : *
13 : * SPDX-License-Identifier: MIT
14 : *******************************************************************************/
15 : #include "io.h"
16 :
17 : #include <iostream>
18 : #include <cstdint>
19 : #include <cstring>
20 :
21 : const size_t DWGConstants::SentinelLength = 16;
22 : const char * DWGConstants::HeaderVariablesStart
23 : = "\xCF\x7B\x1F\x23\xFD\xDE\x38\xA9\x5F\x7C\x68\xB8\x4E\x6D\x33\x5F";
24 : const char * DWGConstants::HeaderVariablesEnd
25 : = "\x30\x84\xE0\xDC\x02\x21\xC7\x56\xA0\x83\x97\x47\xB1\x92\xCC\xA0";
26 :
27 : const char * DWGConstants::DSClassesStart
28 : = "\x8D\xA1\xC4\xB8\xC4\xA9\xF8\xC5\xC0\xDC\xF4\x5F\xE7\xCF\xB6\x8A";
29 : const char * DWGConstants::DSClassesEnd
30 : = "\x72\x5E\x3B\x47\x3B\x56\x07\x3A\x3F\x23\x0B\xA0\x18\x30\x49\x75";
31 :
32 : const int DWGCRC8Table[256] = {
33 : 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1,
34 : 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40,
35 : 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1,
36 : 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
37 : 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1,
38 : 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40,
39 : 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1,
40 : 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
41 : 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0,
42 : 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740,
43 : 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0,
44 : 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
45 : 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1,
46 : 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140,
47 : 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0,
48 : 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
49 : 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0,
50 : 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341,
51 : 0x4100, 0x81C1, 0x8081, 0x4040
52 : };
53 :
54 36206 : unsigned short CalculateCRC8( unsigned short initialVal, const char *ptr, int num )
55 : {
56 : unsigned char al;
57 36206 : while( num-- > 0 )
58 : {
59 35977 : al = static_cast<unsigned char>( ( *ptr ) ^
60 : ( static_cast<char>( initialVal & 0xFF ) ) );
61 35977 : initialVal = ( initialVal >> 8 ) & 0xFF;
62 35977 : initialVal = static_cast<unsigned short>( initialVal ^ DWGCRC8Table[al & 0xFF] );
63 35977 : ptr++;
64 : }
65 :
66 229 : return initialVal;
67 : }
68 :
69 : //------------------------------------------------------------------------------
70 : // CADBuffer
71 : //------------------------------------------------------------------------------
72 :
73 450 : CADBuffer::CADBuffer(size_t size) : m_nBitOffsetFromStart(0)
74 : {
75 450 : m_pBuffer = new char[size];
76 : // zero memory
77 450 : memset(m_pBuffer, 0, size);
78 450 : m_nSize = size;
79 450 : }
80 :
81 900 : CADBuffer::~CADBuffer()
82 : {
83 450 : delete [] m_pBuffer;
84 450 : }
85 :
86 24 : void CADBuffer::WriteRAW(const void *data, size_t size)
87 : {
88 24 : memcpy(m_pBuffer, data, size);
89 24 : m_nBitOffsetFromStart += size * 8;
90 24 : }
91 :
92 4470 : unsigned char CADBuffer::Read2B()
93 : {
94 4470 : unsigned char result = 0;
95 4470 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
96 4470 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
97 :
98 4470 : if(nByteOffset + 2 > m_nSize)
99 : {
100 0 : m_bEOB = true;
101 0 : return 0;
102 : }
103 :
104 : unsigned char a2BBytes[2];
105 4470 : memcpy( a2BBytes, m_pBuffer + nByteOffset, 2 );
106 :
107 4470 : switch( nBitOffsetInByte )
108 : {
109 163 : case 7:
110 163 : result = ( a2BBytes[0] & binary( 00000001 ) ) << 1;
111 163 : result |= ( a2BBytes[1] & binary( 10000000 ) ) >> 7;
112 163 : break;
113 4307 : default:
114 4307 : result = ( a2BBytes[0] >> ( 6 - nBitOffsetInByte ) );
115 4307 : break;
116 : }
117 :
118 4470 : result &= binary( 00000011 );
119 4470 : m_nBitOffsetFromStart += 2;
120 :
121 4470 : return result;
122 : }
123 :
124 0 : unsigned char CADBuffer::Read3B()
125 : {
126 0 : unsigned char result = 0;
127 0 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
128 0 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
129 :
130 0 : if(nByteOffset + 2 > m_nSize)
131 : {
132 0 : m_bEOB = true;
133 0 : return 0;
134 : }
135 :
136 : unsigned char a3BBytes[2];
137 0 : memcpy( a3BBytes, m_pBuffer + nByteOffset, 2 );
138 :
139 0 : switch( nBitOffsetInByte )
140 : {
141 0 : case 6:
142 0 : result = ( a3BBytes[0] & binary( 00000011 ) ) << 1;
143 0 : result |= ( a3BBytes[1] & binary( 10000000 ) ) >> 7;
144 0 : break;
145 :
146 0 : case 7:
147 0 : result = ( a3BBytes[0] & binary( 00000001 ) ) << 2;
148 0 : result |= ( a3BBytes[1] & binary( 11000000 ) ) >> 6;
149 0 : break;
150 :
151 0 : default:
152 0 : result = ( a3BBytes[0] >> ( 5 - nBitOffsetInByte ) );
153 0 : break;
154 : }
155 :
156 0 : result &= binary( 00000111 );
157 0 : m_nBitOffsetFromStart += 3;
158 :
159 0 : return result;
160 : }
161 :
162 4016 : unsigned char CADBuffer::Read4B()
163 : {
164 4016 : unsigned char result = 0;
165 4016 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
166 4016 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
167 :
168 4016 : if(nByteOffset + 2 > m_nSize)
169 : {
170 0 : m_bEOB = true;
171 0 : return 0;
172 : }
173 :
174 : unsigned char a4BBytes[2];
175 4016 : memcpy( a4BBytes, m_pBuffer + nByteOffset, 2 );
176 :
177 4016 : switch( nBitOffsetInByte )
178 : {
179 64 : case 5:
180 64 : result = ( a4BBytes[0] & binary( 00000111 ) ) << 1;
181 64 : result |= ( a4BBytes[1] & binary( 10000000 ) ) >> 7;
182 64 : break;
183 1040 : case 6:
184 1040 : result = ( a4BBytes[0] & binary( 00000011 ) ) << 2;
185 1040 : result |= ( a4BBytes[1] & binary( 11000000 ) ) >> 6;
186 1040 : break;
187 :
188 20 : case 7:
189 20 : result = ( a4BBytes[0] & binary( 00000001 ) ) << 3;
190 20 : result |= ( a4BBytes[1] & binary( 11100000 ) ) >> 5;
191 20 : break;
192 :
193 2892 : default:
194 2892 : result = ( a4BBytes[0] >> ( 4 - nBitOffsetInByte ) );
195 2892 : break;
196 : }
197 :
198 4016 : result &= binary( 00001111 );
199 4016 : m_nBitOffsetFromStart += 4;
200 :
201 4016 : return result;
202 : }
203 :
204 :
205 790 : double CADBuffer::ReadBITDOUBLE()
206 : {
207 790 : unsigned char BITCODE = Read2B();
208 :
209 790 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
210 790 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
211 :
212 790 : if(nByteOffset + 9 > m_nSize)
213 : {
214 0 : m_bEOB = true;
215 0 : return 0.0;
216 : }
217 :
218 : unsigned char aDoubleBytes[9]; // maximum bytes a single double can take.
219 790 : memcpy( aDoubleBytes, m_pBuffer + nByteOffset, 9 );
220 :
221 790 : switch( BITCODE )
222 : {
223 100 : case BITDOUBLE_NORMAL:
224 : {
225 100 : aDoubleBytes[0] <<= nBitOffsetInByte;
226 100 : aDoubleBytes[0] |= ( aDoubleBytes[1] >> ( 8 - nBitOffsetInByte ) );
227 100 : aDoubleBytes[1] <<= nBitOffsetInByte;
228 100 : aDoubleBytes[1] |= ( aDoubleBytes[2] >> ( 8 - nBitOffsetInByte ) );
229 100 : aDoubleBytes[2] <<= nBitOffsetInByte;
230 100 : aDoubleBytes[2] |= ( aDoubleBytes[3] >> ( 8 - nBitOffsetInByte ) );
231 100 : aDoubleBytes[3] <<= nBitOffsetInByte;
232 100 : aDoubleBytes[3] |= ( aDoubleBytes[4] >> ( 8 - nBitOffsetInByte ) );
233 100 : aDoubleBytes[4] <<= nBitOffsetInByte;
234 100 : aDoubleBytes[4] |= ( aDoubleBytes[5] >> ( 8 - nBitOffsetInByte ) );
235 100 : aDoubleBytes[5] <<= nBitOffsetInByte;
236 100 : aDoubleBytes[5] |= ( aDoubleBytes[6] >> ( 8 - nBitOffsetInByte ) );
237 100 : aDoubleBytes[6] <<= nBitOffsetInByte;
238 100 : aDoubleBytes[6] |= ( aDoubleBytes[7] >> ( 8 - nBitOffsetInByte ) );
239 100 : aDoubleBytes[7] <<= nBitOffsetInByte;
240 100 : aDoubleBytes[7] |= ( aDoubleBytes[8] >> ( 8 - nBitOffsetInByte ) );
241 :
242 100 : m_nBitOffsetFromStart += 64;
243 :
244 : double result;
245 100 : memcpy(&result, aDoubleBytes, sizeof(result));
246 100 : FromLSB(result);
247 100 : return result;
248 : }
249 :
250 87 : case BITDOUBLE_ONE_VALUE:
251 : {
252 87 : m_nBitOffsetFromStart += 0;
253 :
254 87 : return 1.0f;
255 : }
256 :
257 603 : case BITDOUBLE_ZERO_VALUE:
258 : {
259 603 : m_nBitOffsetFromStart += 0;
260 :
261 603 : return 0.0f;
262 : }
263 :
264 0 : case BITDOUBLE_NOT_USED:
265 : {
266 0 : m_nBitOffsetFromStart += 0;
267 :
268 0 : return 0.0f;
269 : }
270 : }
271 :
272 0 : return 0.0f;
273 : }
274 :
275 272 : void CADBuffer::SkipBITDOUBLE()
276 : {
277 272 : unsigned char BITCODE = Read2B();
278 272 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
279 272 : if(nByteOffset + 9 > m_nSize)
280 : {
281 0 : m_bEOB = true;
282 0 : return;
283 : }
284 :
285 272 : switch( BITCODE )
286 : {
287 83 : case BITDOUBLE_NORMAL:
288 83 : m_nBitOffsetFromStart += 64;
289 83 : break;
290 61 : case BITDOUBLE_ONE_VALUE:
291 61 : m_nBitOffsetFromStart += 0;
292 61 : break;
293 128 : case BITDOUBLE_ZERO_VALUE:
294 : case BITDOUBLE_NOT_USED:
295 128 : break;
296 : }
297 : }
298 :
299 253 : short CADBuffer::ReadRAWSHORT()
300 : {
301 253 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
302 253 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
303 :
304 253 : if(nByteOffset + 3 > m_nSize)
305 : {
306 0 : m_bEOB = true;
307 0 : return 0;
308 : }
309 : unsigned char aShortBytes[3];
310 253 : memcpy( aShortBytes, m_pBuffer + nByteOffset, 3 );
311 :
312 253 : switch( nBitOffsetInByte )
313 : {
314 229 : case 0:
315 229 : break;
316 :
317 24 : default:
318 24 : aShortBytes[0] <<= nBitOffsetInByte;
319 24 : aShortBytes[0] |= ( aShortBytes[1] >> ( 8 - nBitOffsetInByte ) );
320 24 : aShortBytes[1] <<= nBitOffsetInByte;
321 24 : aShortBytes[1] |= ( aShortBytes[2] >> ( 8 - nBitOffsetInByte ) );
322 24 : break;
323 : }
324 :
325 : int16_t result;
326 253 : memcpy(&result, aShortBytes, sizeof(result));
327 253 : FromLSB(result);
328 :
329 253 : m_nBitOffsetFromStart += 16;
330 :
331 253 : return result;
332 : }
333 :
334 93 : double CADBuffer::ReadRAWDOUBLE()
335 : {
336 93 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
337 93 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
338 :
339 93 : if(nByteOffset + 9 > m_nSize)
340 : {
341 0 : m_bEOB = true;
342 0 : return 0.0;
343 : }
344 :
345 : unsigned char aDoubleBytes[9];
346 93 : memcpy( aDoubleBytes, m_pBuffer + nByteOffset, 9 );
347 :
348 93 : switch( nBitOffsetInByte )
349 : {
350 37 : case 0:
351 37 : break;
352 :
353 56 : default:
354 56 : aDoubleBytes[0] <<= nBitOffsetInByte;
355 56 : aDoubleBytes[0] |= ( aDoubleBytes[1] >> ( 8 - nBitOffsetInByte ) );
356 56 : aDoubleBytes[1] <<= nBitOffsetInByte;
357 56 : aDoubleBytes[1] |= ( aDoubleBytes[2] >> ( 8 - nBitOffsetInByte ) );
358 56 : aDoubleBytes[2] <<= nBitOffsetInByte;
359 56 : aDoubleBytes[2] |= ( aDoubleBytes[3] >> ( 8 - nBitOffsetInByte ) );
360 56 : aDoubleBytes[3] <<= nBitOffsetInByte;
361 56 : aDoubleBytes[3] |= ( aDoubleBytes[4] >> ( 8 - nBitOffsetInByte ) );
362 56 : aDoubleBytes[4] <<= nBitOffsetInByte;
363 56 : aDoubleBytes[4] |= ( aDoubleBytes[5] >> ( 8 - nBitOffsetInByte ) );
364 56 : aDoubleBytes[5] <<= nBitOffsetInByte;
365 56 : aDoubleBytes[5] |= ( aDoubleBytes[6] >> ( 8 - nBitOffsetInByte ) );
366 56 : aDoubleBytes[6] <<= nBitOffsetInByte;
367 56 : aDoubleBytes[6] |= ( aDoubleBytes[7] >> ( 8 - nBitOffsetInByte ) );
368 56 : aDoubleBytes[7] <<= nBitOffsetInByte;
369 56 : aDoubleBytes[7] |= ( aDoubleBytes[8] >> ( 8 - nBitOffsetInByte ) );
370 56 : break;
371 : }
372 :
373 : double result;
374 93 : memcpy(&result, aDoubleBytes, sizeof(result));
375 93 : FromLSB(result);
376 :
377 93 : m_nBitOffsetFromStart += 64;
378 :
379 93 : return result;
380 : }
381 :
382 205 : int CADBuffer::ReadRAWLONG()
383 : {
384 205 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
385 205 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
386 :
387 205 : if(nByteOffset + 5 > m_nSize)
388 : {
389 0 : m_bEOB = true;
390 0 : return 0;
391 : }
392 :
393 : unsigned char aLongBytes[5];
394 205 : memcpy( aLongBytes, m_pBuffer + nByteOffset, 5 );
395 :
396 205 : switch( nBitOffsetInByte )
397 : {
398 0 : case 0:
399 0 : break;
400 :
401 205 : default:
402 205 : aLongBytes[0] <<= nBitOffsetInByte;
403 205 : aLongBytes[0] |= ( aLongBytes[1] >> ( 8 - nBitOffsetInByte ) );
404 205 : aLongBytes[1] <<= nBitOffsetInByte;
405 205 : aLongBytes[1] |= ( aLongBytes[2] >> ( 8 - nBitOffsetInByte ) );
406 205 : aLongBytes[2] <<= nBitOffsetInByte;
407 205 : aLongBytes[2] |= ( aLongBytes[3] >> ( 8 - nBitOffsetInByte ) );
408 205 : aLongBytes[3] <<= nBitOffsetInByte;
409 205 : aLongBytes[3] |= ( aLongBytes[4] >> ( 8 - nBitOffsetInByte ) );
410 205 : break;
411 : }
412 :
413 : int32_t result;
414 205 : memcpy(&result, aLongBytes, sizeof(result));
415 205 : FromLSB(result);
416 :
417 205 : m_nBitOffsetFromStart += 32;
418 :
419 205 : return result;
420 : }
421 :
422 298 : bool CADBuffer::ReadBIT()
423 : {
424 298 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
425 298 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
426 :
427 298 : if(nByteOffset >= m_nSize)
428 : {
429 0 : m_bEOB = true;
430 0 : return false;
431 : }
432 :
433 298 : unsigned char resultVal = ( m_pBuffer[nByteOffset] >> ( 7 - nBitOffsetInByte ) ) & binary( 00000001 );
434 298 : ++m_nBitOffsetFromStart;
435 :
436 298 : return resultVal == 0 ? false : true;
437 : }
438 :
439 2400 : short CADBuffer::ReadBITSHORT()
440 : {
441 2400 : unsigned char BITCODE = Read2B();
442 :
443 2400 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
444 2400 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
445 :
446 2400 : if(nByteOffset + 4 > m_nSize)
447 : {
448 0 : m_bEOB = true;
449 0 : return 0;
450 : }
451 :
452 : unsigned char aShortBytes[4]; // maximum bytes a single short can take.
453 2400 : memcpy( aShortBytes, m_pBuffer + nByteOffset, 4 );
454 :
455 2400 : switch( BITCODE )
456 : {
457 349 : case BITSHORT_NORMAL:
458 : {
459 349 : aShortBytes[0] = ( aShortBytes[0] << nBitOffsetInByte );
460 349 : aShortBytes[0] |= ( aShortBytes[1] >> ( 8 - nBitOffsetInByte ) );
461 349 : aShortBytes[1] = ( aShortBytes[1] << nBitOffsetInByte );
462 349 : aShortBytes[1] |= ( aShortBytes[2] >> ( 8 - nBitOffsetInByte ) );
463 :
464 349 : m_nBitOffsetFromStart += 16;
465 :
466 : int16_t result;
467 349 : memcpy(&result, aShortBytes, sizeof(result));
468 349 : FromLSB(result);
469 :
470 349 : return result;
471 : }
472 :
473 1609 : case BITSHORT_UNSIGNED_CHAR:
474 : {
475 1609 : aShortBytes[0] = ( aShortBytes[0] << nBitOffsetInByte );
476 1609 : aShortBytes[0] |= ( aShortBytes[1] >> ( 8 - nBitOffsetInByte ) );
477 :
478 1609 : m_nBitOffsetFromStart += 8;
479 :
480 1609 : return static_cast<unsigned char>(aShortBytes[0]);
481 : }
482 :
483 399 : case BITSHORT_ZERO_VALUE:
484 : {
485 399 : m_nBitOffsetFromStart += 0;
486 399 : return 0;
487 : }
488 :
489 43 : case BITSHORT_256:
490 : {
491 43 : m_nBitOffsetFromStart += 0;
492 43 : return 256;
493 : }
494 : }
495 :
496 0 : return -1;
497 : }
498 :
499 26233 : unsigned char CADBuffer::ReadCHAR()
500 : {
501 26233 : unsigned char result = 0;
502 26233 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
503 26233 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
504 :
505 26233 : if(nByteOffset + 2 > m_nSize)
506 : {
507 0 : m_bEOB = true;
508 0 : return result;
509 : }
510 :
511 : unsigned char aCharBytes[2]; // maximum bytes a single char can take.
512 26233 : memcpy( aCharBytes, m_pBuffer + nByteOffset, 2 );
513 :
514 26233 : result = ( aCharBytes[0] << nBitOffsetInByte );
515 26233 : result |= ( aCharBytes[1] >> ( 8 - nBitOffsetInByte ) );
516 :
517 26233 : m_nBitOffsetFromStart += 8;
518 :
519 26233 : return result;
520 : }
521 :
522 1220 : std::string CADBuffer::ReadTV()
523 : {
524 1220 : short stringLength = ReadBITSHORT();
525 :
526 1220 : std::string result;
527 :
528 15532 : for( short i = 0; i < stringLength; ++i )
529 : {
530 14312 : result += static_cast<char>(ReadCHAR());
531 : }
532 :
533 1220 : return result;
534 : }
535 :
536 1793 : long CADBuffer::ReadUMCHAR()
537 : {
538 1793 : long result = 0;
539 1793 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
540 : // TODO: bit offset is calculated, but function has nothing to do with it.
541 : /*size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;*/
542 :
543 1793 : if(nByteOffset + 8 > m_nSize)
544 : {
545 0 : m_bEOB = true;
546 0 : return 0;
547 : }
548 : unsigned char aMCharBytes[8]; // 8 bytes is maximum.
549 : //memcpy( aMCharBytes, m_pBuffer + nByteOffset, 8 );
550 :
551 1793 : unsigned char nMCharBytesCount = 0;
552 1799 : for( unsigned char i = 0; i < 8; ++i )
553 : {
554 1799 : aMCharBytes[i] = ReadCHAR();
555 1799 : ++nMCharBytesCount;
556 1799 : if ( !( aMCharBytes[i] & binary( 10000000 ) ) )
557 : {
558 1793 : break;
559 : }
560 6 : aMCharBytes[i] &= binary( 01111111 );
561 : }
562 :
563 1793 : int nOffset = 0;
564 3592 : for(unsigned char i = 0; i < nMCharBytesCount; ++i)
565 : {
566 1799 : unsigned long nVal = aMCharBytes[i];
567 1799 : result += nVal << nOffset;
568 1799 : nOffset += 7;
569 : }
570 1793 : return result;
571 : }
572 :
573 1793 : long CADBuffer::ReadMCHAR()
574 : {
575 1793 : long result = 0;
576 1793 : bool negative = false;
577 1793 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
578 :
579 : // TODO: bit offset is calculated, but function has nothing to do with it.
580 : /*size_t nBitOffsetInByte = nBitOffsetFromStart % 8;*/
581 :
582 1793 : if(nByteOffset + 8 > m_nSize)
583 : {
584 0 : m_bEOB = true;
585 0 : return 0;
586 : }
587 : unsigned char aMCharBytes[8]; // 8 bytes is maximum.
588 :
589 1793 : unsigned char nMCharBytesCount = 0;
590 3841 : for( unsigned char i = 0; i < 8; ++i )
591 : {
592 3841 : aMCharBytes[i] = ReadCHAR();
593 3841 : ++nMCharBytesCount;
594 3841 : if ( !( aMCharBytes[i] & binary( 10000000 ) ) )
595 : {
596 1793 : break;
597 : }
598 2048 : aMCharBytes[i] &= binary( 01111111 );
599 : }
600 :
601 1793 : if ( ( aMCharBytes[nMCharBytesCount - 1] & binary( 01000000 ) ) == binary( 01000000 ) )
602 : {
603 723 : aMCharBytes[nMCharBytesCount - 1] &= binary( 10111111 );
604 723 : negative = true;
605 : }
606 :
607 1793 : int nOffset = 0;
608 5634 : for(unsigned char i = 0; i < nMCharBytesCount; ++i)
609 : {
610 3841 : unsigned long nVal = aMCharBytes[i];
611 3841 : result += nVal << nOffset;
612 3841 : nOffset += 7;
613 : }
614 :
615 1793 : if( negative )
616 : {
617 723 : result *= -1;
618 : }
619 :
620 1793 : return result;
621 : }
622 :
623 426 : unsigned int CADBuffer::ReadMSHORT()
624 : {
625 : unsigned char aMShortBytes[8]; // 8 bytes is maximum.
626 :
627 : // TODO: this function does not support MSHORTS longer than 4 bytes. ODA says
628 : // it's impossible, but not sure.
629 426 : size_t MShortBytesCount = 2;
630 426 : aMShortBytes[0] = ReadCHAR();
631 426 : aMShortBytes[1] = ReadCHAR();
632 426 : if ( aMShortBytes[1] & binary( 10000000 ) )
633 : {
634 0 : aMShortBytes[2] = ReadCHAR();
635 0 : aMShortBytes[3] = ReadCHAR();
636 0 : MShortBytesCount = 4;
637 : }
638 :
639 426 : SwapEndianness( aMShortBytes, MShortBytesCount );
640 :
641 426 : if( MShortBytesCount == 2 )
642 : {
643 426 : aMShortBytes[0] &= binary( 01111111 ); // drop high order flag bit.
644 : }
645 : else
646 : {
647 0 : aMShortBytes[0] &= binary( 01111111 );
648 0 : aMShortBytes[2] &= binary( 01111111 );
649 :
650 0 : aMShortBytes[2] |= ( aMShortBytes[1] << 7 );
651 0 : aMShortBytes[1] = ( aMShortBytes[1] >> 1 );
652 0 : aMShortBytes[1] |= ( aMShortBytes[0] << 7 );
653 0 : aMShortBytes[0] = ( aMShortBytes[0] >> 1 );
654 : }
655 :
656 : unsigned int result;
657 426 : if( MShortBytesCount == 2 )
658 : {
659 426 : result = (aMShortBytes[0] << 8) | aMShortBytes[1];
660 : }
661 : else
662 : {
663 0 : result = (static_cast<unsigned>(aMShortBytes[0]) << 24) |
664 0 : (aMShortBytes[1] << 16) | (aMShortBytes[2] << 8) | aMShortBytes[3];
665 : }
666 :
667 426 : return result;
668 : }
669 :
670 :
671 :
672 2 : double CADBuffer::ReadBITDOUBLEWD(double defaultvalue )
673 : {
674 : unsigned char aDefaultValueBytes[8];
675 2 : memcpy( aDefaultValueBytes, & defaultvalue, 8 );
676 :
677 2 : unsigned char BITCODE = Read2B();
678 :
679 2 : switch( BITCODE )
680 : {
681 0 : case BITDOUBLEWD_DEFAULT_VALUE:
682 : {
683 0 : return defaultvalue;
684 : }
685 :
686 0 : case BITDOUBLEWD_4BYTES_PATCHED:
687 : {
688 0 : aDefaultValueBytes[0] = ReadCHAR();
689 0 : aDefaultValueBytes[1] = ReadCHAR();
690 0 : aDefaultValueBytes[2] = ReadCHAR();
691 0 : aDefaultValueBytes[3] = ReadCHAR();
692 :
693 : double result;
694 0 : memcpy(&result, aDefaultValueBytes, sizeof(result));
695 0 : FromLSB(result);
696 0 : return result;
697 : }
698 :
699 0 : case BITDOUBLEWD_6BYTES_PATCHED:
700 : {
701 0 : aDefaultValueBytes[4] = ReadCHAR();
702 0 : aDefaultValueBytes[5] = ReadCHAR();
703 0 : aDefaultValueBytes[0] = ReadCHAR();
704 0 : aDefaultValueBytes[1] = ReadCHAR();
705 0 : aDefaultValueBytes[2] = ReadCHAR();
706 0 : aDefaultValueBytes[3] = ReadCHAR();
707 :
708 : double result;
709 0 : memcpy(&result, aDefaultValueBytes, sizeof(result));
710 0 : FromLSB(result);
711 0 : return result;
712 : }
713 :
714 2 : case BITDOUBLEWD_FULL_RD:
715 : {
716 2 : aDefaultValueBytes[0] = ReadCHAR();
717 2 : aDefaultValueBytes[1] = ReadCHAR();
718 2 : aDefaultValueBytes[2] = ReadCHAR();
719 2 : aDefaultValueBytes[3] = ReadCHAR();
720 2 : aDefaultValueBytes[4] = ReadCHAR();
721 2 : aDefaultValueBytes[5] = ReadCHAR();
722 2 : aDefaultValueBytes[6] = ReadCHAR();
723 2 : aDefaultValueBytes[7] = ReadCHAR();
724 :
725 : double result;
726 2 : memcpy(&result, aDefaultValueBytes, sizeof(result));
727 2 : FromLSB(result);
728 2 : return result;
729 : }
730 : }
731 :
732 0 : return 0.0f;
733 : }
734 :
735 1936 : CADHandle CADBuffer::ReadHANDLE()
736 : {
737 1936 : CADHandle result( Read4B() );
738 1936 : unsigned char counter = Read4B();
739 4286 : for( unsigned char i = 0; i < counter; ++i )
740 : {
741 2350 : result.addOffset( ReadCHAR() );
742 : }
743 :
744 1936 : return result;
745 : }
746 :
747 72 : void CADBuffer::SkipHANDLE()
748 : {
749 72 : Read4B();
750 72 : unsigned char counter = Read4B();
751 72 : m_nBitOffsetFromStart += counter * 8;
752 72 : }
753 :
754 0 : CADHandle CADBuffer::ReadHANDLE8BLENGTH()
755 : {
756 0 : CADHandle result;
757 :
758 0 : unsigned char counter = ReadCHAR();
759 :
760 0 : for( unsigned char i = 0; i < counter; ++i )
761 : {
762 0 : result.addOffset( ReadCHAR() );
763 : }
764 :
765 0 : return result;
766 : }
767 :
768 429 : int CADBuffer::ReadBITLONG()
769 : {
770 429 : unsigned char BITCODE = Read2B();
771 :
772 429 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
773 429 : size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
774 :
775 429 : if(nByteOffset + 5 > m_nSize)
776 : {
777 0 : m_bEOB = true;
778 0 : return 0;
779 : }
780 : unsigned char aLongBytes[5]; // maximum bytes a single short can take.
781 429 : memcpy( aLongBytes, m_pBuffer + nByteOffset, 5 );
782 :
783 429 : switch( BITCODE )
784 : {
785 48 : case BITLONG_NORMAL:
786 : {
787 48 : aLongBytes[0] <<= nBitOffsetInByte;
788 48 : aLongBytes[0] |= ( aLongBytes[1] >> ( 8 - nBitOffsetInByte ) );
789 48 : aLongBytes[1] <<= nBitOffsetInByte;
790 48 : aLongBytes[1] |= ( aLongBytes[2] >> ( 8 - nBitOffsetInByte ) );
791 48 : aLongBytes[2] <<= nBitOffsetInByte;
792 48 : aLongBytes[2] |= ( aLongBytes[3] >> ( 8 - nBitOffsetInByte ) );
793 48 : aLongBytes[3] <<= nBitOffsetInByte;
794 48 : aLongBytes[3] |= ( aLongBytes[4] >> ( 8 - nBitOffsetInByte ) );
795 :
796 48 : m_nBitOffsetFromStart += 32;
797 :
798 : int32_t result;
799 48 : memcpy(&result, aLongBytes, sizeof(result));
800 48 : FromLSB(result);
801 48 : return result;
802 : }
803 :
804 264 : case BITLONG_UNSIGNED_CHAR:
805 : {
806 264 : aLongBytes[0] <<= nBitOffsetInByte;
807 264 : aLongBytes[0] |= ( aLongBytes[1] >> ( 8 - nBitOffsetInByte ) );
808 :
809 264 : m_nBitOffsetFromStart += 8;
810 :
811 264 : return aLongBytes[0];
812 : }
813 :
814 117 : case BITLONG_ZERO_VALUE:
815 : {
816 117 : m_nBitOffsetFromStart += 0;
817 117 : return 0;
818 : }
819 :
820 0 : case BITLONG_NOT_USED:
821 : {
822 : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
823 : std::cerr <<
824 0 : "THAT SHOULD NEVER HAPPENED! BUG. (in file, or reader, or both.) ReadBITLONG(), case BITLONG_NOT_USED\n";
825 : #endif
826 0 : m_nBitOffsetFromStart += 0;
827 0 : return 0;
828 : }
829 : }
830 :
831 0 : return -1;
832 : }
833 :
834 56 : void CADBuffer::SkipTV()
835 : {
836 56 : short stringLength = ReadBITSHORT();
837 56 : if( stringLength < 0 )
838 : {
839 : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
840 0 : std::cerr << "Negative string length" << std::endl;
841 : #endif
842 0 : return;
843 : }
844 56 : m_nBitOffsetFromStart += size_t( stringLength * 8 );
845 : }
846 :
847 24 : void CADBuffer::SkipBITLONG()
848 : {
849 24 : unsigned char BITCODE = Read2B();
850 24 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
851 24 : if(nByteOffset + 5 > m_nSize)
852 : {
853 0 : m_bEOB = true;
854 0 : return;
855 : }
856 24 : switch( BITCODE )
857 : {
858 8 : case BITLONG_NORMAL:
859 8 : m_nBitOffsetFromStart += 32;
860 8 : break;
861 :
862 0 : case BITLONG_UNSIGNED_CHAR:
863 0 : m_nBitOffsetFromStart += 8;
864 0 : break;
865 :
866 16 : case BITLONG_ZERO_VALUE:
867 : case BITLONG_NOT_USED:
868 16 : break;
869 : }
870 : }
871 :
872 448 : void CADBuffer::SkipBITSHORT()
873 : {
874 448 : unsigned char BITCODE = Read2B();
875 448 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
876 448 : if(nByteOffset + 4 > m_nSize)
877 : {
878 0 : m_bEOB = true;
879 0 : return;
880 : }
881 448 : switch( BITCODE )
882 : {
883 56 : case BITSHORT_NORMAL:
884 56 : m_nBitOffsetFromStart += 16;
885 56 : break;
886 :
887 214 : case BITSHORT_UNSIGNED_CHAR:
888 214 : m_nBitOffsetFromStart += 8;
889 214 : break;
890 :
891 178 : case BITSHORT_ZERO_VALUE:
892 : case BITSHORT_256:
893 178 : break;
894 : }
895 : }
896 :
897 0 : void CADBuffer::SkipBIT()
898 : {
899 0 : size_t nByteOffset = m_nBitOffsetFromStart / 8;
900 0 : if(nByteOffset >= m_nSize)
901 : {
902 0 : m_bEOB = true;
903 0 : return;
904 : }
905 0 : ++m_nBitOffsetFromStart;
906 : }
907 :
908 21 : CADVector CADBuffer::ReadVector()
909 : {
910 : double x, y, z;
911 21 : x = ReadBITDOUBLE();
912 21 : y = ReadBITDOUBLE();
913 21 : z = ReadBITDOUBLE();
914 :
915 21 : return CADVector( x, y, z );
916 : }
917 :
918 9 : CADVector CADBuffer::ReadRAWVector()
919 : {
920 : double x, y;
921 9 : x = ReadRAWDOUBLE();
922 9 : y = ReadRAWDOUBLE();
923 :
924 9 : return CADVector( x, y );
925 : }
926 :
927 508 : void CADBuffer::Seek(size_t offset, CADBuffer::SeekPosition position)
928 : {
929 508 : switch (position) {
930 460 : case BEG:
931 460 : m_nBitOffsetFromStart = offset;
932 460 : break;
933 48 : case CURRENT:
934 48 : m_nBitOffsetFromStart += offset;
935 48 : break;
936 0 : case END:
937 0 : m_nBitOffsetFromStart = m_nSize - offset;
938 0 : break;
939 0 : default:
940 0 : break;
941 : }
942 508 : }
|