///|
const UPPER_A = 65
///|
const UPPER_Z = 90
///|
const LOWER_DELTA = 32
///|
fn char_code(s : String, i : Int) -> Int {
s.unsafe_get(i).to_int()
}
///|
fn code_to_char(code : Int) -> Char {
code.unsafe_to_char()
}
///|
fn is_space_code(code : Int) -> Bool {
code == 32 || code == 9 || code == 10 || code == 13 || code == 12
}
///|
fn ascii_lower_code(code : Int) -> Int {
if code >= UPPER_A && code <= UPPER_Z {
code + LOWER_DELTA
} else {
code
}
}
///|
fn trim_ascii(input : String) -> String {
let len = input.length()
let mut start = 0
while start < len && is_space_code(char_code(input, start)) {
start = start + 1
}
let mut end = len
while end > start && is_space_code(char_code(input, end - 1)) {
end = end - 1
}
input[start:end].to_owned()
}
///|
fn lower_ascii(input : String) -> String {
let chars : Array[Char] = []
for i in 0.. Bool {
if offset < 0 || offset + prefix.length() > text.length() {
return false
}
for i in 0.. Bool {
starts_with_at(text, prefix, 0)
}
///|
fn ends_with(text : String, suffix : String) -> Bool {
if suffix.length() > text.length() {
false
} else {
starts_with_at(text, suffix, text.length() - suffix.length())
}
}
///|
pub fn contains_text(text : String, needle : String) -> Bool {
if needle.length() == 0 {
return true
}
if needle.length() > text.length() {
return false
}
let mut start = 0
let last = text.length() - needle.length()
while start <= last {
if starts_with_at(text, needle, start) {
return true
}
start = start + 1
}
false
}
///|
fn split_by_char(input : String, sep : Int) -> Array[String] {
let out : Array[String] = []
let mut start = 0
let mut i = 0
while i < input.length() {
if char_code(input, i) == sep {
out.push(input[start:i].to_owned())
start = i + 1
}
i = i + 1
}
out.push(input[start:].to_owned())
out
}
///|
fn split_words(input : String) -> Array[String] {
let words : Array[String] = []
let mut i = 0
while i < input.length() {
while i < input.length() && is_space_code(char_code(input, i)) {
i = i + 1
}
let start = i
while i < input.length() && !is_space_code(char_code(input, i)) {
i = i + 1
}
if i > start {
words.push(input[start:i].to_owned())
}
}
words
}
///|
fn join_strings(items : Array[String], sep : String) -> String {
let mut out = ""
for i, item in items {
if i > 0 {
out = out + sep
}
out = out + item
}
out
}
///|
fn strip_quotes(input : String) -> String {
let text = trim_ascii(input)
if text.length() >= 2 &&
char_code(text, 0) == 39 &&
char_code(text, text.length() - 1) == 39 {
text[1:text.length() - 1].to_owned()
} else {
text
}
}
///|
fn normalize_token(input : String) -> String {
lower_ascii(trim_ascii(input))
}
///|
fn normalize_url(input : String) -> String {
trim_ascii(input)
}
///|
fn find_scheme_end(url : String) -> Int {
let mut i = 0
while i + 2 < url.length() {
if char_code(url, i) == 58 &&
char_code(url, i + 1) == 47 &&
char_code(url, i + 2) == 47 {
return i
}
i = i + 1
}
-1
}
///|
fn extract_origin(url : String) -> String {
let scheme_end = find_scheme_end(url)
if scheme_end < 0 {
return ""
}
let mut end = scheme_end + 3
while end < url.length() &&
char_code(url, end) != 47 &&
char_code(url, end) != 63 &&
char_code(url, end) != 35 {
end = end + 1
}
lower_ascii(url[:end].to_owned())
}
///|
fn extract_scheme(url : String) -> String {
let scheme_end = find_scheme_end(url)
if scheme_end < 0 {
""
} else {
lower_ascii(url[:scheme_end + 1].to_owned())
}
}
///|
fn extract_host_pattern(source : String) -> String {
let value = lower_ascii(source)
let scheme_end = find_scheme_end(value)
if scheme_end >= 0 {
let mut end = scheme_end + 3
while end < value.length() && char_code(value, end) != 47 {
end = end + 1
}
value[scheme_end + 3:end].to_owned()
} else {
value
}
}