-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbin_ops.py
155 lines (107 loc) · 3.52 KB
/
bin_ops.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import struct
import binascii
ENCODING_READ = 'utf-8-sig'
ENCODING_WRITE = 'utf-8'
# Format
class TypeFormat:
SByte = '<b'
Byte = '<B'
Int16 = '<h'
UInt16 = '<H'
Int32 = '<i'
UInt32 = '<I'
Int64 = '<l'
UInt64 = '<L'
Single = '<f'
Double = '<d'
def roundToMultiple(numToRound, multiple):
return (numToRound + multiple - 1) // multiple * multiple
def readByte(file, print_hex=False):
numberBin = file.read(1)
number = struct.unpack(TypeFormat.Byte, numberBin)[0]
if print_hex:
print(" ", numberBin, binascii.hexlify(numberBin))
return number
def writeByte(number):
bytesBin = struct.pack(TypeFormat.Byte, number)
return bytesBin
def readUInt16(file):
numberBin = file.read(2)
number = struct.unpack(TypeFormat.UInt16, numberBin)[0]
return number
def writeUInt16(number):
uInt16 = struct.pack(TypeFormat.UInt16, number)
return uInt16
def readInt16(file):
numberBin = file.read(2)
number = struct.unpack(TypeFormat.Int16, numberBin)[0]
return number
def writeInt16(number):
int16 = struct.pack(TypeFormat.Int16, number)
return int16
def readUInt32(file, print_hex=False):
numberBin = file.read(4)
number = struct.unpack(TypeFormat.UInt32, numberBin)[0]
if print_hex:
print(" ", numberBin, binascii.hexlify(numberBin))
return number
def writeUInt32(number):
uInt32 = struct.pack(TypeFormat.UInt32, number)
return uInt32
def readSingle(file, round_to=None, print_hex=False):
numberBin = file.read(4)
single = struct.unpack(TypeFormat.Single, numberBin)[0]
if print_hex:
print(" ", numberBin, binascii.hexlify(numberBin))
if round_to is not None:
single = round(single, round_to)
return single
def writeSingle(number):
single = struct.pack(TypeFormat.Single, number)
return single
def readString(file):
# Read the byte as an integer indicating the string length
byte = file.read(1) + b'\x00'
string_length = struct.unpack(TypeFormat.UInt16, byte)[0]
# print(string_length, binascii.hexlify(byte))
# Handle edge case where a "01" follows the string length. Maybe this is a bone visibility flag?
byte = file.read(1)
if byte != b'\x01':
file.seek(file.tell() - 1)
else:
print("Handled edge case '01' after string length")
# Read the string of the indicated length
string = ""
for i in range(string_length):
# print(string, binascii.hexlify(byte))
byte = file.read(1)
if byte == b'\x00':
print("WARNING: String contains null character. This should never happen!")
file.seek(file.tell() - 1)
break
char = decodeBytes(byte)
string += char
# print(string)
return string
def writeString(string):
# String Length
byteString = encodeString(string)
return byteString
def decodeBytes(bytes):
# print(bytes)
return bytes.decode(ENCODING_READ)
def encodeString(string):
# print(string)
return string.encode(ENCODING_WRITE)
def hasHeader(fileformat='.xps'):
return fileformat == '.xps'
def hasTangentVersion(verMayor, verMinor, hasHeader=True):
return (verMinor <= 12 and verMayor <= 2) if hasHeader else True
def hasVariableWeights(verMayor, verMinor, hasHeader=True):
return (verMayor >= 3) if hasHeader else False
def check_and_return(file, length):
numberBin = file.read(length)
file.seek(file.tell() - length)
return numberBin
def move_by(file, length):
file.seek(file.tell() + length)