git repos / blockattack-game

blame: source/misc/embedded_libs/fmt-8.1.1/support/printable.py

normal view · raw

f8deb5b9 Poul Sander 2022-01-15 13:55 1
#!/usr/bin/env python3
f8deb5b9 Poul Sander 2022-01-15 13:55 2
f8deb5b9 Poul Sander 2022-01-15 13:55 3
# This script is based on
f8deb5b9 Poul Sander 2022-01-15 13:55 4
# https://github.com/rust-lang/rust/blob/master/library/core/src/unicode/printable.py
f8deb5b9 Poul Sander 2022-01-15 13:55 5
# distributed under https://github.com/rust-lang/rust/blob/master/LICENSE-MIT.
f8deb5b9 Poul Sander 2022-01-15 13:55 6
f8deb5b9 Poul Sander 2022-01-15 13:55 7
# This script uses the following Unicode tables:
f8deb5b9 Poul Sander 2022-01-15 13:55 8
# - UnicodeData.txt
f8deb5b9 Poul Sander 2022-01-15 13:55 9
f8deb5b9 Poul Sander 2022-01-15 13:55 10
f8deb5b9 Poul Sander 2022-01-15 13:55 11
from collections import namedtuple
f8deb5b9 Poul Sander 2022-01-15 13:55 12
import csv
f8deb5b9 Poul Sander 2022-01-15 13:55 13
import os
f8deb5b9 Poul Sander 2022-01-15 13:55 14
import subprocess
f8deb5b9 Poul Sander 2022-01-15 13:55 15
f8deb5b9 Poul Sander 2022-01-15 13:55 16
NUM_CODEPOINTS=0x110000
f8deb5b9 Poul Sander 2022-01-15 13:55 17
f8deb5b9 Poul Sander 2022-01-15 13:55 18
def to_ranges(iter):
f8deb5b9 Poul Sander 2022-01-15 13:55 19
    current = None
f8deb5b9 Poul Sander 2022-01-15 13:55 20
    for i in iter:
f8deb5b9 Poul Sander 2022-01-15 13:55 21
        if current is None or i != current[1] or i in (0x10000, 0x20000):
f8deb5b9 Poul Sander 2022-01-15 13:55 22
            if current is not None:
f8deb5b9 Poul Sander 2022-01-15 13:55 23
                yield tuple(current)
f8deb5b9 Poul Sander 2022-01-15 13:55 24
            current = [i, i + 1]
f8deb5b9 Poul Sander 2022-01-15 13:55 25
        else:
f8deb5b9 Poul Sander 2022-01-15 13:55 26
            current[1] += 1
f8deb5b9 Poul Sander 2022-01-15 13:55 27
    if current is not None:
f8deb5b9 Poul Sander 2022-01-15 13:55 28
        yield tuple(current)
f8deb5b9 Poul Sander 2022-01-15 13:55 29
f8deb5b9 Poul Sander 2022-01-15 13:55 30
def get_escaped(codepoints):
f8deb5b9 Poul Sander 2022-01-15 13:55 31
    for c in codepoints:
f8deb5b9 Poul Sander 2022-01-15 13:55 32
        if (c.class_ or "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and c.value != ord(' '):
f8deb5b9 Poul Sander 2022-01-15 13:55 33
            yield c.value
f8deb5b9 Poul Sander 2022-01-15 13:55 34
f8deb5b9 Poul Sander 2022-01-15 13:55 35
def get_file(f):
f8deb5b9 Poul Sander 2022-01-15 13:55 36
    try:
f8deb5b9 Poul Sander 2022-01-15 13:55 37
        return open(os.path.basename(f))
f8deb5b9 Poul Sander 2022-01-15 13:55 38
    except FileNotFoundError:
f8deb5b9 Poul Sander 2022-01-15 13:55 39
        subprocess.run(["curl", "-O", f], check=True)
f8deb5b9 Poul Sander 2022-01-15 13:55 40
        return open(os.path.basename(f))
f8deb5b9 Poul Sander 2022-01-15 13:55 41
f8deb5b9 Poul Sander 2022-01-15 13:55 42
Codepoint = namedtuple('Codepoint', 'value class_')
f8deb5b9 Poul Sander 2022-01-15 13:55 43
f8deb5b9 Poul Sander 2022-01-15 13:55 44
def get_codepoints(f):
f8deb5b9 Poul Sander 2022-01-15 13:55 45
    r = csv.reader(f, delimiter=";")
f8deb5b9 Poul Sander 2022-01-15 13:55 46
    prev_codepoint = 0
f8deb5b9 Poul Sander 2022-01-15 13:55 47
    class_first = None
f8deb5b9 Poul Sander 2022-01-15 13:55 48
    for row in r:
f8deb5b9 Poul Sander 2022-01-15 13:55 49
        codepoint = int(row[0], 16)
f8deb5b9 Poul Sander 2022-01-15 13:55 50
        name = row[1]
f8deb5b9 Poul Sander 2022-01-15 13:55 51
        class_ = row[2]
f8deb5b9 Poul Sander 2022-01-15 13:55 52
f8deb5b9 Poul Sander 2022-01-15 13:55 53
        if class_first is not None:
f8deb5b9 Poul Sander 2022-01-15 13:55 54
            if not name.endswith("Last>"):
f8deb5b9 Poul Sander 2022-01-15 13:55 55
                raise ValueError("Missing Last after First")
f8deb5b9 Poul Sander 2022-01-15 13:55 56
f8deb5b9 Poul Sander 2022-01-15 13:55 57
        for c in range(prev_codepoint + 1, codepoint):
f8deb5b9 Poul Sander 2022-01-15 13:55 58
            yield Codepoint(c, class_first)
f8deb5b9 Poul Sander 2022-01-15 13:55 59
f8deb5b9 Poul Sander 2022-01-15 13:55 60
        class_first = None
f8deb5b9 Poul Sander 2022-01-15 13:55 61
        if name.endswith("First>"):
f8deb5b9 Poul Sander 2022-01-15 13:55 62
            class_first = class_
f8deb5b9 Poul Sander 2022-01-15 13:55 63
f8deb5b9 Poul Sander 2022-01-15 13:55 64
        yield Codepoint(codepoint, class_)
f8deb5b9 Poul Sander 2022-01-15 13:55 65
        prev_codepoint = codepoint
f8deb5b9 Poul Sander 2022-01-15 13:55 66
f8deb5b9 Poul Sander 2022-01-15 13:55 67
    if class_first is not None:
f8deb5b9 Poul Sander 2022-01-15 13:55 68
        raise ValueError("Missing Last after First")
f8deb5b9 Poul Sander 2022-01-15 13:55 69
f8deb5b9 Poul Sander 2022-01-15 13:55 70
    for c in range(prev_codepoint + 1, NUM_CODEPOINTS):
f8deb5b9 Poul Sander 2022-01-15 13:55 71
        yield Codepoint(c, None)
f8deb5b9 Poul Sander 2022-01-15 13:55 72
f8deb5b9 Poul Sander 2022-01-15 13:55 73
def compress_singletons(singletons):
f8deb5b9 Poul Sander 2022-01-15 13:55 74
    uppers = [] # (upper, # items in lowers)
f8deb5b9 Poul Sander 2022-01-15 13:55 75
    lowers = []
f8deb5b9 Poul Sander 2022-01-15 13:55 76
f8deb5b9 Poul Sander 2022-01-15 13:55 77
    for i in singletons:
f8deb5b9 Poul Sander 2022-01-15 13:55 78
        upper = i >> 8
f8deb5b9 Poul Sander 2022-01-15 13:55 79
        lower = i & 0xff
f8deb5b9 Poul Sander 2022-01-15 13:55 80
        if len(uppers) == 0 or uppers[-1][0] != upper:
f8deb5b9 Poul Sander 2022-01-15 13:55 81
            uppers.append((upper, 1))
f8deb5b9 Poul Sander 2022-01-15 13:55 82
        else:
f8deb5b9 Poul Sander 2022-01-15 13:55 83
            upper, count = uppers[-1]
f8deb5b9 Poul Sander 2022-01-15 13:55 84
            uppers[-1] = upper, count + 1
f8deb5b9 Poul Sander 2022-01-15 13:55 85
        lowers.append(lower)
f8deb5b9 Poul Sander 2022-01-15 13:55 86
f8deb5b9 Poul Sander 2022-01-15 13:55 87
    return uppers, lowers
f8deb5b9 Poul Sander 2022-01-15 13:55 88
f8deb5b9 Poul Sander 2022-01-15 13:55 89
def compress_normal(normal):
f8deb5b9 Poul Sander 2022-01-15 13:55 90
    # lengths 0x00..0x7f are encoded as 00, 01, ..., 7e, 7f
f8deb5b9 Poul Sander 2022-01-15 13:55 91
    # lengths 0x80..0x7fff are encoded as 80 80, 80 81, ..., ff fe, ff ff
f8deb5b9 Poul Sander 2022-01-15 13:55 92
    compressed = [] # [truelen, (truelenaux), falselen, (falselenaux)]
f8deb5b9 Poul Sander 2022-01-15 13:55 93
f8deb5b9 Poul Sander 2022-01-15 13:55 94
    prev_start = 0
f8deb5b9 Poul Sander 2022-01-15 13:55 95
    for start, count in normal:
f8deb5b9 Poul Sander 2022-01-15 13:55 96
        truelen = start - prev_start
f8deb5b9 Poul Sander 2022-01-15 13:55 97
        falselen = count
f8deb5b9 Poul Sander 2022-01-15 13:55 98
        prev_start = start + count
f8deb5b9 Poul Sander 2022-01-15 13:55 99
f8deb5b9 Poul Sander 2022-01-15 13:55 100
        assert truelen < 0x8000 and falselen < 0x8000
f8deb5b9 Poul Sander 2022-01-15 13:55 101
        entry = []
f8deb5b9 Poul Sander 2022-01-15 13:55 102
        if truelen > 0x7f:
f8deb5b9 Poul Sander 2022-01-15 13:55 103
            entry.append(0x80 | (truelen >> 8))
f8deb5b9 Poul Sander 2022-01-15 13:55 104
            entry.append(truelen & 0xff)
f8deb5b9 Poul Sander 2022-01-15 13:55 105
        else:
f8deb5b9 Poul Sander 2022-01-15 13:55 106
            entry.append(truelen & 0x7f)
f8deb5b9 Poul Sander 2022-01-15 13:55 107
        if falselen > 0x7f:
f8deb5b9 Poul Sander 2022-01-15 13:55 108
            entry.append(0x80 | (falselen >> 8))
f8deb5b9 Poul Sander 2022-01-15 13:55 109
            entry.append(falselen & 0xff)
f8deb5b9 Poul Sander 2022-01-15 13:55 110
        else:
f8deb5b9 Poul Sander 2022-01-15 13:55 111
            entry.append(falselen & 0x7f)
f8deb5b9 Poul Sander 2022-01-15 13:55 112
f8deb5b9 Poul Sander 2022-01-15 13:55 113
        compressed.append(entry)
f8deb5b9 Poul Sander 2022-01-15 13:55 114
f8deb5b9 Poul Sander 2022-01-15 13:55 115
    return compressed
f8deb5b9 Poul Sander 2022-01-15 13:55 116
f8deb5b9 Poul Sander 2022-01-15 13:55 117
def print_singletons(uppers, lowers, uppersname, lowersname):
f8deb5b9 Poul Sander 2022-01-15 13:55 118
    print("  static constexpr singleton {}[] = {{".format(uppersname))
f8deb5b9 Poul Sander 2022-01-15 13:55 119
    for u, c in uppers:
f8deb5b9 Poul Sander 2022-01-15 13:55 120
        print("    {{{:#04x}, {}}},".format(u, c))
f8deb5b9 Poul Sander 2022-01-15 13:55 121
    print("  };")
f8deb5b9 Poul Sander 2022-01-15 13:55 122
    print("  static constexpr unsigned char {}[] = {{".format(lowersname))
f8deb5b9 Poul Sander 2022-01-15 13:55 123
    for i in range(0, len(lowers), 8):
f8deb5b9 Poul Sander 2022-01-15 13:55 124
        print("    {}".format(" ".join("{:#04x},".format(l) for l in lowers[i:i+8])))
f8deb5b9 Poul Sander 2022-01-15 13:55 125
    print("  };")
f8deb5b9 Poul Sander 2022-01-15 13:55 126
f8deb5b9 Poul Sander 2022-01-15 13:55 127
def print_normal(normal, normalname):
f8deb5b9 Poul Sander 2022-01-15 13:55 128
    print("  static constexpr unsigned char {}[] = {{".format(normalname))
f8deb5b9 Poul Sander 2022-01-15 13:55 129
    for v in normal:
f8deb5b9 Poul Sander 2022-01-15 13:55 130
        print("    {}".format(" ".join("{:#04x},".format(i) for i in v)))
f8deb5b9 Poul Sander 2022-01-15 13:55 131
    print("  };")
f8deb5b9 Poul Sander 2022-01-15 13:55 132
f8deb5b9 Poul Sander 2022-01-15 13:55 133
def main():
f8deb5b9 Poul Sander 2022-01-15 13:55 134
    file = get_file("https://www.unicode.org/Public/UNIDATA/UnicodeData.txt")
f8deb5b9 Poul Sander 2022-01-15 13:55 135
f8deb5b9 Poul Sander 2022-01-15 13:55 136
    codepoints = get_codepoints(file)
f8deb5b9 Poul Sander 2022-01-15 13:55 137
f8deb5b9 Poul Sander 2022-01-15 13:55 138
    CUTOFF=0x10000
f8deb5b9 Poul Sander 2022-01-15 13:55 139
    singletons0 = []
f8deb5b9 Poul Sander 2022-01-15 13:55 140
    singletons1 = []
f8deb5b9 Poul Sander 2022-01-15 13:55 141
    normal0 = []
f8deb5b9 Poul Sander 2022-01-15 13:55 142
    normal1 = []
f8deb5b9 Poul Sander 2022-01-15 13:55 143
    extra = []
f8deb5b9 Poul Sander 2022-01-15 13:55 144
f8deb5b9 Poul Sander 2022-01-15 13:55 145
    for a, b in to_ranges(get_escaped(codepoints)):
f8deb5b9 Poul Sander 2022-01-15 13:55 146
        if a > 2 * CUTOFF:
f8deb5b9 Poul Sander 2022-01-15 13:55 147
            extra.append((a, b - a))
f8deb5b9 Poul Sander 2022-01-15 13:55 148
        elif a == b - 1:
f8deb5b9 Poul Sander 2022-01-15 13:55 149
            if a & CUTOFF:
f8deb5b9 Poul Sander 2022-01-15 13:55 150
                singletons1.append(a & ~CUTOFF)
f8deb5b9 Poul Sander 2022-01-15 13:55 151
            else:
f8deb5b9 Poul Sander 2022-01-15 13:55 152
                singletons0.append(a)
f8deb5b9 Poul Sander 2022-01-15 13:55 153
        elif a == b - 2:
f8deb5b9 Poul Sander 2022-01-15 13:55 154
            if a & CUTOFF:
f8deb5b9 Poul Sander 2022-01-15 13:55 155
                singletons1.append(a & ~CUTOFF)
f8deb5b9 Poul Sander 2022-01-15 13:55 156
                singletons1.append((a + 1) & ~CUTOFF)
f8deb5b9 Poul Sander 2022-01-15 13:55 157
            else:
f8deb5b9 Poul Sander 2022-01-15 13:55 158
                singletons0.append(a)
f8deb5b9 Poul Sander 2022-01-15 13:55 159
                singletons0.append(a + 1)
f8deb5b9 Poul Sander 2022-01-15 13:55 160
        else:
f8deb5b9 Poul Sander 2022-01-15 13:55 161
            if a >= 2 * CUTOFF:
f8deb5b9 Poul Sander 2022-01-15 13:55 162
                extra.append((a, b - a))
f8deb5b9 Poul Sander 2022-01-15 13:55 163
            elif a & CUTOFF:
f8deb5b9 Poul Sander 2022-01-15 13:55 164
                normal1.append((a & ~CUTOFF, b - a))
f8deb5b9 Poul Sander 2022-01-15 13:55 165
            else:
f8deb5b9 Poul Sander 2022-01-15 13:55 166
                normal0.append((a, b - a))
f8deb5b9 Poul Sander 2022-01-15 13:55 167
f8deb5b9 Poul Sander 2022-01-15 13:55 168
    singletons0u, singletons0l = compress_singletons(singletons0)
f8deb5b9 Poul Sander 2022-01-15 13:55 169
    singletons1u, singletons1l = compress_singletons(singletons1)
f8deb5b9 Poul Sander 2022-01-15 13:55 170
    normal0 = compress_normal(normal0)
f8deb5b9 Poul Sander 2022-01-15 13:55 171
    normal1 = compress_normal(normal1)
f8deb5b9 Poul Sander 2022-01-15 13:55 172
f8deb5b9 Poul Sander 2022-01-15 13:55 173
    print("""\
f8deb5b9 Poul Sander 2022-01-15 13:55 174
inline auto is_printable(uint32_t cp) -> bool {\
f8deb5b9 Poul Sander 2022-01-15 13:55 175
""")
f8deb5b9 Poul Sander 2022-01-15 13:55 176
    print_singletons(singletons0u, singletons0l, 'singletons0', 'singletons0_lower')
f8deb5b9 Poul Sander 2022-01-15 13:55 177
    print_singletons(singletons1u, singletons1l, 'singletons1', 'singletons1_lower')
f8deb5b9 Poul Sander 2022-01-15 13:55 178
    print_normal(normal0, 'normal0')
f8deb5b9 Poul Sander 2022-01-15 13:55 179
    print_normal(normal1, 'normal1')
f8deb5b9 Poul Sander 2022-01-15 13:55 180
    print("""\
f8deb5b9 Poul Sander 2022-01-15 13:55 181
  auto lower = static_cast<uint16_t>(cp);
f8deb5b9 Poul Sander 2022-01-15 13:55 182
  if (cp < 0x10000) {
f8deb5b9 Poul Sander 2022-01-15 13:55 183
    return is_printable(lower, singletons0,
f8deb5b9 Poul Sander 2022-01-15 13:55 184
                        sizeof(singletons0) / sizeof(*singletons0),
f8deb5b9 Poul Sander 2022-01-15 13:55 185
                        singletons0_lower, normal0, sizeof(normal0));
f8deb5b9 Poul Sander 2022-01-15 13:55 186
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 187
  if (cp < 0x20000) {
f8deb5b9 Poul Sander 2022-01-15 13:55 188
    return is_printable(lower, singletons1,
f8deb5b9 Poul Sander 2022-01-15 13:55 189
                        sizeof(singletons1) / sizeof(*singletons1),
f8deb5b9 Poul Sander 2022-01-15 13:55 190
                        singletons1_lower, normal1, sizeof(normal1));
f8deb5b9 Poul Sander 2022-01-15 13:55 191
  }\
f8deb5b9 Poul Sander 2022-01-15 13:55 192
""")
f8deb5b9 Poul Sander 2022-01-15 13:55 193
    for a, b in extra:
f8deb5b9 Poul Sander 2022-01-15 13:55 194
        print("  if (0x{:x} <= cp && cp < 0x{:x}) return false;".format(a, a + b))
f8deb5b9 Poul Sander 2022-01-15 13:55 195
    print("""\
f8deb5b9 Poul Sander 2022-01-15 13:55 196
  return cp < 0x{:x};
f8deb5b9 Poul Sander 2022-01-15 13:55 197
}}\
f8deb5b9 Poul Sander 2022-01-15 13:55 198
""".format(NUM_CODEPOINTS))
f8deb5b9 Poul Sander 2022-01-15 13:55 199
f8deb5b9 Poul Sander 2022-01-15 13:55 200
if __name__ == '__main__':
f8deb5b9 Poul Sander 2022-01-15 13:55 201
    main()
1970-01-01 00:00 202