def test_read_unsigned_long(): # little endian! data = b"\x00\x0e\xfc\xda\xb0" bs = BitStream(data) assert bs.read_bits(4) == 0 assert bs.read_unsigned_long() == 0xABCDEF00 assert bs.read_bits(4) == 0
def test_read_unsigned_long(): # little endian! data = b'\x00\x0e\xfc\xda\xb0' bs = BitStream(data) assert bs.read_bits(4) == 0 assert bs.read_unsigned_long() == 0xabcdef00 assert bs.read_bits(4) == 0
def parse_bitstream(bs: BitStream, commands: List[Tuple[str, Any]]) -> Dict[str, Any]: version = bs.dxfversion min_ver = ACAD_13 max_ver = ACAD_LATEST hdr_vars: Dict[str, Any] = dict() skip_next_cmd = False for cmd, params in commands: if skip_next_cmd: skip_next_cmd = False continue if cmd == CMD_SET_VERSION: min_ver, max_ver = params elif cmd == CMD_SKIP_BITS: bs.skip(int(params)) elif cmd == CMD_SKIP_NEXT_IF: skip_next_cmd = eval(params, None, {"header": hdr_vars}) elif cmd == CMD_SET_VAR: if min_ver <= version <= max_ver: name, code = params hdr_vars[name] = bs.read_code(code) else: raise ValueError(f"Unknown command: {cmd}") return hdr_vars
def test_read_unsigned_short(): # little endian! data = b"\x0c\xda\xb0" bs = BitStream(data) assert bs.read_bits(4) == 0 assert bs.read_unsigned_short() == 0xABCD assert bs.read_bits(4) == 0
def test_read_bits(): data = b"\x0f\x0f" bs = BitStream(data) assert bs.read_bits(4) == 0 assert bs.read_bits(2) == 3 assert bs.read_bits(3) == 6 assert bs.read_bits(4) == 1 assert bs.read_bits(3) == 7
def test_read_bitshort(): bs = BitStream(b"\xe0") assert bs.read_bit_short() == 256 # 11 assert bs.read_bit_short() == 0 # 10 bs = BitStream(b"\x00\xff\xff") bs.read_bits(6) assert bs.read_bit_short() == -1 assert BitStream(b"\x7f\x00").read_bit_short() == 252
def test_read_signed_modular_chars(): bs = BitStream(bytes([ 0b11101001, 0b10010111, 0b11100110, 0b00110101, 0b10000010, 0b00100100, 0b10000101, 0b01001011, ])) mc = bs.read_signed_modular_chars() assert mc == 112823273 mc = bs.read_signed_modular_chars() assert mc == 4610 mc = bs.read_signed_modular_chars() assert mc == -1413
def test_read_modular_shorts(): bs = BitStream( bytes( [ 0b00110001, 0b11110100, 0b10001101, 0b00000000, ] ) ) ms = bs.read_modular_shorts() assert ms == 4650033
def load_classes(self) -> Iterable[Tuple[int, DXFClass]]: sentinel = self.data[:SENTINEL_SIZE] if ( sentinel != b"\x8D\xA1\xC4\xB8\xC4\xA9\xF8\xC5\xC0\xDC\xF4\x5F\xE7\xCF\xB6\x8A" ): raise DwgCorruptedClassesSection( "Sentinel for start of CLASSES section not found." ) start_index = SENTINEL_SIZE bs = BitStream( self.data[start_index:], dxfversion=self.specs.version, encoding=self.specs.encoding, ) class_data_size = bs.read_unsigned_long() # data size in bytes end_sentinel_index = SENTINEL_SIZE + 6 + class_data_size end_index = end_sentinel_index - 2 end_bit_index = (3 + class_data_size) << 3 while bs.bit_index < end_bit_index: class_num = bs.read_bit_short() dxfattribs = { "flags": bs.read_bit_short(), # version? "app_name": bs.read_text(), "cpp_class_name": bs.read_text(), "name": bs.read_text(), "was_a_proxy": bs.read_bit(), "is_an_entity": int(bs.read_bit_short() == 0x1F2), } yield class_num, DXFClass.new(dxfattribs=dxfattribs) if self.crc_check and False: check = struct.unpack_from("<H", self.data, end_index)[0] # TODO: classes crc check # Which data should be checked? This is not correct: crc = crc8(self.data[start_index:end_index]) if check != crc: raise CRCError("CRC error in classes section.") sentinel = self.data[ end_sentinel_index : end_sentinel_index + SENTINEL_SIZE ] if ( sentinel != b"\x72\x5E\x3B\x47\x3B\x56\x07\x3A\x3F\x23\x0B\xA0\x18\x30\x49\x75" ): raise DwgCorruptedClassesSection( "Sentinel for end of CLASSES section not found." )
def load_header_vars(self) -> Dict: data = self.data sentinel = data[:16] if (sentinel != b"\xCF\x7B\x1F\x23\xFD\xDE\x38\xA9\x5F\x7C\x68\xB8\x4E\x6D\x33\x5F" ): raise DwgCorruptedHeaderSection( "Sentinel for start of HEADER section not found.") index = 16 size = struct.unpack_from("<L", data, index)[0] index += 4 bs = BitStream( data[index:index + size], dxfversion=self.specs.version, encoding=self.specs.encoding, ) hdr_vars = parse_header(bs) index += size if self.crc_check: check = struct.unpack_from("<H", data, index)[0] # CRC of data from end of sentinel until start of crc value crc = crc8(data[16:-18], seed=0xC0C1) if check != crc: raise CRCError("CRC error in header section.") sentinel = data[-16:] if (sentinel != b"\x30\x84\xE0\xDC\x02\x21\xC7\x56\xA0\x83\x97\x47\xB1\x92\xCC\xA0" ): raise DwgCorruptedHeaderSection( "Sentinel for end of HEADER section not found.") return hdr_vars
def test_read_object_type(): assert BitStream(bytes([0b00000000, 0b01000000])).read_object_type() == 1 assert ( BitStream(bytes([0b01000000, 0b01000000])).read_object_type() == 1 + 0x1F0 ) assert ( BitStream( bytes([0b10000000, 0b01000000, 0b01000000]) ).read_object_type() == 257 ) assert ( BitStream( bytes([0b11000000, 0b01000000, 0b01000000]) ).read_object_type() == 257 )
def classes_R2000(self) -> None: seeker, section_size = self.specs.sections[CLASSES_ID] sentinel = self.data[seeker:seeker + SENTINEL_SIZE] if sentinel != b'\x8D\xA1\xC4\xB8\xC4\xA9\xF8\xC5\xC0\xDC\xF4\x5F\xE7\xCF\xB6\x8A': raise DwgCorruptedClassesSection( 'Sentinel for start of section not found.') cls_tag = DXFTag(0, 'CLASS') classes = self.sections['CLASSES'] bs = BitStream( self.data[seeker + SENTINEL_SIZE:seeker + section_size], dxfversion=self.specs.version, encoding=self.specs.encoding, ) class_data_size = bs.read_unsigned_long() # data size in bytes end_index = (3 + class_data_size) << 3 while bs.bit_index < end_index: class_num = bs.read_bit_short() flags = bs.read_bit_short() # version? app_name = bs.read_text() cpp_class_name = bs.read_text() class_dxf_name = bs.read_text() was_a_zombie = bs.read_bit() item_class_id = bs.read_bit_short() # print((class_num, flags, app_name, class_dxf_name, cpp_class_name, was_a_zombie, item_class_id)) classes.append( Tags([ cls_tag, DXFTag(1, class_dxf_name), DXFTag(2, cpp_class_name), DXFTag(3, app_name), DXFTag(90, flags), DXFTag(280, was_a_zombie), DXFTag(281, 1 if item_class_id == 0x1f2 else 0) ])) self.dxf_object_types[class_num] = class_dxf_name # Ignore crc for the sake of speed. # _index = index + (20 + class_data_size) # crc = struct.unpack_from('<h', self.data, index) _index = seeker + (SENTINEL_SIZE + 6 + class_data_size) sentinel = self.data[_index:_index + SENTINEL_SIZE] if sentinel != b'\x72\x5E\x3B\x47\x3B\x56\x07\x3A\x3F\x23\x0B\xA0\x18\x30\x49\x75': raise DwgCorruptedClassesSection( 'Sentinel for end of section not found.')
def test_read_bit(): data = b"\xaa" bs = BitStream(data) assert bs.read_bit() == 1 assert bs.read_bit() == 0 assert bs.read_bit() == 1 assert bs.read_bit() == 0 assert bs.read_bit() == 1 assert bs.read_bit() == 0 assert bs.read_bit() == 1 assert bs.read_bit() == 0 with pytest.raises(EndOfBufferError): _ = bs.read_bit()
def lwpolyline(self, data: bytes): # OpenDesign Specs LWPLINE: 20.4.85 Page 211 logger.warning( 'Untested proxy graphic entity: LWPOLYLINE - Need examples!') bs = BitStream(data) flag = bs.read_bit_short() attribs = self._build_dxf_attribs() if flag & 4: attribs['const_width'] = bs.read_bit_double() if flag & 8: attribs['elevation'] = bs.read_bit_double() if flag & 2: attribs['thickness'] = bs.read_bit_double() if flag & 1: attribs['extrusion'] = Vec3(bs.read_bit_double(3)) num_points = bs.read_bit_long() if flag & 16: num_bulges = bs.read_bit_long() else: num_bulges = 0 if self.dxfversion >= 'AC1024': # R2010+ vertex_id_count = bs.read_bit_long() else: vertex_id_count = 0 if flag & 32: num_width = bs.read_bit_long() else: num_width = 0 # ignore DXF R13/14 special vertex order vertices = [bs.read_raw_double(2)] prev_point = vertices[-1] for _ in range(num_points - 1): x = bs.read_bit_double_default(default=prev_point[0]) y = bs.read_bit_double_default(default=prev_point[1]) prev_point = (x, y) vertices.append(prev_point) bulges = [bs.read_bit_double() for _ in range(num_bulges)] vertex_ids = [bs.read_bit_long() for _ in range(vertex_id_count)] widths = [(bs.read_bit_double(), bs.read_bit_double()) for _ in range(num_width)] if len(bulges) == 0: bulges = list(repeat(0, num_points)) if len(widths) == 0: widths = list(repeat((0, 0), num_points)) points = [] for v, w, b in zip(vertices, widths, bulges): points.append((v[0], v[1], w[0], w[1], b)) lwpolyline = cast('LWPolyline', self._factory('LWPOLYLINE', dxfattribs=attribs)) lwpolyline.set_points(points) return lwpolyline
def test_read_unsigned_byte(): data = b'\x0f\x0f' bs = BitStream(data) assert bs.read_bits(4) == 0 assert bs.read_unsigned_byte() == 0xf0
def test_read_aligned_unsigned_long(): # little endian! data = b'\x00\xef\xcd\xab' bs = BitStream(data) assert bs.read_unsigned_long() == 0xabcdef00
def test_read_aligned_unsigned_long(): # little endian! data = b"\x00\xef\xcd\xab" bs = BitStream(data) assert bs.read_unsigned_long() == 0xABCDEF00
def test_read_aligned_unsigned_short(): # little endian! data = b"\x00\xcd\xab" bs = BitStream(data) assert bs.read_unsigned_byte() == 0 assert bs.read_unsigned_short() == 0xABCD
def test_read_signed_byte(): data = b"\x0f\xf0" bs = BitStream(data) assert bs.read_bits(4) == 0 assert bs.read_signed_byte() == -1