cleanup string handling
This commit is contained in:
104
blendfile.py
104
blendfile.py
@@ -55,13 +55,13 @@ FILE_BUFFER_SIZE = 1024 * 1024
|
|||||||
# open a filename
|
# open a filename
|
||||||
# determine if the file is compressed
|
# determine if the file is compressed
|
||||||
# and returns a handle
|
# and returns a handle
|
||||||
def openBlendFile(filename, access="rb"):
|
def open_blend(filename, access="rb"):
|
||||||
"""Opens a blend file for reading or writing pending on the access
|
"""Opens a blend file for reading or writing pending on the access
|
||||||
supports 2 kind of blend files. Uncompressed and compressed.
|
supports 2 kind of blend files. Uncompressed and compressed.
|
||||||
Known issue: does not support packaged blend files
|
Known issue: does not support packaged blend files
|
||||||
"""
|
"""
|
||||||
handle = open(filename, access)
|
handle = open(filename, access)
|
||||||
magic = ReadString(handle, 7)
|
magic = read_string(handle, 7)
|
||||||
if magic == "BLENDER":
|
if magic == "BLENDER":
|
||||||
log.debug("normal blendfile detected")
|
log.debug("normal blendfile detected")
|
||||||
handle.seek(0, os.SEEK_SET)
|
handle.seek(0, os.SEEK_SET)
|
||||||
@@ -89,29 +89,10 @@ def openBlendFile(filename, access="rb"):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def closeBlendFile(afile):
|
|
||||||
"""close the blend file
|
|
||||||
writes the blend file to disk if changes has happened"""
|
|
||||||
handle = afile.handle
|
|
||||||
if afile.is_compressed:
|
|
||||||
log.debug("close compressed blend file")
|
|
||||||
handle.seek(os.SEEK_SET, 0)
|
|
||||||
log.debug("compressing started")
|
|
||||||
fs = gzip.open(afile.filepath_orig, "wb")
|
|
||||||
data = handle.read(FILE_BUFFER_SIZE)
|
|
||||||
while data:
|
|
||||||
fs.write(data)
|
|
||||||
data = handle.read(FILE_BUFFER_SIZE)
|
|
||||||
fs.close()
|
|
||||||
log.debug("compressing finished")
|
|
||||||
|
|
||||||
handle.close()
|
|
||||||
|
|
||||||
|
|
||||||
######################################################
|
######################################################
|
||||||
# Write a string to the file.
|
# Write a string to the file.
|
||||||
######################################################
|
######################################################
|
||||||
def WriteString(handle, astring, fieldlen):
|
def write_string(handle, astring, fieldlen):
|
||||||
assert(isinstance(astring, str))
|
assert(isinstance(astring, str))
|
||||||
stringw = ""
|
stringw = ""
|
||||||
if len(astring) >= fieldlen:
|
if len(astring) >= fieldlen:
|
||||||
@@ -121,7 +102,7 @@ def WriteString(handle, astring, fieldlen):
|
|||||||
handle.write(stringw.encode('utf-8'))
|
handle.write(stringw.encode('utf-8'))
|
||||||
|
|
||||||
|
|
||||||
def WriteBytes(handle, astring, fieldlen):
|
def write_bytes(handle, astring, fieldlen):
|
||||||
assert(isinstance(astring, (bytes, bytearray)))
|
assert(isinstance(astring, (bytes, bytearray)))
|
||||||
stringw = b''
|
stringw = b''
|
||||||
if len(astring) >= fieldlen:
|
if len(astring) >= fieldlen:
|
||||||
@@ -133,37 +114,37 @@ def WriteBytes(handle, astring, fieldlen):
|
|||||||
handle.write(stringw)
|
handle.write(stringw)
|
||||||
|
|
||||||
|
|
||||||
######################################################
|
def _string_struct(length):
|
||||||
# ReadString reads a String of given length from a file handle
|
if length < len(_string_struct.STRING):
|
||||||
######################################################
|
st = _string_struct.STRING[length]
|
||||||
STRING = []
|
else:
|
||||||
for i in range(0, 2048):
|
st = struct.Struct("%ds" % length)
|
||||||
STRING.append(struct.Struct(str(i) + "s"))
|
return st
|
||||||
|
_string_struct.STRING = [struct.Struct("%ds" % i) for i in range(0, 2048)]
|
||||||
|
|
||||||
|
|
||||||
def ReadString(handle, length):
|
def read_string(handle, length):
|
||||||
st = STRING[length]
|
"""
|
||||||
return st.unpack(handle.read(st.size))[0].decode("iso-8859-1")
|
read_string reads a String of given length from a file handle
|
||||||
|
"""
|
||||||
######################################################
|
st = _string_struct(length)
|
||||||
# ReadString0 reads a zero terminating String from a file handle
|
return st.unpack(handle.read(st.size))[0].decode('utf-8')
|
||||||
######################################################
|
|
||||||
ZEROTESTER = 0
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
ZEROTESTER = "\0"
|
|
||||||
|
|
||||||
|
|
||||||
def ReadString0(data, offset):
|
def read_string0(data, offset):
|
||||||
|
"""
|
||||||
|
read_string0 reads a zero terminating String from a file handle
|
||||||
|
"""
|
||||||
add = 0
|
add = 0
|
||||||
|
|
||||||
while data[offset+add] != ZEROTESTER:
|
# TODO, faster method!
|
||||||
|
while data[offset + add] != 0:
|
||||||
add += 1
|
add += 1
|
||||||
if add < len(STRING):
|
|
||||||
st = STRING[add]
|
st = _string_struct(add)
|
||||||
S = st.unpack_from(data, offset)[0].decode("iso-8859-1")
|
|
||||||
else:
|
result = st.unpack_from(data, offset)[0].decode('utf-8')
|
||||||
S = struct.Struct(str(add) + "s").unpack_from(data, offset)[0].decode("iso-8859-1")
|
return result
|
||||||
return S
|
|
||||||
|
|
||||||
######################################################
|
######################################################
|
||||||
# ReadUShort reads an unsigned short from a file handle
|
# ReadUShort reads an unsigned short from a file handle
|
||||||
@@ -290,10 +271,27 @@ class BlendFile:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
"""
|
||||||
|
Close the blend file
|
||||||
|
writes the blend file to disk if changes has happened
|
||||||
|
"""
|
||||||
if not self.is_modified:
|
if not self.is_modified:
|
||||||
self.handle.close()
|
self.handle.close()
|
||||||
else:
|
else:
|
||||||
closeBlendFile(self)
|
handle = self.handle
|
||||||
|
if self.is_compressed:
|
||||||
|
log.debug("close compressed blend file")
|
||||||
|
handle.seek(os.SEEK_SET, 0)
|
||||||
|
log.debug("compressing started")
|
||||||
|
fs = gzip.open(self.filepath_orig, "wb")
|
||||||
|
data = handle.read(FILE_BUFFER_SIZE)
|
||||||
|
while data:
|
||||||
|
fs.write(data)
|
||||||
|
data = handle.read(FILE_BUFFER_SIZE)
|
||||||
|
fs.close()
|
||||||
|
log.debug("compressing finished")
|
||||||
|
|
||||||
|
handle.close()
|
||||||
|
|
||||||
|
|
||||||
class BlendFileBlock:
|
class BlendFileBlock:
|
||||||
@@ -449,7 +447,7 @@ class DNACatalog:
|
|||||||
|
|
||||||
log.debug("building #%d names" % names_len)
|
log.debug("building #%d names" % names_len)
|
||||||
for i in range(names_len):
|
for i in range(names_len):
|
||||||
tName = ReadString0(data, offset)
|
tName = read_string0(data, offset)
|
||||||
offset = offset + len(tName) + 1
|
offset = offset + len(tName) + 1
|
||||||
self.names.append(DNAName(tName))
|
self.names.append(DNAName(tName))
|
||||||
del names_len
|
del names_len
|
||||||
@@ -460,7 +458,7 @@ class DNACatalog:
|
|||||||
offset += 4
|
offset += 4
|
||||||
log.debug("building #"+str(types_len)+" types")
|
log.debug("building #"+str(types_len)+" types")
|
||||||
for i in range(types_len):
|
for i in range(types_len):
|
||||||
tType = ReadString0(data, offset)
|
tType = read_string0(data, offset)
|
||||||
self.types.append([tType, 0, None])
|
self.types.append([tType, 0, None])
|
||||||
offset += len(tType) + 1
|
offset += len(tType) + 1
|
||||||
|
|
||||||
@@ -598,7 +596,7 @@ class DNAStructure:
|
|||||||
elif ftype[0] == "float":
|
elif ftype[0] == "float":
|
||||||
return ReadFloat(handle, header)
|
return ReadFloat(handle, header)
|
||||||
elif ftype[0] == "char":
|
elif ftype[0] == "char":
|
||||||
return ReadString(handle, fname.array_size)
|
return read_string(handle, fname.array_size)
|
||||||
else:
|
else:
|
||||||
return ftype[2].field_get(header, handle, rest)
|
return ftype[2].field_get(header, handle, rest)
|
||||||
|
|
||||||
@@ -620,9 +618,9 @@ class DNAStructure:
|
|||||||
if len(rest) == 0:
|
if len(rest) == 0:
|
||||||
if ftype[0] == "char":
|
if ftype[0] == "char":
|
||||||
if type(value) is str:
|
if type(value) is str:
|
||||||
return WriteString(handle, value, fname.array_size)
|
return write_string(handle, value, fname.array_size)
|
||||||
else:
|
else:
|
||||||
return WriteBytes(handle, value, fname.array_size)
|
return write_bytes(handle, value, fname.array_size)
|
||||||
else:
|
else:
|
||||||
return ftype[2].field_set(header, handle, rest, value)
|
return ftype[2].field_set(header, handle, rest, value)
|
||||||
else:
|
else:
|
||||||
|
Reference in New Issue
Block a user