/*!
Optimized routines for parsing INI.
This module provides 2 functions: `find_nl` and `find_nl_chr`:
* `fn find_nl(s: &[u8]) -> usize`
Finds the first `b'\r'` or `b'\n'` in the input byte string and returns its index.
If no match was found returns the length of the input.
* `fn find_nl_chr(s: &[u8], chr: u8) -> usize`
Finds the first `b'\r'`, `b'\n'` or `chr` in the input byte string and returns its index.
If no match was found returns the length of the input.
For more information on the SWAR approaches see: <http://0x80.pl/articles/simd-strfind.html#swar>.
In reality I only see minor improvements with SWAR (about 33% faster).
*/
// LLVM is big dum dum, trust me I'm a human
#[cfg(not(debug_assertions))]
macro_rules! unsafe_assert {
($e:expr) => { unsafe { if !$e { ::core::hint::unreachable_unchecked(); } } };
}
#[cfg(debug_assertions)]
macro_rules! unsafe_assert {
($e:expr) => {};
}
mod generic;
cfg_if::cfg_if! {
// These optimizations are little endian specific
if #[cfg(not(target_endian = "little"))] {
pub use self::generic::*;
}
else if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "avx2"))] {
mod avx2;
pub use self::avx2::*;
}
else if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))] {
mod sse2;
pub use self::sse2::*;
}
else if #[cfg(target_pointer_width = "64")] {
mod swar64;
pub use self::swar64::*;
}
else if #[cfg(target_pointer_width = "32")] {
mod swar32;
pub use self::swar32::*;
}
else {
pub use self::generic::*;
}
}
#[test]
fn test_parse() {
let mut buffer = [b'-'; 254];
for i in 0..buffer.len() {
buffer[i] = b'\n';
// Check reference implementation
assert_eq!(generic::find_nl(&buffer), i);
assert_eq!(generic::find_nl_chr(&buffer, b'='), i);
// Check target implementation
assert_eq!(find_nl(&buffer), i);
assert_eq!(find_nl_chr(&buffer, b'='), i);
// Write annoying byte back
buffer[i] = if i & 1 == 0 { !0x0D } else { !0x0A };
}
}