Skip to content

Commit

Permalink
Added better error handling for parsing strings and a setting to chan…
Browse files Browse the repository at this point in the history
…ge default encoding
  • Loading branch information
tw1lac committed Nov 5, 2023
1 parent f1c4d63 commit 95f0370
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 4 deletions.
11 changes: 11 additions & 0 deletions export_mdl/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,14 @@ def get_team_glow(teamGlowIndex):
'BROWN': get_team_glow(11),
'BLACK': get_team_glow(12)
}

ENCODINGS = {
'LATIN_1': 'latin-1',
'UTF_8': 'utf-8',
'UTF_16': 'utf-16',
'UTF_32': 'utf-32',
'ASCII': 'ascii',
'BIG5': 'big5',
'EUC_KR': 'euc_kr',
'EUC_JP': 'euc_jp',
}
23 changes: 19 additions & 4 deletions export_mdl/import_stuff/mdx_parser/binary_reader.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,41 @@
import struct
from typing import Tuple, List

import bpy

from export_mdl import War3Preferences, constants


class Reader:
def __init__(self, data: bytes):
self.__data: bytes = data
self.offset = 0
preferences: War3Preferences = bpy.context.preferences.addons.get('export_mdl').preferences
self.default_enc = constants.ENCODINGS[preferences.defaultEncoding]

def getf(self, value_format: str) -> Tuple:
size = struct.calcsize(value_format)
self.offset += size
return struct.unpack_from(value_format, self.__data, self.offset - size)

def gets(self, size: int) -> Tuple:
def gets(self, size: int) -> str:
self.offset += size
# return struct.unpack_from('<{}s'.format(size), self.__data, self.offset - size)[0].split(b'\x00')[0].decode(encoding='mbcs')
string_struct = struct.unpack_from('<{}s'.format(size), self.__data, self.offset - size)[0].split(b'\x00')[0]
string_struct: bytes = struct.unpack_from('<{}s'.format(size), self.__data, self.offset - size)[0].split(b'\x00')[0]
try:
return string_struct.decode(encoding='utf-8')
return string_struct.decode(encoding=self.default_enc)
except UnicodeDecodeError:
return string_struct.decode(encoding='utf-16')
for enc in constants.ENCODINGS.values():
string = self.try_get_encoded_string(string_struct, enc)
if string is not None:
return string
return str(string_struct)

def try_get_encoded_string(self, string_struct: bytes, encoding: str):
try:
return string_struct.decode(encoding=encoding)
except UnicodeError:
return None

def getid(self, required_chunks_id: Tuple[str, ...], debug=True):
self.offset += 4
Expand Down
15 changes: 15 additions & 0 deletions export_mdl/properties/War3Preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,24 @@ class War3Preferences(bpy.types.AddonPreferences):
name='Image Extension',
default='png'
)
defaultEncoding: bpy.props.EnumProperty(
name='Default Encoding',
items=[
('LATIN_1', 'latin-1', ""),
('UTF_8', 'utf-8', ""),
('UTF_16', 'utf-16', ""),
('UTF_32', 'utf-32', ""),
('ASCII', 'ascii', ""),
('BIG5', 'big5 (CH)', ""),
('EUC_KR', 'euc_kr (KR)', ""),
('EUC_JP', 'euc_jp (JP)', ""),
],
default='LATIN_1'
)

def draw(self, context):
layout = self.layout
layout.prop(self, 'resourceFolder')
layout.prop(self, 'alternativeResourceFolder')
layout.prop(self, 'textureExtension')
layout.prop(self, 'defaultEncoding')

0 comments on commit 95f0370

Please sign in to comment.