Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![feature(align_offset)]
- use std::usize;
- use std::mem;
- use std::cmp;
- const LO_U64: u64 = 0x0101010101010101;
- const HI_U64: u64 = 0x8080808080808080;
- // use truncation
- const LO_USIZE: usize = LO_U64 as usize;
- const HI_USIZE: usize = HI_U64 as usize;
- #[inline]
- fn contains_zero_byte(x: usize) -> bool {
- x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
- }
- #[cfg(target_pointer_width = "16")]
- #[inline]
- fn repeat_byte(b: u8) -> usize {
- (b as usize) << 8 | b as usize
- }
- #[cfg(target_pointer_width = "32")]
- #[inline]
- fn repeat_byte(b: u8) -> usize {
- let mut rep = (b as usize) << 8 | b as usize;
- rep = rep << 16 | rep;
- rep
- }
- #[cfg(target_pointer_width = "64")]
- #[inline]
- fn repeat_byte(b: u8) -> usize {
- let mut rep = (b as usize) << 8 | b as usize;
- rep = rep << 16 | rep;
- rep = rep << 32 | rep;
- rep
- }
- /// Return the first index matching the byte `a` in `text`.
- pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
- // Scan for a single byte value by reading two `usize` words at a time.
- //
- // Split `text` in three parts
- // - unaligned initial part, before the first word aligned address in text
- // - body, scan by 2 words at a time
- // - the last remaining part, < 2 word size
- let len = text.len();
- let ptr = text.as_ptr();
- let usize_bytes = mem::size_of::<usize>();
- // search up to an aligned boundary
- let mut offset = ptr.align_offset(usize_bytes);
- if offset > 0 {
- offset = cmp::min(offset, len);
- if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
- return Some(index);
- }
- }
- // search the body of the text
- let repeated_x = repeat_byte(x);
- if len >= 2 * usize_bytes {
- while offset <= len - 2 * usize_bytes {
- unsafe {
- let u = *(ptr.offset(offset as isize) as *const usize);
- let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
- // break if there is a matching byte
- let zu = contains_zero_byte(u ^ repeated_x);
- let zv = contains_zero_byte(v ^ repeated_x);
- if zu || zv {
- break;
- }
- }
- offset += usize_bytes * 2;
- }
- }
- // find the byte after the point the body loop stopped
- text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i)
- }
- fn main() {
- let mut buff:Vec<u8> = Vec::new();
- buff.resize(1024*1024*512, 0);
- buff[1024*1024*510] = 7;
- buff[1024*1024*128] = 77;
- for _ in 0..8 {
- match memchr(7, buff.as_slice()) {
- Some(x) => {
- println!("{}", x);
- },
- None => {
- println!("0";
- }
- }
- }
- for _ in 0..8 {
- match memchr(7, buff.as_slice()) {
- Some(x) => {
- println!("{}", x);
- },
- None => {
- println!("0";
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement