Commit | Line | Data |
---|---|---|
a81dbb3f MW |
1 | #! /usr/bin/python |
2 | ||
3 | from sys import argv, exit | |
4 | from itertools import cycle, izip | |
5 | import re as RX | |
6 | ||
7 | def bad_usage(): | |
8 | exit('usage: split-pieces { scaf WD | qf WD/N|WD,WD,... } N N ...') | |
9 | ||
10 | ARGC = 1 | |
11 | def getarg(must = True): | |
12 | global ARGC | |
13 | if ARGC < len(argv): ARGC += 1; return argv[ARGC - 1] | |
14 | elif must: bad_usage() | |
15 | else: return None | |
16 | ||
17 | class ScafConvert (object): | |
18 | def __init__(me, piecewd): | |
19 | me.piecewd = piecewd | |
20 | me.fmt = '0x%%0%dx' % ((piecewd + 3)/4) | |
21 | me.mask = (1 << piecewd) - 1 | |
22 | @classmethod | |
23 | def parse(cls): | |
24 | return ScafConvert(int(getarg())) | |
25 | def hack(me, n): | |
26 | nn = [] | |
27 | while n: | |
28 | nn.append(me.fmt % (n&me.mask)) | |
29 | n >>= me.piecewd | |
30 | return nn | |
31 | def unhack(me, nn): | |
32 | return sum(n << i*me.piecewd for i, n in enumerate(nn)) | |
33 | ||
34 | class QfConvert (object): | |
35 | def __init__(me, p, wdseq): | |
36 | me.p = p | |
37 | me.wdseq = wdseq | |
38 | @classmethod | |
39 | def parse(cls): | |
40 | p = eval(getarg()) | |
41 | arg = getarg() | |
42 | if '/' in arg: | |
43 | wd, n = map(int, arg.split('/')) | |
44 | seq = [(wd*(i + 1) + n - 1)/n - (wd*i + n - 1)/n for i in xrange(n)] | |
45 | else: | |
46 | seq = map(int, arg.split(',')) | |
47 | print ";; piece widths = %r" % seq | |
48 | return QfConvert(p, seq) | |
49 | def hack(me, n): | |
50 | if 2*n >= me.p: n -= p | |
51 | nn = [] | |
52 | wds = cycle(me.wdseq) | |
53 | while n: | |
54 | wd = wds.next() | |
55 | lim = 1 << wd; m = lim - 1 | |
56 | d = n&m; n >>= wd | |
57 | if d >= lim/2: d -= lim; n += 1 | |
58 | nn.append(str(d)) | |
59 | return nn | |
60 | def unhack(me, nn): | |
61 | a = o = 0 | |
62 | for n, w in izip(nn, cycle(me.wdseq)): | |
63 | a += n << o | |
64 | o += w | |
65 | if a < 0: a += me.p | |
66 | return a | |
67 | ||
68 | R_split = RX.compile(r',\s*|\s+') | |
69 | def spliteval(arg): return map(eval, R_split.split(arg.strip())) | |
70 | ||
71 | convmap = { 'scaf': ScafConvert, | |
72 | 'unscaf': ScafConvert, | |
73 | 'qf': QfConvert, | |
74 | 'unqf': QfConvert } | |
75 | op = getarg() | |
76 | cvt = convmap[op].parse() | |
77 | if op.startswith('un'): prepare, conv, format = spliteval, cvt.unhack, str | |
78 | else: prepare, conv, format = eval, cvt.hack, lambda vv: ', '.join(vv) | |
79 | ||
80 | while True: | |
81 | val = getarg(must = False) | |
82 | if val is None: break | |
83 | print format(conv(prepare(val))) |