import struct, warnings try: import lz4 except ImportError: lz4 = None else: import lz4.block #old scheme for VERSION < 0.9 otherwise use lz4.block def decompress(data): (compression,) = struct.unpack(">L", data[4:8]) scheme = compression >> 27 size = compression & 0x07ffffff if scheme == 0: pass elif scheme == 1 and lz4: res = lz4.block.decompress(struct.pack("L", (scheme << 27) + (len(data) & 0x07ffffff)) if scheme == 0 : return data elif scheme == 1 and lz4: res = lz4.block.compress(data, mode='high_compression', compression=16, store_size=False) return hdr + res else: warnings.warn("Table failed to compress by unsupported compression scheme") return data def _entries(attrs, sameval): ak = 0 vals = [] lastv = 0 for k,v in attrs: if len(vals) and (k != ak + 1 or (sameval and v != lastv)) : yield (ak - len(vals) + 1, len(vals), vals) vals = [] ak = k vals.append(v) lastv = v yield (ak - len(vals) + 1, len(vals), vals) def entries(attributes, sameval = False): g = _entries(sorted(attributes.items(), key=lambda x:int(x[0])), sameval) return g def bininfo(num, size=1): if num == 0: return struct.pack(">4H", 0, 0, 0, 0) srange = 1; select = 0 while srange <= num: srange *= 2 select += 1 select -= 1 srange //= 2 srange *= size shift = num * size - srange return struct.pack(">4H", num, srange, select, shift) def num2tag(n): if n < 0x200000: return str(n) else: return struct.unpack('4s', struct.pack('>L', n))[0].replace(b'\000', b'').decode() def tag2num(n): try: return int(n) except ValueError: n = (n+" ")[:4] return struct.unpack('>L', n.encode('ascii'))[0]