///|
fn pdf_number_view_without_double_minus(view : BytesView) -> BytesView {
if view.length() > 1 && view[0].to_int() == 45 && view[1].to_int() == 45 {
view[1:]
} else {
view
}
}
///|
fn pdf_number_view_has_real_marker(view : BytesView) -> Bool {
for i in 0.. Int? {
if view.length() == 0 {
None
} else {
let mut index = 0
let mut negative = false
match view[0].to_int() {
43 => index = 1
45 => {
negative = true
index = 1
}
_ => ()
}
if index >= view.length() {
None
} else {
let limit : Int64 = if negative { 2147483648L } else { 2147483647L }
let mut value : Int64 = 0L
let mut valid = true
while valid && index < view.length() {
let byte = view[index].to_int()
if byte < 48 || byte > 57 {
valid = false
} else {
value = value * 10L + (byte - 48).to_int64()
if value > limit {
valid = false
}
index += 1
}
}
if !valid {
None
} else if negative {
Some((-value).to_int())
} else {
Some(value.to_int())
}
}
}
}
///|
fn pdf_number_view_real(view : BytesView) -> PdfLexeme {
try @ascii.decode(view) catch {
_ => LexNone
} noraise {
text => {
let real : Result[Double, Error] = try @string.parse_double(text) catch {
err => Err(err)
} noraise {
value => Ok(value)
}
match real {
Ok(value) => LexReal(value)
Err(_) => LexNone
}
}
}
}
///|
/// Lex `true` or `false` at the current cursor position.
///
/// The cursor first reads one regular token. Non-boolean tokens produce
/// `LexNone`.
pub fn pdf_cursor_lex_bool(cursor : @core.ByteCursor) -> PdfLexeme {
let view = pdf_cursor_read_regular_token_view(cursor)
match view {
[116, 114, 117, 101] => LexBool(true)
[102, 97, 108, 115, 101] => LexBool(false)
_ => LexNone
}
}
///|
/// Lex a PDF integer or real number.
///
/// Integers are limited to MoonBit `Int` range; oversized integer-looking
/// tokens fall back to real-number parsing. A leading doubled minus is accepted
/// compatibly by dropping one minus sign.
pub fn pdf_cursor_lex_number(cursor : @core.ByteCursor) -> PdfLexeme {
let view = pdf_number_view_without_double_minus(
pdf_cursor_read_regular_token_view(cursor),
)
if view.length() == 0 {
LexNone
} else if pdf_number_view_has_real_marker(view) {
pdf_number_view_real(view)
} else {
match pdf_number_view_int(view) {
Some(value) => LexInt(value)
None => pdf_number_view_real(view)
}
}
}