• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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