///|
priv struct StringDump {
minimum : Int64
base : Int32
label : Int64?
pending : Array[Byte]
mut skip : Int64
mut remaining : Int64?
mut offset : Int64
mut start : Int64
}
///|
fn StringDump::done(self : StringDump) -> Bool {
self.skip == 0L &&
(
self.remaining == Some(0L) ||
(
self.pending.is_empty() &&
self.remaining is Some(left) &&
left < self.minimum
)
)
}
///|
fn StringDump::record(self : StringDump, output : StringBuilder) -> Unit {
if self.pending.length().to_int64() >= self.minimum {
let prefix = labeled_address(self.start, self.base, self.label)
if prefix != "" {
output.write_string(prefix + " ")
}
for byte in self.pending {
output.write_char(byte.to_int().unsafe_to_char())
}
output.write_char('\n')
}
self.pending.clear()
}
///|
fn StringDump::feed(self : StringDump, data : BytesView) -> String {
let output = StringBuilder()
for byte in data {
if self.skip > 0L {
self.skip -= 1
self.offset += 1
self.start = self.offset
continue
}
if self.done() {
break
}
self.offset += 1
if self.remaining is Some(left) {
self.remaining = Some(left - 1)
}
if byte == b'\x00' {
self.record(output)
self.start = self.offset
} else if byte >= b' ' && byte <= b'~' {
self.pending.push(byte)
} else {
self.pending.clear()
self.start = self.offset
}
if self.remaining == Some(0L) && byte >= b' ' && byte <= b'~' {
self.record(output)
}
}
output.to_string()
}
///|
async fn StringDump::read(self : StringDump, reader : &@io.Reader) -> Unit {
let buffer = FixedArray::make(65536, b'\x00')
let data = buffer.unsafe_reinterpret_as_bytes()
while !self.done() {
let request = match self.remaining {
Some(left) =>
(self.skip.min(65536L) + left.min(65536L)).min(65536L).to_int()
None => 65536
}
let count = reader.read(buffer, max_len=request)
if count == 0 {
break
}
@stdio.stdout.write(self.feed(data[:count]))
}
}