1import struct, warnings 2 3try: 4 import lz4 5except ImportError: 6 lz4 = None 7else: 8 import lz4.block 9 10# old scheme for VERSION < 0.9 otherwise use lz4.block 11 12 13def decompress(data): 14 (compression,) = struct.unpack(">L", data[4:8]) 15 scheme = compression >> 27 16 size = compression & 0x07FFFFFF 17 if scheme == 0: 18 pass 19 elif scheme == 1 and lz4: 20 res = lz4.block.decompress(struct.pack("<L", size) + data[8:]) 21 if len(res) != size: 22 warnings.warn("Table decompression failed.") 23 else: 24 data = res 25 else: 26 warnings.warn("Table is compressed with an unsupported compression scheme") 27 return (data, scheme) 28 29 30def compress(scheme, data): 31 hdr = data[:4] + struct.pack(">L", (scheme << 27) + (len(data) & 0x07FFFFFF)) 32 if scheme == 0: 33 return data 34 elif scheme == 1 and lz4: 35 res = lz4.block.compress( 36 data, mode="high_compression", compression=16, store_size=False 37 ) 38 return hdr + res 39 else: 40 warnings.warn("Table failed to compress by unsupported compression scheme") 41 return data 42 43 44def _entries(attrs, sameval): 45 ak = 0 46 vals = [] 47 lastv = 0 48 for k, v in attrs: 49 if len(vals) and (k != ak + 1 or (sameval and v != lastv)): 50 yield (ak - len(vals) + 1, len(vals), vals) 51 vals = [] 52 ak = k 53 vals.append(v) 54 lastv = v 55 yield (ak - len(vals) + 1, len(vals), vals) 56 57 58def entries(attributes, sameval=False): 59 g = _entries(sorted(attributes.items(), key=lambda x: int(x[0])), sameval) 60 return g 61 62 63def bininfo(num, size=1): 64 if num == 0: 65 return struct.pack(">4H", 0, 0, 0, 0) 66 srange = 1 67 select = 0 68 while srange <= num: 69 srange *= 2 70 select += 1 71 select -= 1 72 srange //= 2 73 srange *= size 74 shift = num * size - srange 75 return struct.pack(">4H", num, srange, select, shift) 76 77 78def num2tag(n): 79 if n < 0x200000: 80 return str(n) 81 else: 82 return ( 83 struct.unpack("4s", struct.pack(">L", n))[0].replace(b"\000", b"").decode() 84 ) 85 86 87def tag2num(n): 88 try: 89 return int(n) 90 except ValueError: 91 n = (n + " ")[:4] 92 return struct.unpack(">L", n.encode("ascii"))[0] 93