///|
// Strategy: seq-integer-batches
///|
fn Decimal::bounded_integer(self : Decimal) -> Int64? {
if self.scale != 0 ||
self.coefficient.compare_int64(-9223372036854775808L) < 0 ||
self.coefficient.compare_int64(9223372036854775807L) > 0 {
None
} else {
Some(self.coefficient.to_int64())
}
}
///|
priv struct IntegerSequence {
mut current : Int64
last : Int64
step : Int64
separator : Bytes
width : Int32
scratch : FixedArray[Byte]
mut emitted : Bool
mut done : Bool
}
///|
fn IntegerSequence::new(
first : Int64,
step : Int64,
last : Int64,
separator : Bytes,
width : Int32,
) -> IntegerSequence {
{
current: first,
step,
last,
separator,
width,
scratch: FixedArray::make(20, b'0'),
emitted: false,
done: false,
}
}
///|
fn IntegerSequence::fill(
self : IntegerSequence,
output : FixedArray[Byte],
) -> Int32 {
let mut used = 0
while !self.done {
let value = self.current
if (self.step > 0 && value > self.last) ||
(self.step < 0 && value < self.last) {
if self.emitted {
output[used] = b'\n'
used += 1
}
self.done = true
break
}
// Reserve the complete next record and its eventual terminal newline.
if output.length() - used < self.separator.length() + 21 {
break
}
if self.emitted {
for byte in self.separator {
output[used] = byte
used += 1
}
}
let negative = value < 0
let mut magnitude = if negative {
0UL - value.reinterpret_as_uint64()
} else {
value.reinterpret_as_uint64()
}
let mut start = 20
for ;; {
start -= 1
self.scratch[start] = (magnitude % 10UL).to_byte() + b'0'
magnitude /= 10UL
if magnitude == 0UL {
break
}
}
if negative {
output[used] = b'-'
used += 1
}
let digits = 20 - start + (if negative { 1 } else { 0 })
for _ in digits.. 0 && value > 9223372036854775807L - self.step) ||
(self.step < 0 && value < -9223372036854775808L - self.step) {
output[used] = b'\n'
used += 1
self.done = true
break
}
self.current += self.step
}
used
}
///|
async fn print_integers(
sequence : IntegerSequence,
writer : &@io.Writer,
) -> Unit {
let buffer = FixedArray::make(65536, b'\x00')
while !sequence.done {
let count = sequence.fill(buffer)
if count > 0 {
writer.write(buffer.unsafe_reinterpret_as_bytes()[:count])
}
}
}