# ***** BEGIN GPL LICENSE BLOCK ***** # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # ***** END GPL LICENCE BLOCK ***** # # (c) 2009, At Mind B.V. - Jeroen Bakker # (c) 2014, Blender Foundation - Campbell Barton # (c) 2018, Blender Foundation - Sybren A. Stüvel import logging import os import pathlib import struct import typing from . import dna_io, exceptions log = logging.getLogger(__name__) class BlendFileHeader: """ BlendFileHeader represents the first 12 bytes of a blend file. It contains information about the hardware architecture, which is relevant to the structure of the rest of the file. """ structure = struct.Struct(b'7s1s1s3s') def __init__(self, fileobj: typing.IO[bytes], path: pathlib.Path) -> None: log.debug("reading blend-file-header %s", path) fileobj.seek(0, os.SEEK_SET) header = fileobj.read(self.structure.size) values = self.structure.unpack(header) self.magic = values[0] pointer_size_id = values[1] if pointer_size_id == b'-': self.pointer_size = 8 elif pointer_size_id == b'_': self.pointer_size = 4 else: raise exceptions.BlendFileError('invalid pointer size %r' % pointer_size_id, path) endian_id = values[2] if endian_id == b'v': self.endian = dna_io.LittleEndianTypes self.endian_str = b'<' # indication for struct.Struct() elif endian_id == b'V': self.endian = dna_io.BigEndianTypes self.endian_str = b'>' # indication for struct.Struct() else: raise exceptions.BlendFileError('invalid endian indicator %r' % endian_id, path) version_id = values[3] self.version = int(version_id) def create_block_header_struct(self) -> struct.Struct: """Create a Struct instance for parsing data block headers.""" return struct.Struct(b''.join(( self.endian_str, b'4sI', b'I' if self.pointer_size == 4 else b'Q', b'II', )))