remove DNACatalog class, this only stored a list
This commit is contained in:
@@ -94,8 +94,8 @@ class BlendFile:
|
|||||||
"block_header_struct",
|
"block_header_struct",
|
||||||
# BlendFileBlock
|
# BlendFileBlock
|
||||||
"blocks",
|
"blocks",
|
||||||
# DNACatalog
|
# [DNAStruct, ...]
|
||||||
"catalog",
|
"structs",
|
||||||
# int
|
# int
|
||||||
"code_index",
|
"code_index",
|
||||||
# bool (did we make a change)
|
# bool (did we make a change)
|
||||||
@@ -115,7 +115,7 @@ class BlendFile:
|
|||||||
block = BlendFileBlock(handle, self)
|
block = BlendFileBlock(handle, self)
|
||||||
while block.code != b'ENDB':
|
while block.code != b'ENDB':
|
||||||
if block.code == b'DNA1':
|
if block.code == b'DNA1':
|
||||||
self.catalog = DNACatalog(self.header, block, handle)
|
self.structs = BlendFile.decode_structs(self.header, block, handle)
|
||||||
else:
|
else:
|
||||||
handle.seek(block.size, os.SEEK_CUR)
|
handle.seek(block.size, os.SEEK_CUR)
|
||||||
|
|
||||||
@@ -126,6 +126,7 @@ class BlendFile:
|
|||||||
self.is_modified = False
|
self.is_modified = False
|
||||||
self.blocks.append(block)
|
self.blocks.append(block)
|
||||||
|
|
||||||
|
|
||||||
def find_blocks_from_code(self, code):
|
def find_blocks_from_code(self, code):
|
||||||
assert(type(code) == bytes)
|
assert(type(code) == bytes)
|
||||||
if code not in self.code_index:
|
if code not in self.code_index:
|
||||||
@@ -161,6 +162,92 @@ class BlendFile:
|
|||||||
|
|
||||||
handle.close()
|
handle.close()
|
||||||
|
|
||||||
|
def sdna_index_from_id(self, dna_type_id):
|
||||||
|
# TODO, use dict?
|
||||||
|
for i, dna_type in enumerate(self.structs):
|
||||||
|
if dna_type_id == dna_type.dna_type_id:
|
||||||
|
return i
|
||||||
|
raise KeyError("%r not found" % dna_type_id)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def decode_structs(header, block, handle):
|
||||||
|
"""
|
||||||
|
DNACatalog is a catalog of all information in the DNA1 file-block
|
||||||
|
"""
|
||||||
|
log.debug("building DNA catalog")
|
||||||
|
shortstruct = DNA_IO.USHORT[header.endian_index]
|
||||||
|
shortstruct2 = struct.Struct(header.endian_str + b'HH')
|
||||||
|
intstruct = DNA_IO.UINT[header.endian_index]
|
||||||
|
|
||||||
|
data = handle.read(block.size)
|
||||||
|
types = []
|
||||||
|
names = []
|
||||||
|
|
||||||
|
structs = []
|
||||||
|
|
||||||
|
offset = 8
|
||||||
|
names_len = intstruct.unpack_from(data, offset)[0]
|
||||||
|
offset += 4
|
||||||
|
|
||||||
|
log.debug("building #%d names" % names_len)
|
||||||
|
for i in range(names_len):
|
||||||
|
tName = DNA_IO.read_data0(data, offset)
|
||||||
|
offset = offset + len(tName) + 1
|
||||||
|
names.append(DNAName(tName))
|
||||||
|
del names_len
|
||||||
|
|
||||||
|
offset = align(offset, 4)
|
||||||
|
offset += 4
|
||||||
|
types_len = intstruct.unpack_from(data, offset)[0]
|
||||||
|
offset += 4
|
||||||
|
log.debug("building #%d types" % types_len)
|
||||||
|
for i in range(types_len):
|
||||||
|
dna_type_id = DNA_IO.read_data0(data, offset)
|
||||||
|
# None will be replaced by the DNAStruct, below
|
||||||
|
types.append(DNAStruct(dna_type_id))
|
||||||
|
offset += len(dna_type_id) + 1
|
||||||
|
|
||||||
|
offset = align(offset, 4)
|
||||||
|
offset += 4
|
||||||
|
log.debug("building #%d type-lengths" % types_len)
|
||||||
|
for i in range(types_len):
|
||||||
|
tLen = shortstruct.unpack_from(data, offset)[0]
|
||||||
|
offset = offset + 2
|
||||||
|
types[i].size = tLen
|
||||||
|
del types_len
|
||||||
|
|
||||||
|
offset = align(offset, 4)
|
||||||
|
offset += 4
|
||||||
|
|
||||||
|
structs_len = intstruct.unpack_from(data, offset)[0]
|
||||||
|
offset += 4
|
||||||
|
log.debug("building #%d structures" % structs_len)
|
||||||
|
for struct_index in range(structs_len):
|
||||||
|
d = shortstruct2.unpack_from(data, offset)
|
||||||
|
struct_type_index = d[0]
|
||||||
|
offset += 4
|
||||||
|
dna_struct = types[struct_type_index]
|
||||||
|
structs.append(dna_struct)
|
||||||
|
|
||||||
|
fields_len = d[1]
|
||||||
|
dna_offset = 0
|
||||||
|
|
||||||
|
for field_index in range(fields_len):
|
||||||
|
d2 = shortstruct2.unpack_from(data, offset)
|
||||||
|
field_type_index = d2[0]
|
||||||
|
field_name_index = d2[1]
|
||||||
|
offset += 4
|
||||||
|
dna_type = types[field_type_index]
|
||||||
|
dna_name = names[field_name_index]
|
||||||
|
if dna_name.is_pointer or dna_name.is_method_pointer:
|
||||||
|
dna_size = header.pointer_size * dna_name.array_size
|
||||||
|
else:
|
||||||
|
dna_size = dna_type.size * dna_name.array_size
|
||||||
|
|
||||||
|
dna_struct.fields.append(DNAField(dna_type, dna_name, dna_size, dna_offset))
|
||||||
|
dna_offset += dna_size
|
||||||
|
return structs
|
||||||
|
|
||||||
|
|
||||||
class BlendFileBlock:
|
class BlendFileBlock:
|
||||||
"""
|
"""
|
||||||
@@ -180,7 +267,7 @@ class BlendFileBlock:
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return ("<%s.%s (%s), size=%d at %s>" %
|
return ("<%s.%s (%s), size=%d at %s>" %
|
||||||
(self.__class__.__name__,
|
(self.__class__.__name__,
|
||||||
self.file.catalog.structs[self.sdna_index].dna_type_id.decode(),
|
self.file.structs[self.sdna_index].dna_type_id.decode(),
|
||||||
self.code.decode(),
|
self.code.decode(),
|
||||||
self.size,
|
self.size,
|
||||||
hex(self.addr_old),
|
hex(self.addr_old),
|
||||||
@@ -225,11 +312,11 @@ class BlendFileBlock:
|
|||||||
def refine_type(self, dna_type_id):
|
def refine_type(self, dna_type_id):
|
||||||
assert(type(dna_type_id) is bytes)
|
assert(type(dna_type_id) is bytes)
|
||||||
sdna_index_curr = self.sdna_index
|
sdna_index_curr = self.sdna_index
|
||||||
sdna_index_next = self.file.catalog.sdna_index_from_id(dna_type_id)
|
sdna_index_next = self.file.sdna_index_from_id(dna_type_id)
|
||||||
|
|
||||||
# never refine to a smaller type
|
# never refine to a smaller type
|
||||||
if (self.file.catalog.structs[sdna_index_curr].size >
|
if (self.file.structs[sdna_index_curr].size >
|
||||||
self.file.catalog.structs[sdna_index_next].size):
|
self.file.structs[sdna_index_next].size):
|
||||||
|
|
||||||
raise RuntimeError("cant refine to smaller type (%s -> %s)" %
|
raise RuntimeError("cant refine to smaller type (%s -> %s)" %
|
||||||
(dna_type_id, sdna_index_curr))
|
(dna_type_id, sdna_index_curr))
|
||||||
@@ -238,13 +325,13 @@ class BlendFileBlock:
|
|||||||
|
|
||||||
def get(self, path,
|
def get(self, path,
|
||||||
use_nil=True, use_str=True):
|
use_nil=True, use_str=True):
|
||||||
dna_struct = self.file.catalog.structs[self.sdna_index]
|
dna_struct = self.file.structs[self.sdna_index]
|
||||||
self.file.handle.seek(self.file_offset, os.SEEK_SET)
|
self.file.handle.seek(self.file_offset, os.SEEK_SET)
|
||||||
return dna_struct.field_get(self.file.header, self.file.handle, path,
|
return dna_struct.field_get(self.file.header, self.file.handle, path,
|
||||||
use_nil=use_nil, use_str=use_str)
|
use_nil=use_nil, use_str=use_str)
|
||||||
|
|
||||||
def set(self, path, value):
|
def set(self, path, value):
|
||||||
dna_struct = self.file.catalog.structs[self.sdna_index]
|
dna_struct = self.file.structs[self.sdna_index]
|
||||||
self.file.handle.seek(self.file_offset, os.SEEK_SET)
|
self.file.handle.seek(self.file_offset, os.SEEK_SET)
|
||||||
self.file.is_modified = True
|
self.file.is_modified = True
|
||||||
return dna_struct.field_set(
|
return dna_struct.field_set(
|
||||||
@@ -256,7 +343,7 @@ class BlendFileBlock:
|
|||||||
# avoid inline pointer casting
|
# avoid inline pointer casting
|
||||||
def get_pointer(self, path):
|
def get_pointer(self, path):
|
||||||
result = self.get(path)
|
result = self.get(path)
|
||||||
assert(self.file.catalog.structs[self.sdna_index].field_from_path(self.file.handle, path).dna_name.is_pointer)
|
assert(self.file.structs[self.sdna_index].field_from_path(self.file.handle, path).dna_name.is_pointer)
|
||||||
if result != 0:
|
if result != 0:
|
||||||
# possible (but unlikely)
|
# possible (but unlikely)
|
||||||
# that this fails and returns None
|
# that this fails and returns None
|
||||||
@@ -277,7 +364,7 @@ class BlendFileBlock:
|
|||||||
self.set(item, value)
|
self.set(item, value)
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
dna_struct = self.file.catalog.structs[self.sdna_index]
|
dna_struct = self.file.structs[self.sdna_index]
|
||||||
return (f.dna_name.name_short for f in dna_struct.fields)
|
return (f.dna_name.name_short for f in dna_struct.fields)
|
||||||
|
|
||||||
def values(self):
|
def values(self):
|
||||||
@@ -353,99 +440,6 @@ class BlendFileHeader:
|
|||||||
)))
|
)))
|
||||||
|
|
||||||
|
|
||||||
class DNACatalog:
|
|
||||||
"""
|
|
||||||
DNACatalog is a catalog of all information in the DNA1 file-block
|
|
||||||
"""
|
|
||||||
__slots__ = (
|
|
||||||
#
|
|
||||||
"names",
|
|
||||||
#
|
|
||||||
# DNAStruct[]
|
|
||||||
"types",
|
|
||||||
# DNAStruct[]
|
|
||||||
"structs",
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, header, block, handle):
|
|
||||||
log.debug("building DNA catalog")
|
|
||||||
shortstruct = DNA_IO.USHORT[header.endian_index]
|
|
||||||
shortstruct2 = struct.Struct(header.endian_str + b'HH')
|
|
||||||
intstruct = DNA_IO.UINT[header.endian_index]
|
|
||||||
data = handle.read(block.size)
|
|
||||||
self.names = []
|
|
||||||
self.types = []
|
|
||||||
self.structs = []
|
|
||||||
|
|
||||||
offset = 8
|
|
||||||
names_len = intstruct.unpack_from(data, offset)[0]
|
|
||||||
offset += 4
|
|
||||||
|
|
||||||
log.debug("building #%d names" % names_len)
|
|
||||||
for i in range(names_len):
|
|
||||||
tName = DNA_IO.read_data0(data, offset)
|
|
||||||
offset = offset + len(tName) + 1
|
|
||||||
self.names.append(DNAName(tName))
|
|
||||||
del names_len
|
|
||||||
|
|
||||||
offset = align(offset, 4)
|
|
||||||
offset += 4
|
|
||||||
types_len = intstruct.unpack_from(data, offset)[0]
|
|
||||||
offset += 4
|
|
||||||
log.debug("building #%d types" % types_len)
|
|
||||||
for i in range(types_len):
|
|
||||||
dna_type_id = DNA_IO.read_data0(data, offset)
|
|
||||||
# None will be replaced by the DNAStruct, below
|
|
||||||
self.types.append(DNAStruct(dna_type_id))
|
|
||||||
offset += len(dna_type_id) + 1
|
|
||||||
|
|
||||||
offset = align(offset, 4)
|
|
||||||
offset += 4
|
|
||||||
log.debug("building #%d type-lengths" % types_len)
|
|
||||||
for i in range(types_len):
|
|
||||||
tLen = shortstruct.unpack_from(data, offset)[0]
|
|
||||||
offset = offset + 2
|
|
||||||
self.types[i].size = tLen
|
|
||||||
del types_len
|
|
||||||
|
|
||||||
offset = align(offset, 4)
|
|
||||||
offset += 4
|
|
||||||
|
|
||||||
structs_len = intstruct.unpack_from(data, offset)[0]
|
|
||||||
offset += 4
|
|
||||||
log.debug("building #%d structures" % structs_len)
|
|
||||||
for struct_index in range(structs_len):
|
|
||||||
d = shortstruct2.unpack_from(data, offset)
|
|
||||||
struct_type_index = d[0]
|
|
||||||
offset += 4
|
|
||||||
dna_struct = self.types[struct_type_index]
|
|
||||||
self.structs.append(dna_struct)
|
|
||||||
|
|
||||||
fields_len = d[1]
|
|
||||||
dna_offset = 0
|
|
||||||
|
|
||||||
for field_index in range(fields_len):
|
|
||||||
d2 = shortstruct2.unpack_from(data, offset)
|
|
||||||
field_type_index = d2[0]
|
|
||||||
field_name_index = d2[1]
|
|
||||||
offset += 4
|
|
||||||
dna_type = self.types[field_type_index]
|
|
||||||
dna_name = self.names[field_name_index]
|
|
||||||
if dna_name.is_pointer or dna_name.is_method_pointer:
|
|
||||||
dna_size = header.pointer_size * dna_name.array_size
|
|
||||||
else:
|
|
||||||
dna_size = dna_type.size * dna_name.array_size
|
|
||||||
|
|
||||||
dna_struct.fields.append(DNAField(dna_type, dna_name, dna_size, dna_offset))
|
|
||||||
dna_offset += dna_size
|
|
||||||
|
|
||||||
def sdna_index_from_id(self, dna_type_id):
|
|
||||||
# TODO, use dict?
|
|
||||||
for i, dna_type in enumerate(self.structs):
|
|
||||||
if dna_type_id == dna_type.dna_type_id:
|
|
||||||
return i
|
|
||||||
raise KeyError("%r not found" % dna_type_id)
|
|
||||||
|
|
||||||
|
|
||||||
class DNAName:
|
class DNAName:
|
||||||
"""
|
"""
|
||||||
|
Reference in New Issue
Block a user