#![allow(non_upper_case_globals)]
use crate::ported::eval::typval_defs_h::{varnumber_T, VARNUMBER_MAX, VARNUMBER_MIN};
pub const STR2NR_BIN: i32 = 0x01;
pub const STR2NR_OCT: i32 = 0x02;
pub const STR2NR_HEX: i32 = 0x04;
pub const STR2NR_OOCT: i32 = 0x08;
pub const STR2NR_QUOTE: i32 = 0x10;
pub const STR2NR_ALL: i32 = STR2NR_BIN | STR2NR_OCT | STR2NR_HEX | STR2NR_OOCT;
pub const STR2NR_FORCE: i32 = 0x80;
#[allow(clippy::too_many_arguments)]
pub fn vim_str2nr(
start: &str,
prep: Option<&mut i32>,
len: Option<&mut i32>,
what: i32,
nptr: Option<&mut varnumber_T>,
unptr: Option<&mut u64>,
maxlen: i32,
_strict: bool,
_overflow: Option<&mut i32>,
) {
let bytes = start.as_bytes();
let mut ptr = 0usize; let mut negative = false; let cap = if maxlen <= 0 {
bytes.len()
} else {
(maxlen as usize).min(bytes.len())
};
if ptr < cap && (bytes[ptr] == b'-' || bytes[ptr] == b'+') {
negative = bytes[ptr] == b'-';
ptr += 1;
}
let mut pre = 0u8; let mut base: u64 = 10;
if (what & STR2NR_FORCE) != 0 {
base = if what & STR2NR_HEX != 0 {
16
} else if what & (STR2NR_OCT | STR2NR_OOCT) != 0 {
8
} else if what & STR2NR_BIN != 0 {
2
} else {
10
};
if ptr + 1 < cap && bytes[ptr] == b'0' {
let c = bytes[ptr + 1];
let pfx = (base == 16 && (c == b'x' || c == b'X'))
|| (base == 2 && (c == b'b' || c == b'B'))
|| (base == 8 && (c == b'o' || c == b'O'));
if pfx {
pre = c;
ptr += 2;
}
}
} else if ptr < cap && bytes[ptr] == b'0' && ptr + 1 < cap {
match bytes[ptr + 1] {
b'x' | b'X' if (what & STR2NR_HEX) != 0 => {
pre = bytes[ptr + 1];
base = 16;
ptr += 2;
}
b'b' | b'B' if (what & STR2NR_BIN) != 0 => {
pre = bytes[ptr + 1];
base = 2;
ptr += 2;
}
b'o' | b'O' if (what & STR2NR_OOCT) != 0 => {
pre = bytes[ptr + 1];
base = 8;
ptr += 2;
}
b'0'..=b'7' if (what & STR2NR_OCT) != 0 => {
pre = b'0';
base = 8;
ptr += 1;
}
_ => {}
}
}
let mut un: u64 = 0; let mut saw_digit = false;
let digit_val = |c: u8| -> Option<u64> {
match c {
b'0'..=b'9' => Some((c - b'0') as u64),
b'a'..=b'f' if base == 16 => Some((c - b'a' + 10) as u64),
b'A'..=b'F' if base == 16 => Some((c - b'A' + 10) as u64),
_ => None,
}
.filter(|&d| d < base)
};
while ptr < cap {
if (what & STR2NR_QUOTE) != 0
&& bytes[ptr] == b'\''
&& ptr + 1 < cap
&& digit_val(bytes[ptr + 1]).is_some()
{
ptr += 1;
continue;
}
let Some(d) = digit_val(bytes[ptr]) else {
break;
};
un = un.saturating_mul(base).saturating_add(d);
saw_digit = true;
ptr += 1;
}
let _ = saw_digit;
if let Some(p) = prep {
*p = pre as i32;
}
if let Some(l) = len {
*l = ptr as i32;
}
if let Some(u) = unptr {
*u = un;
}
if let Some(n) = nptr {
*n = if negative {
if un > VARNUMBER_MAX as u64 {
VARNUMBER_MIN
} else {
-(un as varnumber_T)
}
} else if un > VARNUMBER_MAX as u64 {
VARNUMBER_MAX
} else {
un as varnumber_T
};
}
}