///|
fn upper_ascii(s : String) -> String {
let mut out = ""
let mut i = 0
while i < s.length() {
let c = s[i]
if c >= 'a' && c <= 'z' {
let mut k = 0
let lower = "abcdefghijklmnopqrstuvwxyz"
while k < 26 {
if lower[k] == c {
out = out + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[k:k + 1].to_owned()
break
}
k += 1
}
} else {
out = out + unit_at(s, i)
}
i += 1
}
out
}
///|
fn trim_ascii(s : String) -> String {
let mut start = 0
let mut end = s.length()
while start < end && (s[start] == ' ' || s[start] == '\t') {
start += 1
}
while end > start && (s[end - 1] == ' ' || s[end - 1] == '\t') {
end -= 1
}
s[start:end].to_owned()
}
///|
fn split_raw_lines(input : String) -> Array[String] {
let lines : Array[String] = []
let mut start = 0
let mut i = 0
while i < input.length() {
let c = input[i]
if c == '\n' || c == '\r' {
lines.push(input[start:i].to_owned())
if c == '\r' && i + 1 < input.length() && input[i + 1] == '\n' {
i += 1
}
start = i + 1
}
i += 1
}
if start <= input.length() {
lines.push(input[start:input.length()].to_owned())
}
let out : Array[String] = []
i = 0
while i < lines.length() {
let t = trim_ascii(lines[i])
if t.length() > 0 {
out.push(upper_ascii(t))
}
i += 1
}
out
}
///|
fn expand_single_line(line : String) -> Array[String]? {
if line.length() == 88 {
return Some([line[0:44].to_owned(), line[44:88].to_owned()])
}
if line.length() == 72 {
return Some([line[0:36].to_owned(), line[36:72].to_owned()])
}
if line.length() == 90 {
return Some([
line[0:30].to_owned(),
line[30:60].to_owned(),
line[60:90].to_owned(),
])
}
None
}
///|
fn detect_layout(lines : Array[String]) -> Layout? {
if lines.length() == 2 && lines[0].length() == 44 && lines[1].length() == 44 {
return Some(TD3)
}
if lines.length() == 2 && lines[0].length() == 36 && lines[1].length() == 36 {
return Some(TD2)
}
if lines.length() == 3 &&
lines[0].length() == 30 &&
lines[1].length() == 30 &&
lines[2].length() == 30 {
return Some(TD1)
}
None
}
///|
fn rtrim_fillers(s : String) -> String {
let mut end = s.length()
while end > 0 && s[end - 1] == '<' {
end -= 1
}
s[0:end].to_owned()
}
///|
fn humanize_fillers(s : String) -> String {
let mut out = ""
let mut i = 0
let mut space = false
while i < s.length() {
let c = s[i]
if c == '<' {
space = true
} else {
if space && out.length() > 0 {
out = out + " "
}
out = out + unit_at(s, i)
space = false
}
i += 1
}
out
}
///|
fn split_names(field : String) -> Names {
let mut i = 0
while i + 1 < field.length() {
if field[i] == '<' && field[i + 1] == '<' {
return {
primary: humanize_fillers(field[0:i].to_owned()),
secondary: humanize_fillers(field[i + 2:field.length()].to_owned()),
}
}
i += 1
}
{ primary: humanize_fillers(field), secondary: "" }
}
///|
fn pad_fillers(s : String, width : Int) -> String {
if s.length() >= width {
return s[0:width].to_owned()
}
let mut out = s
while out.length() < width {
out = out + "<"
}
out
}
///|
fn spaces_to_fillers(s : String) -> String {
let mut out = ""
let mut i = 0
while i < s.length() {
if s[i] == ' ' {
out = out + "<"
} else {
out = out + unit_at(s, i)
}
i += 1
}
out
}