///|
/// Whether `cp` is in one of the inclusive start/end pairs of `ranges`.
fn in_ranges(ranges : FixedArray[Int], cp : Int) -> Bool {
let mut lo = 0
let mut hi = ranges.length() / 2 - 1
while lo <= hi {
let mid = (lo + hi) / 2
if cp < ranges[mid * 2] {
hi = mid - 1
} else if cp > ranges[mid * 2 + 1] {
lo = mid + 1
} else {
return true
}
}
false
}
///|
/// Whether `c` can start a lower-case name (a Unicode lower-case letter).
pub fn is_lower_start(c : Char) -> Bool {
let cp = c.to_int()
if cp < 0x80 {
c >= 'a' && c <= 'z'
} else {
in_ranges(lower_start_ranges, cp)
}
}
///|
/// Whether `c` can start an upper-case name (a Unicode upper-case or
/// title-case letter).
pub fn is_upper_start(c : Char) -> Bool {
let cp = c.to_int()
if cp < 0x80 {
c >= 'A' && c <= 'Z'
} else {
in_ranges(upper_start_ranges, cp)
}
}
///|
/// Whether `c` can continue a name: a Unicode letter or number, or `_`.
pub fn is_name_part(c : Char) -> Bool {
let cp = c.to_int()
if cp < 0x80 {
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c == '_'
} else {
in_ranges(inner_ranges, cp)
}
}
///|
/// Whether `c` is a title-case letter (Lt), such as `Dž`.
fn is_titlecase(c : Char) -> Bool {
c.to_int() >= 0x80 && in_ranges(titlecase_ranges, c.to_int())
}
///|
/// Whether `c` is a number outside ASCII (Nd, Nl, No), such as `₁` or `٣`.
fn is_non_ascii_number(c : Char) -> Bool {
c.to_int() >= 0x80 && in_ranges(number_ranges, c.to_int())
}