///|
fn is_ws(ch : Char) -> Bool {
match ch {
' ' | '\n' | '\r' | '\t' => true
_ => false
}
}
///|
fn char_at(source : String, pos : Int) -> Char? {
source.get_char(pos)
}
///|
fn skip_ws(source : String, pos : Int) -> Int {
let mut i = pos
while i < source.length() {
match char_at(source, i) {
Some(ch) => if is_ws(ch) { i += 1 } else { return i }
None => return i
}
}
i
}
///|
fn first_token(source : String) -> (String, String) {
let start = skip_ws(source, 0)
if start >= source.length() {
return ("", "")
}
let mut end = start
while end < source.length() {
match char_at(source, end) {
Some(ch) => if is_ws(ch) { break } else { end += 1 }
None => break
}
}
(source[start:end].to_owned(), source[end:].to_owned())
}
///|
fn tokens(source : String) -> Array[String] {
let result : Array[String] = []
let mut i = 0
while i < source.length() {
i = skip_ws(source, i)
if i >= source.length() {
break
}
let start = i
while i < source.length() {
match char_at(source, i) {
Some(ch) => if is_ws(ch) { break } else { i += 1 }
None => break
}
}
result.push(source[start:i].to_owned())
}
result
}
///|
fn first_arg(arguments : String) -> String {
let (token, _) = first_token(arguments)
token
}
///|
fn contains_token(source : String, token : String) -> Bool {
let target = token.to_lower()
for part in tokens(source.to_lower()) {
if part == target {
return true
}
}
false
}
///|
fn find_ignore_case(source : String, needle : String) -> Int? {
source.to_lower().find(needle.to_lower())
}
///|
fn split_physical_lines(source : String) -> Array[String] {
let result : Array[String] = []
for part in source.split("\n") {
result.push(part.trim_end(chars="\r").to_owned())
}
result
}
///|
fn json_escape(value : String) -> String {
let out = StringBuilder()
for ch in value {
match ch {
'"' => out.write_string("\\\"")
'\\' => out.write_string("\\\\")
'\n' => out.write_string("\\n")
'\r' => out.write_string("\\r")
'\t' => out.write_string("\\t")
_ => out.write_char(ch)
}
}
out.to_string()
}