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