File: | dwgbuffer.cpp |
Warning: | line 520, column 29 The result of left shift is undefined because the right operand '45' is not smaller than 32, the capacity of 'int' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /****************************************************************************** | |||
2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** | |||
3 | ** ** | |||
4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** | |||
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 2 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 | #include "dwgbuffer.h" | |||
15 | #include "../libdwgr.h" | |||
16 | #include "drw_textcodec.h" | |||
17 | #include "drw_dbg.h" | |||
18 | //#include <bitset> | |||
19 | /*#include <fstream> | |||
20 | #include <algorithm> | |||
21 | #include <sstream> | |||
22 | #include "dwgreader.h"*/ | |||
23 | //#include "dxfwriter.h" | |||
24 | ||||
25 | ||||
26 | //#define FIRSTHANDLE 48 | |||
27 | ||||
28 | /*enum sections { | |||
29 | secUnknown, | |||
30 | secHeader, | |||
31 | secTables, | |||
32 | secBlocks, | |||
33 | secEntities, | |||
34 | secObjects | |||
35 | };*/ | |||
36 | ||||
37 | static unsigned int crctable[256]= { | |||
38 | 0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241, | |||
39 | 0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440, | |||
40 | 0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40, | |||
41 | 0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841, | |||
42 | 0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40, | |||
43 | 0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41, | |||
44 | 0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641, | |||
45 | 0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040, | |||
46 | 0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240, | |||
47 | 0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441, | |||
48 | 0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41, | |||
49 | 0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840, | |||
50 | 0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41, | |||
51 | 0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40, | |||
52 | 0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640, | |||
53 | 0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041, | |||
54 | 0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240, | |||
55 | 0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441, | |||
56 | 0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41, | |||
57 | 0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840, | |||
58 | 0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41, | |||
59 | 0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40, | |||
60 | 0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640, | |||
61 | 0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041, | |||
62 | 0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241, | |||
63 | 0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440, | |||
64 | 0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40, | |||
65 | 0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841, | |||
66 | 0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40, | |||
67 | 0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41, | |||
68 | 0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641, | |||
69 | 0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040 }; | |||
70 | ||||
71 | static unsigned int crc32Table[256] ={ | |||
72 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, | |||
73 | 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, | |||
74 | 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, | |||
75 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, | |||
76 | 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, | |||
77 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, | |||
78 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, | |||
79 | 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, | |||
80 | 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, | |||
81 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, | |||
82 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, | |||
83 | 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, | |||
84 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, | |||
85 | 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, | |||
86 | 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, | |||
87 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, | |||
88 | 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, | |||
89 | 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, | |||
90 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, | |||
91 | 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, | |||
92 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, | |||
93 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, | |||
94 | 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, | |||
95 | 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, | |||
96 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, | |||
97 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, | |||
98 | 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, | |||
99 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, | |||
100 | 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, | |||
101 | 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, | |||
102 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, | |||
103 | 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; | |||
104 | ||||
105 | union typeCast { | |||
106 | char buf[8]; | |||
107 | duint16 i16; | |||
108 | duint32 i32; | |||
109 | duint64 i64; | |||
110 | ddouble64 d64; | |||
111 | }; | |||
112 | ||||
113 | bool dwgFileStream::setPos(duint64 p){ | |||
114 | if (p >= sz) | |||
115 | return false; | |||
116 | ||||
117 | stream->seekg(p); | |||
118 | return stream->good(); | |||
119 | } | |||
120 | ||||
121 | bool dwgFileStream::read(duint8* s, duint64 n){ | |||
122 | stream->read (reinterpret_cast<char*>(s),n); | |||
123 | return stream->good(); | |||
124 | } | |||
125 | ||||
126 | bool dwgCharStream::setPos(duint64 p){ | |||
127 | if (p > size()) { | |||
128 | isOk = false; | |||
129 | return false; | |||
130 | } | |||
131 | ||||
132 | pos = p; | |||
133 | return true; | |||
134 | } | |||
135 | ||||
136 | bool dwgCharStream::read(duint8* s, duint64 n){ | |||
137 | if ( n > (sz - pos) ) { | |||
138 | isOk = false; | |||
139 | return false; | |||
140 | } | |||
141 | for (duint64 i=0; i<n; i++){ | |||
142 | s[i]= stream[pos++]; | |||
143 | } | |||
144 | return true; | |||
145 | } | |||
146 | ||||
147 | dwgBuffer::dwgBuffer(duint8 *buf, duint64 size, DRW_TextCodec *dc) | |||
148 | :decoder{dc} | |||
149 | ,filestr{new dwgCharStream(buf, size)} | |||
150 | ,maxSize{size} | |||
151 | {} | |||
152 | ||||
153 | dwgBuffer::dwgBuffer(std::ifstream *stream, DRW_TextCodec *dc) | |||
154 | :decoder{dc} | |||
155 | ,filestr{new dwgFileStream(stream)} | |||
156 | ,maxSize{filestr->size()} | |||
157 | {} | |||
158 | ||||
159 | dwgBuffer::dwgBuffer( const dwgBuffer& org ) | |||
160 | :decoder{org.decoder} | |||
161 | ,filestr{org.filestr->clone()} | |||
162 | ,maxSize{filestr->size()} | |||
163 | ,currByte{org.currByte} | |||
164 | ,bitPos{org.bitPos} | |||
165 | {} | |||
166 | ||||
167 | dwgBuffer& dwgBuffer::operator=( const dwgBuffer& org ){ | |||
168 | filestr.reset( org.filestr->clone()); | |||
169 | decoder = org.decoder; | |||
170 | maxSize = filestr->size(); | |||
171 | currByte = org.currByte; | |||
172 | bitPos = org.bitPos; | |||
173 | return *this; | |||
174 | } | |||
175 | ||||
176 | /**Gets the current byte position in buffer **/ | |||
177 | duint64 dwgBuffer::getPosition() const{ | |||
178 | if (bitPos != 0) | |||
179 | return filestr->getPos() -1; | |||
180 | return filestr->getPos(); | |||
181 | } | |||
182 | ||||
183 | /**Sets the buffer position in pos byte, reset the bit position **/ | |||
184 | bool dwgBuffer::setPosition(duint64 pos){ | |||
185 | bitPos = 0; | |||
186 | /* if (pos>=maxSize) | |||
187 | return false;*/ | |||
188 | return filestr->setPos(pos); | |||
189 | // return true; | |||
190 | } | |||
191 | ||||
192 | //RLZ: Fails if ... ??? | |||
193 | void dwgBuffer::setBitPos(duint8 pos){ | |||
194 | if (pos>7) | |||
195 | return; | |||
196 | if (pos != 0 && bitPos == 0){ | |||
197 | duint8 buffer; | |||
198 | filestr->read (&buffer,1); | |||
199 | currByte = buffer; | |||
200 | } | |||
201 | if (pos == 0 && bitPos != 0){//reset current byte | |||
202 | filestr->setPos(filestr->getPos()-1); | |||
203 | } | |||
204 | bitPos = pos; | |||
205 | } | |||
206 | ||||
207 | bool dwgBuffer::moveBitPos(dint32 size){ | |||
208 | if (size == 0) return true; | |||
209 | ||||
210 | dint32 b= size + bitPos; | |||
211 | filestr->setPos(getPosition() + (b >> 3) ); | |||
212 | bitPos = b & 7; | |||
213 | ||||
214 | if (bitPos != 0){ | |||
215 | filestr->read (&currByte,1); | |||
216 | } | |||
217 | return filestr->good(); | |||
218 | } | |||
219 | ||||
220 | /**Reads one Bit returns a char with value 0/1 (B) **/ | |||
221 | duint8 dwgBuffer::getBit(){ | |||
222 | duint8 buffer; | |||
223 | duint8 ret = 0; | |||
224 | if (bitPos == 0){ | |||
225 | filestr->read (&buffer,1); | |||
226 | currByte = buffer; | |||
227 | } | |||
228 | ||||
229 | ret = (currByte >> (7 - bitPos) & 1); | |||
230 | bitPos +=1; | |||
231 | if (bitPos == 8) | |||
232 | bitPos = 0; | |||
233 | ||||
234 | return ret; | |||
235 | } | |||
236 | ||||
237 | /**Reads one Bit returns a bool value 0==false 1==true (B) **/ | |||
238 | bool dwgBuffer::getBoolBit(){ | |||
239 | return (getBit() != 0); | |||
240 | } | |||
241 | ||||
242 | /**Reads two Bits returns a char (BB) **/ | |||
243 | duint8 dwgBuffer::get2Bits(){ | |||
244 | duint8 buffer; | |||
245 | duint8 ret = 0; | |||
246 | if (bitPos == 0){ | |||
247 | filestr->read (&buffer,1); | |||
248 | currByte = buffer; | |||
249 | } | |||
250 | ||||
251 | bitPos +=2; | |||
252 | if (bitPos < 9) | |||
253 | ret = currByte >>(8 - bitPos); | |||
254 | else {//read one bit per byte | |||
255 | ret = currByte << 1; | |||
256 | filestr->read (&buffer,1); | |||
257 | currByte = buffer; | |||
258 | bitPos = 1; | |||
259 | ret = ret | currByte >> 7; | |||
260 | } | |||
261 | if (bitPos == 8) | |||
262 | bitPos = 0; | |||
263 | ret = ret & 3; | |||
264 | return ret; | |||
265 | } | |||
266 | ||||
267 | /**Reads thee Bits returns a char (3B) **/ | |||
268 | //RLZ: todo verify this | |||
269 | duint8 dwgBuffer::get3Bits(){ | |||
270 | duint8 buffer; | |||
271 | duint8 ret = 0; | |||
272 | if (bitPos == 0){ | |||
273 | filestr->read (&buffer,1); | |||
274 | currByte = buffer; | |||
275 | } | |||
276 | ||||
277 | bitPos +=3; | |||
278 | if (bitPos < 9) | |||
279 | ret = currByte >>(8 - bitPos); | |||
280 | else {//read one bit per byte | |||
281 | ret = currByte << 1; | |||
282 | filestr->read (&buffer,1); | |||
283 | currByte = buffer; | |||
284 | bitPos = 1; | |||
285 | ret = ret | currByte >> 7; | |||
286 | } | |||
287 | if (bitPos == 8) | |||
288 | bitPos = 0; | |||
289 | ret = ret & 7; | |||
290 | return ret; | |||
291 | } | |||
292 | ||||
293 | /**Reads tree Bits returns a char (3B) for R24 **/ | |||
294 | //to be written | |||
295 | ||||
296 | /**Reads compressed Short (max. 16 + 2 bits) little-endian order, returns a UNsigned 16 bits (BS) **/ | |||
297 | duint16 dwgBuffer::getBitShort(){ | |||
298 | duint8 b = get2Bits(); | |||
299 | if (b == 0) | |||
300 | return getRawShort16(); | |||
301 | else if (b== 1) | |||
302 | return getRawChar8(); | |||
303 | else if (b == 2) | |||
304 | return 0; | |||
305 | else | |||
306 | return 256; | |||
307 | } | |||
308 | /**Reads compressed Short (max. 16 + 2 bits) little-endian order, returns a signed 16 bits (BS) **/ | |||
309 | dint16 dwgBuffer::getSBitShort(){ | |||
310 | duint8 b = get2Bits(); | |||
311 | if (b == 0) | |||
312 | return static_cast<dint16>(getRawShort16()); | |||
313 | else if (b== 1) | |||
314 | return static_cast<dint16>(getRawChar8()); | |||
315 | else if (b == 2) | |||
316 | return 0; | |||
317 | else | |||
318 | return 256; | |||
319 | } | |||
320 | ||||
321 | /**Reads compressed 32 bits Int (max. 32 + 2 bits) little-endian order, returns a signed 32 bits (BL) **/ | |||
322 | //to be written | |||
323 | dint32 dwgBuffer::getBitLong(){ | |||
324 | dint8 b = get2Bits(); | |||
325 | if (b == 0) | |||
326 | return getRawLong32(); | |||
327 | else if (b== 1) | |||
328 | return getRawChar8(); | |||
329 | else //if (b == 2) | |||
330 | return 0; | |||
331 | } | |||
332 | ||||
333 | /**Reads compressed 64 bits Int (max. 56 + 3 bits) little-endian order, returns a unsigned 64 bits (BLL) **/ | |||
334 | duint64 dwgBuffer::getBitLongLong(){ | |||
335 | dint8 b = get3Bits(); | |||
336 | duint64 ret=0; | |||
337 | for (duint8 i=0; i<b; i++){ | |||
338 | ret = ret << 8; | |||
339 | ret |= getRawChar8(); | |||
340 | } | |||
341 | return ret; | |||
342 | } | |||
343 | ||||
344 | /**Reads compressed Double (max. 64 + 2 bits) returns a floating point double of 64 bits (BD) **/ | |||
345 | double dwgBuffer::getBitDouble(){ | |||
346 | dint8 b = get2Bits(); | |||
347 | if (b == 1) | |||
348 | return 1.0; | |||
349 | else if (b == 0){ | |||
350 | duint8 buffer[8]; | |||
351 | if (bitPos != 0) { | |||
352 | for (int i = 0; i < 8; i++) | |||
353 | buffer[i] = getRawChar8(); | |||
354 | } else { | |||
355 | filestr->read (buffer,8); | |||
356 | } | |||
357 | double* ret = reinterpret_cast<double*>( buffer ); | |||
358 | return *ret; | |||
359 | } | |||
360 | // if (b == 2) | |||
361 | return 0.0; | |||
362 | } | |||
363 | ||||
364 | /**Reads 3 compressed Double (max. 64 + 2 bits) returns a DRW_Coord of floating point double of 64 bits (3BD) **/ | |||
365 | DRW_Coord dwgBuffer::get3BitDouble(){ | |||
366 | DRW_Coord crd; | |||
367 | crd.x = getBitDouble(); | |||
368 | crd.y = getBitDouble(); | |||
369 | crd.z = getBitDouble(); | |||
370 | return crd; | |||
371 | } | |||
372 | ||||
373 | /**Reads raw char 8 bits returns a unsigned char (RC) **/ | |||
374 | duint8 dwgBuffer::getRawChar8(){ | |||
375 | duint8 ret=0; | |||
376 | duint8 buffer=0; | |||
377 | filestr->read (&buffer,1); | |||
378 | if (bitPos == 0) | |||
379 | return buffer; | |||
380 | else { | |||
381 | ret = currByte << bitPos; | |||
382 | currByte = buffer; | |||
383 | ret = ret | (currByte >>(8 - bitPos)); | |||
384 | } | |||
385 | return ret; | |||
386 | } | |||
387 | ||||
388 | /**Reads raw short 16 bits little-endian order, returns a unsigned short (RS) **/ | |||
389 | duint16 dwgBuffer::getRawShort16(){ | |||
390 | duint8 buffer[2]={0,0}; | |||
391 | duint16 ret=0; | |||
392 | ||||
393 | filestr->read (buffer,2); | |||
394 | if (bitPos == 0) { | |||
395 | /* no offset directly swap bytes for little-endian */ | |||
396 | ret = (buffer[1] << 8) | (buffer[0] & 0x00FF); | |||
397 | } else { | |||
398 | ret = (buffer[0] << 8) | (buffer[1] & 0x00FF); | |||
399 | /* apply offset */ | |||
400 | ret = ret >> (8 - bitPos); | |||
401 | ret = ret | (currByte << (8 + bitPos)); | |||
402 | currByte = buffer[1]; | |||
403 | /* swap bytes for little-endian */ | |||
404 | ret = (ret << 8) | (ret >> 8); | |||
405 | } | |||
406 | return ret; | |||
407 | } | |||
408 | ||||
409 | /**Reads raw double IEEE standard 64 bits returns a double (RD) **/ | |||
410 | double dwgBuffer::getRawDouble(){ | |||
411 | duint8 buffer[8]; | |||
412 | memset(buffer,0,sizeof(buffer)); | |||
413 | if (bitPos == 0) | |||
414 | filestr->read (buffer,8); | |||
415 | else { | |||
416 | for (int i = 0; i < 8; i++) | |||
417 | buffer[i] = getRawChar8(); | |||
418 | } | |||
419 | double* nOffset = reinterpret_cast<double*>( buffer ); | |||
420 | return *nOffset; | |||
421 | } | |||
422 | ||||
423 | /**Reads 2 raw double IEEE standard 64 bits returns a DRW_Coord of floating point double 64 bits (2RD) **/ | |||
424 | DRW_Coord dwgBuffer::get2RawDouble(){ | |||
425 | DRW_Coord crd; | |||
426 | crd.x = getRawDouble(); | |||
427 | crd.y = getRawDouble(); | |||
428 | return crd; | |||
429 | } | |||
430 | ||||
431 | ||||
432 | /**Reads raw int 32 bits little-endian order, returns a unsigned (RL) **/ | |||
433 | duint32 dwgBuffer::getRawLong32(){ | |||
434 | duint16 tmp1 = getRawShort16(); | |||
435 | duint16 tmp2 = getRawShort16(); | |||
436 | duint32 ret = (tmp2 << 16) | (tmp1 & 0x0000FFFF); | |||
437 | ||||
438 | return ret; | |||
439 | } | |||
440 | ||||
441 | /**Reads raw int 64 bits little-endian order, returns a unsigned long long (RLL) **/ | |||
442 | duint64 dwgBuffer::getRawLong64(){ | |||
443 | duint32 tmp1 = getRawLong32(); | |||
444 | duint64 tmp2 = getRawLong32(); | |||
445 | duint64 ret = (tmp2 << 32) | (tmp1 & 0x00000000FFFFFFFF); | |||
446 | ||||
447 | return ret; | |||
448 | } | |||
449 | ||||
450 | /**Reads modular unsigner int, char based, compressed form, little-endian order, returns a unsigned (U-MC) **/ | |||
451 | duint32 dwgBuffer::getUModularChar(){ | |||
452 | std::vector<duint8> buffer; | |||
453 | duint32 result =0; | |||
454 | for (int i=0; i<4;i++){ | |||
455 | duint8 b= getRawChar8(); | |||
456 | buffer.push_back(b & 0x7F); | |||
457 | if (! (b & 0x80)) | |||
458 | break; | |||
459 | } | |||
460 | int offset = 0; | |||
461 | for (unsigned int i=0; i<buffer.size();i++){ | |||
462 | result += buffer[i] << offset; | |||
463 | offset +=7; | |||
464 | } | |||
465 | //RLZ: WARNING!!! needed to verify on read handles | |||
466 | //result = result & 0x7F; | |||
467 | return result; | |||
468 | } | |||
469 | ||||
470 | /**Reads modular int, char based, compressed form, little-endian order, returns a signed int (MC) **/ | |||
471 | dint32 dwgBuffer::getModularChar(){ | |||
472 | bool negative = false; | |||
473 | std::vector<dint8> buffer; | |||
474 | dint32 result =0; | |||
475 | for (int i=0; i<4;i++){ | |||
476 | duint8 b= getRawChar8(); | |||
477 | buffer.push_back(b & 0x7F); | |||
478 | if (! (b & 0x80)) | |||
479 | break; | |||
480 | } | |||
481 | dint8 b= buffer.back(); | |||
482 | if (b & 0x40) { | |||
483 | negative = true; | |||
484 | buffer.pop_back(); | |||
485 | buffer.push_back(b & 0x3F); | |||
486 | } | |||
487 | ||||
488 | int offset = 0; | |||
489 | for (unsigned int i=0; i<buffer.size();i++){ | |||
490 | result += buffer[i] << offset; | |||
491 | offset +=7; | |||
492 | } | |||
493 | if (negative) | |||
494 | result = -result; | |||
495 | return result; | |||
496 | } | |||
497 | ||||
498 | /**Reads modular int, short based, compressed form, little-endian order, returns a unsigned (MC) **/ | |||
499 | dint32 dwgBuffer::getModularShort(){ | |||
500 | // bool negative = false; | |||
501 | std::vector<dint16> buffer; | |||
502 | dint32 result =0; | |||
503 | for (int i=0; i<2;i++){ | |||
| ||||
504 | duint16 b= getRawShort16(); | |||
505 | buffer.push_back(b & 0x7FFF); | |||
506 | if (! (b & 0x8000)) | |||
507 | break; | |||
508 | } | |||
509 | ||||
510 | //only positive ? | |||
511 | /* dint8 b= buffer.back(); | |||
512 | if (! (b & 0x40)) { | |||
513 | negative = true; | |||
514 | buffer.pop_back(); | |||
515 | buffer.push_back(b & 0x3F); | |||
516 | }*/ | |||
517 | ||||
518 | int offset = 0; | |||
519 | for (unsigned int i=0; i<buffer.size();i++){ | |||
520 | result += buffer[i] << offset; | |||
| ||||
521 | offset +=15; | |||
522 | } | |||
523 | /* if (negative) | |||
524 | result = -result;*/ | |||
525 | return result; | |||
526 | } | |||
527 | ||||
528 | dwgHandle dwgBuffer::getHandle(){ //H | |||
529 | dwgHandle hl; | |||
530 | duint8 data = getRawChar8(); | |||
531 | hl.code = (data >> 4) & 0x0F; | |||
532 | hl.size = data & 0x0F; | |||
533 | hl.ref=0; | |||
534 | for (int i=0; i< hl.size;i++){ | |||
535 | hl.ref = (hl.ref << 8) | getRawChar8(); | |||
536 | } | |||
537 | return hl; | |||
538 | } | |||
539 | ||||
540 | dwgHandle dwgBuffer::getOffsetHandle(duint32 href){ //H | |||
541 | dwgHandle hl = getHandle(); | |||
542 | if (hl.code > 5){ | |||
543 | if (hl.code == 0x0C) | |||
544 | hl.ref = href - hl.ref; | |||
545 | else if (hl.code == 0x0A) | |||
546 | hl.ref = href + hl.ref; | |||
547 | else if (hl.code == 0x08) | |||
548 | hl.ref = href - 1; | |||
549 | else if (hl.code == 0x06) | |||
550 | hl.ref = href + 1; | |||
551 | //all are soft pointer reference change to 7 (without offset) | |||
552 | hl.code = 7; | |||
553 | } | |||
554 | return hl; | |||
555 | } | |||
556 | ||||
557 | //internal until 2004 | |||
558 | std::string dwgBuffer::get8bitStr(){ | |||
559 | duint16 textSize = getBitShort(); | |||
560 | if (textSize == 0) | |||
561 | return std::string(); | |||
562 | duint8 *tmpBuffer = new duint8[textSize]; | |||
563 | bool good = getBytes(tmpBuffer, textSize); | |||
564 | if (!good) | |||
565 | return std::string(); | |||
566 | ||||
567 | /* filestr->read (buffer,textSize); | |||
568 | if (!filestr->good()) | |||
569 | return std::string(); | |||
570 | ||||
571 | duint8 tmp; | |||
572 | if (bitPos != 0){ | |||
573 | for (int i=0; i<textSize;i++){ | |||
574 | tmp = buffer[i]; | |||
575 | buffer[i] = (currByte << bitPos) | (tmp >> (8 - bitPos)); | |||
576 | currByte = tmp; | |||
577 | } | |||
578 | }*/ | |||
579 | std::string str(reinterpret_cast<char*>(tmpBuffer), textSize); | |||
580 | delete[]tmpBuffer; | |||
581 | ||||
582 | return str; | |||
583 | } | |||
584 | ||||
585 | //internal since 2007 //pending: are 2 bytes null terminated?? | |||
586 | //nullTerm = true if string are 2 bytes null terminated from the stream | |||
587 | std::string dwgBuffer::get16bitStr(duint16 textSize, bool nullTerm){ | |||
588 | if (textSize == 0) | |||
589 | return std::string(); | |||
590 | textSize *=2; | |||
591 | duint16 ts = textSize; | |||
592 | if (nullTerm) | |||
593 | ts += 2; | |||
594 | duint8 *tmpBuffer = new duint8[textSize + 2]; | |||
595 | bool good = getBytes(tmpBuffer, ts); | |||
596 | if (!good) | |||
597 | return std::string(); | |||
598 | if (!nullTerm) { | |||
599 | tmpBuffer[textSize] = '\0'; | |||
600 | tmpBuffer[textSize + 1] = '\0'; | |||
601 | } | |||
602 | std::string str(reinterpret_cast<char*>(tmpBuffer), ts); | |||
603 | delete[]tmpBuffer; | |||
604 | ||||
605 | return str; | |||
606 | } | |||
607 | ||||
608 | //T 8 bit text converted from codepage to utf8 | |||
609 | std::string dwgBuffer::getCP8Text(){ | |||
610 | std::string strData; | |||
611 | strData = get8bitStr();//RLZ correct these function | |||
612 | if (!decoder) | |||
613 | return strData; | |||
614 | ||||
615 | return decoder->toUtf8(strData); | |||
616 | } | |||
617 | ||||
618 | //TU unicode 16 bit (UCS) text converted to utf8 | |||
619 | /**Reads 2-bytes char (UCS2, NULL terminated) and convert to std::string (only for Latin-1) | |||
620 | ts= total input size in bytes. | |||
621 | **/ | |||
622 | std::string dwgBuffer::getUCSStr(duint16 ts){ | |||
623 | std::string strData; | |||
624 | if (ts<4) //at least 1 char | |||
625 | return std::string(); | |||
626 | strData = get16bitStr(ts/2, false); | |||
627 | if (!decoder) | |||
628 | return strData; | |||
629 | ||||
630 | return decoder->toUtf8(strData); | |||
631 | } | |||
632 | ||||
633 | //TU unicode 16 bit (UCS) text converted to utf8 | |||
634 | //nullTerm = true if string are 2 bytes null terminated from the stream | |||
635 | std::string dwgBuffer::getUCSText(bool nullTerm){ | |||
636 | std::string strData; | |||
637 | duint16 ts = getBitShort(); | |||
638 | if (ts == 0) | |||
639 | return std::string(); | |||
640 | ||||
641 | strData = get16bitStr(ts, nullTerm); | |||
642 | if (!decoder) | |||
643 | return strData; | |||
644 | ||||
645 | return decoder->toUtf8(strData); | |||
646 | } | |||
647 | ||||
648 | //RLZ: read a T or TU if version is 2007+ | |||
649 | //nullTerm = true if string are 2 bytes null terminated from the stream | |||
650 | std::string dwgBuffer::getVariableText(DRW::Version v, bool nullTerm){//TV | |||
651 | if (v > DRW::AC1018) | |||
652 | return getUCSText(nullTerm); | |||
653 | return getCP8Text(); | |||
654 | } | |||
655 | duint16 dwgBuffer::getObjType(DRW::Version v){//OT | |||
656 | if (v > DRW::AC1021) { | |||
657 | duint8 b = get2Bits(); | |||
658 | if (b == 0) | |||
659 | return getRawChar8(); | |||
660 | else if (b== 1){ | |||
661 | return (getRawChar8() + 0x01F0); | |||
662 | } else //b == 2 | |||
663 | return getRawShort16(); | |||
664 | } | |||
665 | return getBitShort(); | |||
666 | } | |||
667 | ||||
668 | /* Bit Extrusion | |||
669 | * For R2000+, this is a single bit, If the single bit is 1, | |||
670 | * the extrusion value is assumed to be 0,0,1 and no explicit | |||
671 | * extrusion is stored. If the single bit is 0, then it will | |||
672 | * be followed by 3BD. | |||
673 | * For R13-R14 this is 3BD. | |||
674 | */ | |||
675 | DRW_Coord dwgBuffer::getExtrusion(bool b_R2000_style) { | |||
676 | DRW_Coord ext(0.0,0.0,1.0); | |||
677 | if ( b_R2000_style ) | |||
678 | /* If the bit is one, the extrusion value is assumed to be 0,0,1*/ | |||
679 | if ( getBit() == 1 ) | |||
680 | return ext; | |||
681 | /*R13-R14 or bit == 0*/ | |||
682 | ext.x = getBitDouble(); | |||
683 | ext.y = getBitDouble(); | |||
684 | ext.z = getBitDouble(); | |||
685 | return ext; | |||
686 | } | |||
687 | ||||
688 | /**Reads compressed Double with default (max. 64 + 2 bits) returns a floating point double of 64 bits (DD) **/ | |||
689 | double dwgBuffer::getDefaultDouble(double d){ | |||
690 | dint8 b = get2Bits(); | |||
691 | if (b == 0) | |||
692 | return d; | |||
693 | else if (b == 1){ | |||
694 | duint8 buffer[4]; | |||
695 | char *tmp=nullptr; | |||
696 | if (bitPos != 0) { | |||
697 | for (int i = 0; i < 4; i++) | |||
698 | buffer[i] = getRawChar8(); | |||
699 | } else { | |||
700 | filestr->read (buffer,4); | |||
701 | } | |||
702 | tmp = reinterpret_cast<char*>(&d); | |||
703 | for (int i = 0; i < 4; i++) | |||
704 | tmp[i] = buffer[i]; | |||
705 | double ret = *reinterpret_cast<double*>( tmp ); | |||
706 | return ret; | |||
707 | } else if (b == 2){ | |||
708 | duint8 buffer[6]; | |||
709 | char *tmp=nullptr; | |||
710 | if (bitPos != 0) { | |||
711 | for (int i = 0; i < 6; i++) | |||
712 | buffer[i] = getRawChar8(); | |||
713 | } else { | |||
714 | filestr->read (buffer,6); | |||
715 | } | |||
716 | tmp = reinterpret_cast<char*>(&d); | |||
717 | for (int i = 2; i < 6; i++) | |||
718 | tmp[i-2] = buffer[i]; | |||
719 | tmp[4] = buffer[0]; | |||
720 | tmp[5] = buffer[1]; | |||
721 | double ret = *reinterpret_cast<double*>( tmp ); | |||
722 | return ret; | |||
723 | } | |||
724 | // if (b == 3) return a full raw double | |||
725 | return getRawDouble(); | |||
726 | } | |||
727 | ||||
728 | ||||
729 | /* BitThickness | |||
730 | * For R13-R14, this is a BD. | |||
731 | * For R2000+, this is a single bit, If the bit is one, | |||
732 | * the thickness value is assumed to be 0.0, if not a BD follow | |||
733 | */ | |||
734 | double dwgBuffer::getThickness(bool b_R2000_style) { | |||
735 | if ( b_R2000_style ) | |||
736 | /* If the bit is one, the thickness value is assumed to be 0.0.*/ | |||
737 | if ( getBit() == 1 ) | |||
738 | return 0.0; | |||
739 | /*R13-R14 or bit == 0*/ | |||
740 | return getBitDouble(); | |||
741 | } | |||
742 | ||||
743 | /* CmColor (CMC) | |||
744 | * For R15 and earlier call directly BS as ACIS color. | |||
745 | * For R2004+, can be CMC or ENC | |||
746 | * RGB value, first 4bits 0xC0 => ByLayer, 0xC1 => ByBlock, 0xC2 => RGB, 0xC3 => last 4 are ACIS | |||
747 | */ | |||
748 | duint32 dwgBuffer::getCmColor(DRW::Version v) { | |||
749 | if (v < DRW::AC1018) //2000- | |||
750 | return getSBitShort(); | |||
751 | duint16 idx = getBitShort(); | |||
752 | duint32 rgb = getBitLong(); | |||
753 | duint8 cb = getRawChar8(); | |||
754 | duint8 type = rgb >> 24; | |||
755 | DRW_DBG("\ntype COLOR: ")DRW_dbg::getInstance()->print("\ntype COLOR: "); DRW_DBGH(type)DRW_dbg::getInstance()->printH(type); | |||
756 | DRW_DBG("\nindex COLOR: ")DRW_dbg::getInstance()->print("\nindex COLOR: "); DRW_DBGH(idx)DRW_dbg::getInstance()->printH(idx); | |||
757 | DRW_DBG("\nRGB COLOR: ")DRW_dbg::getInstance()->print("\nRGB COLOR: "); DRW_DBGH(rgb)DRW_dbg::getInstance()->printH(rgb); | |||
758 | DRW_DBG("\nbyte COLOR: ")DRW_dbg::getInstance()->print("\nbyte COLOR: "); DRW_DBGH(cb)DRW_dbg::getInstance()->printH(cb); | |||
759 | if (cb&1){ | |||
760 | std::string colorName = getVariableText(v, false); | |||
761 | DRW_DBG("\ncolorName: ")DRW_dbg::getInstance()->print("\ncolorName: "); DRW_DBG(colorName)DRW_dbg::getInstance()->print(colorName); | |||
762 | } | |||
763 | if (cb&2){ | |||
764 | std::string bookName = getVariableText(v, false); | |||
765 | DRW_DBG("\nbookName: ")DRW_dbg::getInstance()->print("\nbookName: "); DRW_DBG(bookName)DRW_dbg::getInstance()->print(bookName); | |||
766 | } | |||
767 | switch (type) { | |||
768 | case 0xC0: | |||
769 | return 256;//ByLayer | |||
770 | case 0xC1: | |||
771 | return 0;//ByBlock | |||
772 | case 0xC2: | |||
773 | return 256;//RGB RLZ TODO | |||
774 | case 0xC3: | |||
775 | return rgb&0xFF;//ACIS | |||
776 | default: | |||
777 | break; | |||
778 | } | |||
779 | //check cb if strings follows RLZ TODO | |||
780 | return 256; //default return ByLayer | |||
781 | } | |||
782 | ||||
783 | /* EnColor (ENC) | |||
784 | * For R15 and earlier call directly BS as ACIS color. | |||
785 | * For R2004+, can be CMC or ENC | |||
786 | * RGB value, first 4bits 0xC0 => ByLayer, 0xC1 => ByBlock, 0xC2 => RGB, 0xC3 => last 4 are ACIS | |||
787 | */ | |||
788 | duint32 dwgBuffer::getEnColor(DRW::Version v) { | |||
789 | if (v < DRW::AC1018) //2000- | |||
790 | return getSBitShort(); | |||
791 | duint32 rgb = 0; | |||
792 | duint32 cb = 0; | |||
793 | duint16 idx = getBitShort(); | |||
794 | DRW_DBG("idx reads COLOR: ")DRW_dbg::getInstance()->print("idx reads COLOR: "); DRW_DBGH(idx)DRW_dbg::getInstance()->printH(idx); | |||
795 | duint16 flags = idx>>8; | |||
796 | idx = idx & 0x1FF; //RLZ: warning this is correct? | |||
797 | DRW_DBG("\nflag COLOR: ")DRW_dbg::getInstance()->print("\nflag COLOR: "); DRW_DBGH(flags)DRW_dbg::getInstance()->printH(flags); | |||
798 | DRW_DBG(", index COLOR: ")DRW_dbg::getInstance()->print(", index COLOR: "); DRW_DBGH(idx)DRW_dbg::getInstance()->printH(idx); | |||
799 | // if (flags & 0x80) { | |||
800 | // rgb = getBitLong(); | |||
801 | // DRW_DBG("\nRGB COLOR: "); DRW_DBGH(rgb); | |||
802 | // } | |||
803 | if (flags & 0x20) { | |||
804 | cb = getBitLong(); | |||
805 | DRW_DBG("\nTransparency COLOR: ")DRW_dbg::getInstance()->print("\nTransparency COLOR: "); DRW_DBGH(cb)DRW_dbg::getInstance()->printH(cb); | |||
806 | } | |||
807 | if (flags & 0x40) | |||
808 | DRW_DBG("\nacdbColor COLOR are present")DRW_dbg::getInstance()->print("\nacdbColor COLOR are present" ); | |||
809 | else { | |||
810 | if (flags & 0x80) { | |||
811 | rgb = getBitLong(); | |||
812 | DRW_DBG("\nRGB COLOR: ")DRW_dbg::getInstance()->print("\nRGB COLOR: "); DRW_DBGH(rgb)DRW_dbg::getInstance()->printH(rgb); | |||
813 | } | |||
814 | } | |||
815 | ||||
816 | /* if (flags & 0x80) | |||
817 | return getBitLong();*/ | |||
818 | ||||
819 | return idx; //default return ByLayer | |||
820 | } | |||
821 | ||||
822 | ||||
823 | /**Reads raw short 16 bits big-endian order, returns a unsigned short crc & size **/ | |||
824 | duint16 dwgBuffer::getBERawShort16(){ | |||
825 | char buffer[2]; | |||
826 | buffer[0] = getRawChar8(); | |||
827 | buffer[1] = getRawChar8(); | |||
828 | duint16 size = (buffer[0] << 8) | (buffer[1] & 0xFF); | |||
829 | return size; | |||
830 | } | |||
831 | ||||
832 | /* reads "size" bytes and stores in "buf" return false if fail */ | |||
833 | bool dwgBuffer::getBytes(unsigned char *buf, duint64 size){ | |||
834 | duint8 tmp; | |||
835 | filestr->read (buf,size); | |||
836 | if (!filestr->good()) | |||
837 | return false; | |||
838 | ||||
839 | if (bitPos != 0){ | |||
840 | for (duint64 i=0; i<size;i++){ | |||
841 | tmp = buf[i]; | |||
842 | buf[i] = (currByte << bitPos) | (tmp >> (8 - bitPos)); | |||
843 | currByte = tmp; | |||
844 | } | |||
845 | } | |||
846 | return true; | |||
847 | } | |||
848 | ||||
849 | duint16 dwgBuffer::crc8(duint16 dx,dint32 start,dint32 end){ | |||
850 | duint64 pos = filestr->getPos(); | |||
851 | filestr->setPos(start); | |||
852 | int n = end-start; | |||
853 | duint8 *tmpBuf = new duint8[n]; | |||
854 | duint8 *p = tmpBuf; | |||
855 | filestr->read (tmpBuf,n); | |||
856 | filestr->setPos(pos); | |||
857 | if (!filestr->good()) | |||
858 | return 0; | |||
859 | ||||
860 | duint8 al; | |||
861 | ||||
862 | while (n-- > 0) { | |||
863 | al = (duint8)((*p) ^ ((dint8)(dx & 0xFF))); | |||
864 | dx = (dx>>8) & 0xFF; | |||
865 | dx = dx ^ crctable[al & 0xFF]; | |||
866 | p++; | |||
867 | } | |||
868 | delete[]tmpBuf; | |||
869 | return(dx); | |||
870 | } | |||
871 | ||||
872 | duint32 dwgBuffer::crc32(duint32 seed,dint32 start,dint32 end){ | |||
873 | duint64 pos = filestr->getPos(); | |||
874 | filestr->setPos(start); | |||
875 | int n = end-start; | |||
876 | duint8 *tmpBuf = new duint8[n]; | |||
877 | duint8 *p = tmpBuf; | |||
878 | filestr->read (tmpBuf,n); | |||
879 | filestr->setPos(pos); | |||
880 | if (!filestr->good()) | |||
881 | return 0; | |||
882 | ||||
883 | duint32 invertedCrc = ~seed; | |||
884 | while (n-- > 0) { | |||
885 | duint8 data = *p++; | |||
886 | invertedCrc = (invertedCrc >> 8) ^ crc32Table[(invertedCrc ^ data) & 0xff]; | |||
887 | } | |||
888 | delete[]tmpBuf; | |||
889 | return ~invertedCrc; | |||
890 | } | |||
891 | ||||
892 | ||||
893 | /*std::string dwgBuffer::getBytes(int size){ | |||
894 | char buffer[size]; | |||
895 | char tmp; | |||
896 | filestr->read (buffer,size); | |||
897 | if (!filestr->good()) | |||
898 | return NULL; | |||
899 | ||||
900 | if (bitPos != 0){ | |||
901 | for (int i=0; i<=size;i++){ | |||
902 | tmp = buffer[i]; | |||
903 | buffer[i] = (currByte << bitPos) | (tmp >> (8 - bitPos)); | |||
904 | currByte = tmp; | |||
905 | } | |||
906 | } | |||
907 | std::string st; | |||
908 | for (int i=0; i<size;i++) { | |||
909 | st.push_back(buffer[i]); | |||
910 | } | |||
911 | return st; | |||
912 | // return std::string(buffer); | |||
913 | }*/ | |||
914 |