blob: 3566d143529be9135a6ce18f80e3b7ba8bb08fe2 [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright 2011-2016 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
# This script uses the following Unicode tables:
# - Categories.txt
import os
import subprocess
def to_ranges(iter):
current = None
for i in iter:
if current is None or i != current[1] or i in (0x10000, 0x20000):
if current is not None:
yield tuple(current)
current = [i, i + 1]
else:
current[1] += 1
if current is not None:
yield tuple(current)
def get_escaped(dictionary):
for i in range(0x110000):
if dictionary.get(i, "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and i != ord(' '):
yield i
def get_file(f):
try:
return open(os.path.basename(f))
except FileNotFoundError:
subprocess.run(["curl", "-O", f], check=True)
return open(os.path.basename(f))
def main():
file = get_file("http://www.unicode.org/notes/tn36/Categories.txt")
dictionary = {int(line.split()[0], 16): line.split()[1] for line in file}
CUTOFF=0x10000
singletons0 = []
singletons1 = []
normal0 = []
normal1 = []
extra = []
for a, b in to_ranges(get_escaped(dictionary)):
if a > 2 * CUTOFF:
extra.append((a, b - a))
elif a == b - 1:
if a & CUTOFF:
singletons1.append(a & ~CUTOFF)
else:
singletons0.append(a)
elif a == b - 2:
if a & CUTOFF:
singletons1.append(a & ~CUTOFF)
singletons1.append((a + 1) & ~CUTOFF)
else:
singletons0.append(a)
singletons0.append(a + 1)
else:
if a >= 2 * CUTOFF:
extra.append((a, b - a))
elif a & CUTOFF:
normal1.append((a & ~CUTOFF, b - a))
else:
normal0.append((a, b - a))
print("""\
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// NOTE: The following code was generated by "src/etc/char_private.py",
// do not edit directly!
use slice::SliceExt;
fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
for &s in singletons {
if x == s {
return false;
} else if x < s {
break;
}
}
for w in normal.chunks(2) {
let start = w[0];
let len = w[1];
let difference = (x as i32) - (start as i32);
if 0 <= difference {
if difference < len as i32 {
return false;
}
} else {
break;
}
}
true
}
pub fn is_printable(x: char) -> bool {
let x = x as u32;
let lower = x as u16;
if x < 0x10000 {
check(lower, SINGLETONS0, NORMAL0)
} else if x < 0x20000 {
check(lower, SINGLETONS1, NORMAL1)
} else {\
""")
for a, b in extra:
print(" if 0x{:x} <= x && x < 0x{:x} {{".format(a, a + b))
print(" return false;")
print(" }")
print("""\
true
}
}\
""")
print()
print("const SINGLETONS0: &'static [u16] = &[")
for s in singletons0:
print(" 0x{:x},".format(s))
print("];")
print("const SINGLETONS1: &'static [u16] = &[")
for s in singletons1:
print(" 0x{:x},".format(s))
print("];")
print("const NORMAL0: &'static [u16] = &[")
for a, b in normal0:
print(" 0x{:x}, 0x{:x},".format(a, b))
print("];")
print("const NORMAL1: &'static [u16] = &[")
for a, b in normal1:
print(" 0x{:x}, 0x{:x},".format(a, b))
print("];")
if __name__ == '__main__':
main()