///|
fn field_ranges(line : Bytes, separator : Byte?) -> Array[(Int32, Int32)] {
let ranges : Array[(Int32, Int32)] = []
match separator {
Some(delimiter) => {
let mut start = 0
for index, byte in line {
if byte == delimiter {
ranges.push((start, index))
start = index + 1
}
}
ranges.push((start, line.length()))
}
None => {
let mut start = 0
let mut index = 0
let mut seen_nonblank = false
while index < line.length() {
if byte_is_blank(line[index]) {
if seen_nonblank {
ranges.push((start, index))
start = index
seen_nonblank = false
}
} else {
seen_nonblank = true
}
index += 1
}
if start < line.length() {
ranges.push((start, line.length()))
}
}
}
ranges
}
///|
fn key_start(
line : Bytes,
position : Position,
ranges : Array[(Int32, Int32)],
) -> Int32 {
if position.field > ranges.length() {
return line.length()
}
let (field_start, field_end) = ranges[position.field - 1]
let mut start = field_start
if position.skip_blanks {
while start < field_end && byte_is_blank(line[start]) {
start += 1
}
}
Int32::min(field_end, start + Int32::max(0, position.character - 1))
}
///|
fn key_end(
line : Bytes,
position : Position,
ranges : Array[(Int32, Int32)],
) -> Int32 {
if position.field > ranges.length() {
return line.length()
}
let (field_start, field_end) = ranges[position.field - 1]
let mut start = field_start
if position.skip_blanks {
while start < field_end && byte_is_blank(line[start]) {
start += 1
}
}
if position.character == 0 {
field_end
} else {
Int32::min(field_end, start + position.character)
}
}
///|
fn extract_key(line : Bytes, spec : KeySpec, separator : Byte?) -> Bytes {
let ranges = field_ranges(line, separator)
let start = key_start(line, spec.start, ranges)
let end = match spec.end {
Some(position) => key_end(line, position, ranges)
None => line.length()
}
if end <= start {
b""
} else {
line[start:end].to_owned()
}
}
///|
fn transforms_key(modifiers : Modifiers) -> Bool {
modifiers.ignore_leading_blanks ||
modifiers.ignore_nonprinting ||
modifiers.dictionary_order ||
modifiers.fold_case
}
///|
fn transformed_key(key : Bytes, modifiers : Modifiers) -> Bytes {
if !transforms_key(modifiers) {
return key
}
let output : Array[Byte] = []
let mut start = 0
if modifiers.ignore_leading_blanks {
while start < key.length() && byte_is_blank(key[start]) {
start += 1
}
}
for byte in key[start:] {
if modifiers.ignore_nonprinting &&
(byte.to_int() < 0x20 || byte.to_int() > 0x7E) {
continue
}
if modifiers.dictionary_order &&
!byte_is_blank(byte) &&
!byte_is_alphanumeric(byte) {
continue
}
let value = byte.to_int()
output.push(
if modifiers.fold_case && value >= 0x61 && value <= 0x7A {
(value - 0x20).to_byte()
} else {
byte
},
)
}
Bytes::from_array(output)
}