// Unicode types, general categories, and codepoint properties
///|
pub(all) struct UnicodeVersion {
major : Int32
minor : Int32
update : Int32
} derive(Eq, Debug)
///|
pub let unicode_version : UnicodeVersion = { major: 16, minor: 0, update: 0, }
///|
pub(all) enum GeneralCategory {
Letter
Mark
Number
Punctuation
Symbol
Separator
Other
} derive(Eq, Debug)
///|
pub fn get_general_category(cp : Int32) -> GeneralCategory {
if (cp >= 0x0041 && cp <= 0x005A) ||
(cp >= 0x0061 && cp <= 0x007A) ||
(cp >= 0x4E00 && cp <= 0x9FFF) {
Letter
} else if cp >= 0x0030 && cp <= 0x0039 {
Number
} else if cp == 0x0020 || cp == 0x3000 {
Separator
} else if is_invisible_codepoint(cp) ||
is_bidi_control_codepoint(cp) ||
cp < 0x0020 {
Other
} else if cp == 0x002B || cp == 0x003D || cp == 0x0024 {
Symbol
} else if cp == 0x002C ||
cp == 0x002E ||
cp == 0x003A ||
cp == 0x003B ||
cp == 0x0021 ||
cp == 0x003F {
Punctuation
} else {
Mark
}
}
///|
pub(all) struct CharInfo {
codepoint : Int32
char : Char
name : String
category : GeneralCategory
is_invisible : Bool
is_bidi_control : Bool
} derive(Debug)
///|
pub fn is_ascii(cp : Int32) -> Bool {
cp >= 0 && cp <= 0x7F
}
///|
pub fn is_invisible_codepoint(cp : Int32) -> Bool {
is_default_ignorable(cp)
}
///|
pub fn is_bidi_control_codepoint(cp : Int32) -> Bool {
match cp {
0x200E => true // LEFT-TO-RIGHT MARK
0x200F => true // RIGHT-TO-LEFT MARK
0x061C => true // ARABIC LETTER MARK
0x202A => true // LEFT-TO-RIGHT EMBEDDING
0x202B => true // RIGHT-TO-LEFT EMBEDDING
0x202C => true // POP DIRECTIONAL FORMATTING
0x202D => true // LEFT-TO-RIGHT OVERRIDE
0x202E => true // RIGHT-TO-LEFT OVERRIDE
0x2066 => true // LEFT-TO-RIGHT ISOLATE
0x2067 => true // RIGHT-TO-LEFT ISOLATE
0x2068 => true // FIRST STRONG ISOLATE
0x2069 => true // POP DIRECTIONAL ISOLATE
_ => false
}
}
///|
pub fn is_bidi_override_codepoint(cp : Int32) -> Bool {
cp == 0x202D || cp == 0x202E // LRO, RLO
}
///|
pub fn has_bidi_controls(input : String) -> Bool {
for ch in input {
if is_bidi_control_codepoint(ch.to_int()) {
return true
}
}
false
}
///|
pub fn has_bidi_override(input : String) -> Bool {
for ch in input {
if is_bidi_override_codepoint(ch.to_int()) {
return true
}
}
false
}
///|
pub fn has_invisible_characters(input : String) -> Bool {
for ch in input {
if is_invisible_codepoint(ch.to_int()) {
return true
}
}
false
}
///|
pub fn hex_char(digit : Int32) -> Char {
if digit < 10 {
(48 + digit).unsafe_to_char()
} else {
(65 + digit - 10).unsafe_to_char()
}
}
///|
pub fn format_codepoint(cp : Int32) -> String {
let buf = StringBuilder()
buf.write_string("U+")
let mut temp = cp
let digits : Array[Char] = []
if temp == 0 {
digits.push('0')
digits.push('0')
digits.push('0')
digits.push('0')
} else {
while temp > 0 {
let rem = temp % 16
digits.push(hex_char(rem))
temp = temp / 16
}
while digits.length() < 4 {
digits.push('0')
}
}
for i = digits.length() - 1; i >= 0; i = i - 1 {
buf.write_char(digits[i])
}
buf.to_string()
}