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