1 from struct import pack, unpack, calcsize
3 class fmterror(Exception):
6 class eomerror(fmterror):
19 while (c < 7) and (b & (1 << (6 - c))):
21 if c == 0 or c == 7: raise fmterror("invalid utf8 start-byte")
22 iacc = acc = b & ((1 << (6 - c)) - 1)
25 if i >= len(bs): raise fmterror("unterminated utf8 compound")
28 if b & 0xc0 != 0x80: raise fmterror("invalid utf8 continuation byte")
29 acc = (acc << 6) | b & 0x3f
31 if iacc == 0 and ic != 2 and acc != 0: raise fmterror("invalid utf8 compound")
40 ret.extend(b"\xc0\x80")
44 ret.append(0xc0 | ((c & 0x7c0) >> 6))
45 ret.append(0x80 | (c & 0x03f))
46 elif 2048 <= c < 65536:
47 ret.append(0xe0 | ((c & 0xf000) >> 12))
48 ret.append(0x80 | ((c & 0x0fc0) >> 6))
49 ret.append(0x80 | (c & 0x003f))
51 raise fmterror("non-BMP unicode not supported by Java")
54 class decoder(object):
55 def destruct(self, fmt):
56 return unpack(fmt, self.splice(calcsize(fmt)))
62 return self.destruct(">b")[0]
64 return self.destruct(">B")[0]
66 return self.destruct(">h")[0]
68 return self.destruct(">H")[0]
70 return self.destruct(">i")[0]
72 return self.destruct(">I")[0]
74 return self.destruct(">q")[0]
76 return self.destruct(">Q")[0]
78 return self.destruct(">f")[0]
80 return self.destruct(">d")[0]
82 class decstream(decoder):
83 def __init__(self, bk):
85 self.buf = bytearray()
90 ret = self.bk.read(1024)
97 return self.bk.tell() - len(self.buf)
99 def splice(self, ln=-1):
105 self.buf = bytearray()
110 rl = max(ln - len(buf), 1024)
111 ret = self.bk.read(rl)
113 raise eomerror("unexpected end-of-file")
116 return bytes(buf[:ln])
119 if ln < len(self.buf):
120 self.buf = self.buf[ln:]
123 self.buf = bytearray()
124 if hasattr(self.bk, "seek"):
125 self.bk.seek(ln - 1, 1)
126 if len(self.bk.read(1)) != 1:
127 raise eomerror("unexpected end-of-file")
132 raise eomerror("unexpected end-of-file")
139 p2 = buf.find(b'\0', p)
141 self.buf = buf[p2 + 1:]
142 return str(buf[:p2], "utf-8")
143 ret = self.bk.read(1024)
146 raise eomerror("unexpected end-of-file")
147 raise fmterror("no string terminator found")
157 def __exit__(self, *excinfo):
161 class decbuf(decoder):
162 def __init__(self, data):
167 return len(self.data) - self.offset
170 return self.offset >= len(self.data)
172 def splice(self, ln=-1):
174 ret = self.data[self.offset:]
175 self.offset = len(self.data)
178 if self.offset + ln > len(self.data):
179 raise eomerror("out of data to decode")
180 ret = self.data[self.offset:self.offset + ln]
185 p = self.data.find(b'\0', self.offset)
187 if self.offset == len(self.data):
188 raise eomerror("out of data to decode")
189 raise fmterror("no string terminator found")
190 ret = str(self.data[self.offset:p], "utf-8")
194 class encoder(object):
195 def enstruct(self, fmt, *args):
196 self.extend(pack(fmt, *args))
200 self.enstruct(">b", val)
202 def uint8(self, val):
203 self.enstruct(">B", val)
205 def int16(self, val):
206 self.enstruct(">h", val)
208 def uint16(self, val):
209 self.enstruct(">H", val)
211 def int32(self, val):
212 self.enstruct(">i", val)
214 def uint32(self, val):
215 self.enstruct(">I", val)
217 def int64(self, val):
218 self.enstruct(">q", val)
220 def uint64(self, val):
221 self.enstruct(">Q", val)
223 def float32(self, val):
224 self.enstruct(">f", val)
226 def float64(self, val):
227 self.enstruct(">d", val)
231 if val.find('\0') >= 0:
232 raise ValueError("encoded strings must not contain NULs")
233 self.extend(val.encode("utf-8"))
237 def ttol(self, val, term=False):
239 if isinstance(obj, int):
243 elif 0 <= obj < 65536:
249 elif isinstance(obj, str):
252 elif isinstance(obj, utils.coord):
255 elif isinstance(obj, utils.color):
258 elif isinstance(obj, list):
261 elif isinstance(obj, float):
262 self.uint8(T_FLOAT32)
266 elif isinstance(obj, collections.ByteString):
271 self.uint8(0x80).int32(len(obj))
274 raise ValueError("unexpected type in tto-list: %s" % type(obj))
279 class encstream(encoder):
280 def __init__(self, bk):
283 def extend(self, data):
293 def __exit__(self, *excinfo):
297 class encbuf(encoder, bytearray):
298 def extend(self, data):
299 bytearray.extend(self, data)