| #!/usr/bin/env python3 |
| import io |
| import json |
| import re |
| import sys |
| |
| |
| def extract_numbers(s): |
| """ |
| >>> extract_numbers("CLK_HROW_WR10END2_3") |
| ('CLK_HROW_WR', 10, 'END', 2, '_', 3) |
| >>> extract_numbers("VBRK_WR1END2") |
| ('VBRK_WR', 1, 'END', 2) |
| """ |
| bits = [] |
| for m in re.finditer("([^0-9]*)([0-9]*)", s): |
| if m.group(1): |
| bits.append(m.group(1)) |
| if m.group(2): |
| bits.append(int(m.group(2))) |
| return tuple(bits) |
| |
| |
| def sort(data): |
| # FIXME: We assume that a list is a tileconn.json format... |
| if isinstance(data, list) and len(data) > 0 and 'wire_pairs' in data[0]: |
| for o in data: |
| o['wire_pairs'].sort( |
| key=lambda o: (extract_numbers(o[0]), extract_numbers(o[1]))) |
| |
| data.sort(key=lambda o: (o['tile_types'], o['grid_deltas'])) |
| else: |
| |
| def walker(o, f): |
| if isinstance(o, dict): |
| for i in o.values(): |
| walker(i, f) |
| elif isinstance(o, list): |
| for i in o: |
| walker(i, f) |
| f(o) |
| |
| def f(o): |
| if isinstance(o, list): |
| if len(o) > 2: |
| strings = all(isinstance(x, str) for x in o) |
| if strings: |
| o.sort() |
| |
| walker(data, f) |
| |
| |
| def pprint(f, data): |
| detach = False |
| if not isinstance(f, io.TextIOBase): |
| detach = True |
| f = io.TextIOWrapper(f) |
| sort(data) |
| json.dump(data, f, sort_keys=True, indent=4) |
| f.write('\n') |
| f.flush() |
| if detach: |
| f.detach() |
| |
| |
| if __name__ == "__main__": |
| if len(sys.argv) == 1: |
| import doctest |
| doctest.testmod() |
| else: |
| assert len(sys.argv) == 2 |
| d = json.load(open(sys.argv[1])) |
| pprint(sys.stdout, d) |