Browse Source
The libc crate has newlib bindings now, so we don't have to maintain them in-tree anymorepull/10/head
Fenrir
8 years ago
12 changed files with 244 additions and 390 deletions
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
[package] |
||||
name = "ctr-libc" |
||||
version = "0.1.0" |
||||
authors = ["Fenrir <fenrirwolf@gmail.com>", "The Rust Project Developers"] |
||||
license = "MIT/Apache 2.0" |
||||
|
||||
description = """ |
||||
A library for types and bindings to native C functions found in newlib |
||||
for devkitARM |
||||
""" |
||||
|
||||
[features] |
||||
default = ["use_std"] |
||||
use_std = [] |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
Extended libc bindings for use with ctr-std. This library is experimental. Use of some functions might result in undefined symbols. |
@ -1,131 +0,0 @@
@@ -1,131 +0,0 @@
|
||||
// Many of these constants are unused/unnecessary. But let's keep them around for now.
|
||||
|
||||
pub const STDIN_FILENO: ::c_int = 0; |
||||
pub const STDOUT_FILENO: ::c_int = 1; |
||||
pub const STDERR_FILENO: ::c_int = 2; |
||||
|
||||
pub const EPERM: ::c_int = 1; |
||||
pub const ENOENT: ::c_int = 2; |
||||
pub const ESRCH: ::c_int = 3; |
||||
pub const EINTR: ::c_int = 4; |
||||
pub const EIO: ::c_int = 5; |
||||
pub const ENXIO: ::c_int = 6; |
||||
pub const E2BIG: ::c_int = 7; |
||||
pub const ENOEXEC: ::c_int = 8; |
||||
pub const EBADF: ::c_int = 9; |
||||
pub const ECHILD: ::c_int = 10; |
||||
pub const EAGAIN: ::c_int = 11; |
||||
pub const ENOMEM: ::c_int = 12; |
||||
pub const EACCES: ::c_int = 13; |
||||
pub const EFAULT: ::c_int = 14; |
||||
pub const EBUSY: ::c_int = 16; |
||||
pub const EEXIST: ::c_int = 17; |
||||
pub const EXDEV: ::c_int = 18; |
||||
pub const ENODEV: ::c_int = 19; |
||||
pub const ENOTDIR: ::c_int = 20; |
||||
pub const EISDIR: ::c_int = 21; |
||||
pub const EINVAL: ::c_int = 22; |
||||
pub const ENFILE: ::c_int = 23; |
||||
pub const EMFILE: ::c_int = 24; |
||||
pub const ENOTTY: ::c_int = 25; |
||||
pub const ETXTBSY: ::c_int = 26; |
||||
pub const EFBIG: ::c_int = 27; |
||||
pub const ENOSPC: ::c_int = 28; |
||||
pub const ESPIPE: ::c_int = 29; |
||||
pub const EROFS: ::c_int = 30; |
||||
pub const EMLINK: ::c_int = 31; |
||||
pub const EPIPE: ::c_int = 32; |
||||
pub const EDOM: ::c_int = 33; |
||||
pub const ERANGE: ::c_int = 34; |
||||
pub const ENOMSG: ::c_int = 35; |
||||
pub const EIDRM: ::c_int = 36; |
||||
pub const EDEADLK: ::c_int = 45; |
||||
pub const ENOLCK: ::c_int = 46; |
||||
pub const ENOSTR: ::c_int = 60; |
||||
pub const ENODATA: ::c_int = 61; |
||||
pub const ETIME: ::c_int = 62; |
||||
pub const ENOSR: ::c_int = 63; |
||||
pub const ENOLINK: ::c_int = 67; |
||||
pub const EPROTO: ::c_int = 71; |
||||
pub const EMULTIHOP: ::c_int = 74; |
||||
pub const EBADMSG: ::c_int = 77; |
||||
pub const EFTYPE: ::c_int = 79; |
||||
pub const ENOSYS: ::c_int = 88; |
||||
pub const ENOTEMPTY: ::c_int = 90; |
||||
pub const ENAMETOOLONG: ::c_int = 91; |
||||
pub const ELOOP: ::c_int = 92; |
||||
pub const EOPNOTSUPP: ::c_int = 95; |
||||
pub const EPFNOSUPPORT: ::c_int = 96; |
||||
pub const ECONNRESET: ::c_int = 104; |
||||
pub const ENOBUFS: ::c_int = 105; |
||||
pub const EAFNOSUPPORT: ::c_int = 106; |
||||
pub const EPROTOTYPE: ::c_int = 107; |
||||
pub const ENOTSOCK: ::c_int = 108; |
||||
pub const ENOPROTOOPT: ::c_int = 109; |
||||
pub const ECONNREFUSED: ::c_int = 111; |
||||
pub const EADDRINUSE: ::c_int = 112; |
||||
pub const ECONNABORTED: ::c_int = 113; |
||||
pub const ENETUNREACH: ::c_int = 114; |
||||
pub const ENETDOWN: ::c_int = 115; |
||||
pub const ETIMEDOUT: ::c_int = 116; |
||||
pub const EHOSTDOWN: ::c_int = 117; |
||||
pub const EHOSTUNREACH: ::c_int = 118; |
||||
pub const EINPROGRESS: ::c_int = 119; |
||||
pub const EALREADY: ::c_int = 120; |
||||
pub const EDESTADDRREQ: ::c_int = 121; |
||||
pub const EMSGSIZE: ::c_int = 122; |
||||
pub const EPROTONOSUPPORT: ::c_int = 123; |
||||
pub const EADDRNOTAVAIL: ::c_int = 125; |
||||
pub const ENETRESET: ::c_int = 126; |
||||
pub const EISCONN: ::c_int = 127; |
||||
pub const ENOTCONN: ::c_int = 128; |
||||
pub const ETOOMANYREFS: ::c_int = 129; |
||||
pub const EDQUOT: ::c_int = 132; |
||||
pub const ESTALE: ::c_int = 133; |
||||
pub const ENOTSUP: ::c_int = 134; |
||||
pub const EILSEQ: ::c_int = 138; |
||||
pub const EOVERFLOW: ::c_int = 139; |
||||
pub const ECANCELED: ::c_int = 140; |
||||
pub const ENOTRECOVERABLE: ::c_int = 141; |
||||
pub const EOWNERDEAD: ::c_int = 142; |
||||
pub const EWOULDBLOCK: ::c_int = 11; |
||||
pub const __ELASTERROR: ::c_int = 2000; |
||||
|
||||
pub const O_RDONLY: ::c_int = 0; |
||||
pub const O_WRONLY: ::c_int = 1; |
||||
pub const O_RDWR: ::c_int = 2; |
||||
pub const O_APPEND: ::c_int = 8; |
||||
pub const O_CREAT: ::c_int = 512; |
||||
pub const O_TRUNC: ::c_int = 1024; |
||||
pub const O_EXCL: ::c_int = 2048; |
||||
pub const O_SYNC: ::c_int = 8192; |
||||
pub const O_NONBLOCK: ::c_int = 16384; |
||||
pub const O_NOCTTY: ::c_int = 32768; |
||||
pub const FD_CLOEXEC: ::c_int = 1; |
||||
|
||||
pub const S_IFIFO: ::mode_t = 4096; |
||||
pub const S_IFCHR: ::mode_t = 8192; |
||||
pub const S_IFDIR: ::mode_t = 16384; |
||||
pub const S_IFBLK: ::mode_t = 24576; |
||||
pub const S_IFREG: ::mode_t = 32768; |
||||
pub const S_IFLNK: ::mode_t = 40960; |
||||
pub const S_IFSOCK: ::mode_t = 49152; |
||||
pub const S_IFMT: ::mode_t = 61440; |
||||
|
||||
pub const DT_FIFO: u8 = 1; |
||||
pub const DT_CHR: u8 = 2; |
||||
pub const DT_DIR: u8 = 4; |
||||
pub const DT_BLK: u8 = 6; |
||||
pub const DT_REG: u8 = 8; |
||||
pub const DT_LNK: u8 = 10; |
||||
pub const DT_SOCK: u8 = 12; |
||||
|
||||
pub const O_CLOEXEC: ::c_int = 0x80000; |
||||
pub const O_ACCMODE: ::c_int = 3; |
||||
|
||||
pub const SEEK_SET: ::c_int = 0; |
||||
pub const SEEK_CUR: ::c_int = 1; |
||||
pub const SEEK_END: ::c_int = 2; |
||||
|
||||
pub const SIG_IGN: ::sighandler_t = 1 as ::sighandler_t; |
||||
pub const SIGPIPE: ::c_int = 13; |
@ -1,39 +0,0 @@
@@ -1,39 +0,0 @@
|
||||
extern "C" { |
||||
pub fn abort() -> !; |
||||
pub fn chdir(dir: *const ::c_char) -> ::c_int; |
||||
pub fn chmod(path: *const ::c_char, mode: ::mode_t) -> ::c_int; |
||||
pub fn close(fd: ::c_int) -> ::c_int; |
||||
pub fn closedir(dirp: *mut ::DIR) -> ::c_int; |
||||
pub fn exit(status: ::c_int) -> !; |
||||
pub fn fchmod(fd: ::c_int, mode: ::mode_t) -> ::c_int; |
||||
pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int; |
||||
pub fn fdatasync(fd: ::c_int) -> ::c_int; |
||||
pub fn free(p: *mut ::c_void); |
||||
pub fn fstat(fildes: ::c_int, buf: *mut ::stat) -> ::c_int; |
||||
pub fn ftruncate(fd: ::c_int, length: ::off_t) -> ::c_int; |
||||
pub fn fsync(fd: ::c_int) -> ::c_int; |
||||
pub fn getcwd(buf: *mut ::c_char, size: ::size_t) -> *mut ::c_char; |
||||
pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; |
||||
pub fn link(src: *const ::c_char, dst: *const ::c_char) -> ::c_int; |
||||
pub fn lstat(path: *const ::c_char, buf: *mut ::stat) -> ::c_int; |
||||
pub fn lseek(fd: ::c_int, offset: ::off_t, whence: ::c_int) -> ::off_t; |
||||
pub fn memchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; |
||||
pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; |
||||
pub fn mkdir(path: *const ::c_char, mode: ::mode_t) -> ::c_int; |
||||
pub fn open(path: *const ::c_char, oflag: ::c_int, ...) -> ::c_int; |
||||
pub fn opendir(dirname: *const ::c_char) -> *mut ::DIR; |
||||
pub fn pread(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: ::off_t) -> ::ssize_t; |
||||
pub fn pwrite(fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: ::off_t) -> ::ssize_t; |
||||
pub fn read(fd: ::c_int, puf: *mut ::c_void, count: ::size_t) -> ::ssize_t; |
||||
pub fn readlink(path: *const ::c_char, buf: *mut ::c_char, bufsz: ::size_t) -> ::ssize_t; |
||||
pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent, result: *mut *mut ::dirent) -> ::c_int; |
||||
pub fn realpath(pathname: *const ::c_char, resolved: *mut ::c_char) -> *mut ::c_char; |
||||
pub fn rename(oldname: *const ::c_char, newname: *const ::c_char) -> ::c_int; |
||||
pub fn rmdir(path: *const ::c_char) -> ::c_int; |
||||
pub fn signal(signum: ::c_int, handler: ::sighandler_t) -> ::sighandler_t; |
||||
pub fn stat(path: *const ::c_char, buf: *mut ::stat) -> ::c_int; |
||||
pub fn strlen(cs: *const ::c_char) -> ::size_t; |
||||
pub fn symlink(path1: *const ::c_char, path2: *const ::c_char) -> ::c_int; |
||||
pub fn unlink(c: *const ::c_char) -> ::c_int; |
||||
pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t) -> ::ssize_t; |
||||
} |
@ -1,177 +0,0 @@
@@ -1,177 +0,0 @@
|
||||
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(bad_style, overflowing_literals, improper_ctypes, non_camel_case_types)] |
||||
|
||||
#![no_std] |
||||
|
||||
mod constants; |
||||
mod functions; |
||||
pub use constants::*; |
||||
pub use functions::*; |
||||
|
||||
#[link(name = "c")] |
||||
#[link(name = "m")] |
||||
extern {} |
||||
|
||||
#[repr(u8)] |
||||
pub enum c_void { |
||||
__variant1, |
||||
__variant2, |
||||
} |
||||
|
||||
// char is u8 on ARM
|
||||
pub type c_char = u8; |
||||
pub type c_schar = i8; |
||||
pub type c_uchar = u8; |
||||
pub type c_short = i16; |
||||
pub type c_ushort = u16; |
||||
pub type c_int = i32; |
||||
pub type c_uint = u32; |
||||
pub type c_float = f32; |
||||
pub type c_double = f64; |
||||
pub type c_longlong = i64; |
||||
pub type c_ulonglong = u64; |
||||
|
||||
// 4 bytes on ARM
|
||||
pub type c_long = i32; |
||||
pub type c_ulong = u32; |
||||
|
||||
pub type size_t = usize; |
||||
pub type ptrdiff_t = isize; |
||||
pub type intptr_t = isize; |
||||
pub type uintptr_t = usize; |
||||
pub type ssize_t = isize; |
||||
|
||||
// devkitARM says wchar_t is 4 bytes. Nintendo's API says it's 2 bytes.
|
||||
// hope you never have to interact between the two...
|
||||
pub type wchar_t = c_int; |
||||
|
||||
pub type int8_t = i8; |
||||
pub type uint8_t = u8; |
||||
pub type int16_t = i16; |
||||
pub type uint16_t = u16; |
||||
pub type int32_t = i32; |
||||
pub type uint32_t = u32; |
||||
pub type int64_t = i64; |
||||
pub type uint64_t = u64; |
||||
|
||||
pub type time_t = i32; |
||||
pub type clockid_t = c_int; |
||||
pub type mode_t = u32; |
||||
pub type sighandler_t = size_t; |
||||
pub type dev_t = u32; |
||||
pub type nlink_t = u32; |
||||
pub type uid_t = u32; |
||||
pub type gid_t = u32; |
||||
pub type off_t = i64; |
||||
pub type blksize_t = i32; |
||||
pub type blkcnt_t = c_ulong; |
||||
pub type fsblkcnt_t = uint64_t; |
||||
pub type fsfilcnt_t = uint32_t; |
||||
pub type ino_t = u32; |
||||
pub type suseconds_t = i32; |
||||
pub type error_t = c_int; |
||||
|
||||
pub enum timezone {} |
||||
|
||||
pub enum _reent {} |
||||
|
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct timeval { |
||||
pub tv_sec: time_t, |
||||
pub tv_usec: suseconds_t, |
||||
} |
||||
|
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct timespec { |
||||
pub tv_sec: time_t, |
||||
pub tv_nsec: c_long, |
||||
} |
||||
|
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct itimerspec { |
||||
pub it_interval: timespec, |
||||
pub it_value: timespec, |
||||
} |
||||
|
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct tm { |
||||
pub tm_sec: c_int, |
||||
pub tm_min: c_int, |
||||
pub tm_hour: c_int, |
||||
pub tm_mday: c_int, |
||||
pub tm_mon: c_int, |
||||
pub tm_year: c_int, |
||||
pub tm_wday: c_int, |
||||
pub tm_yday: c_int, |
||||
pub tm_isdst: c_int, |
||||
} |
||||
|
||||
pub enum DIR {} |
||||
|
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct stat { |
||||
pub st_dev: dev_t, |
||||
pub st_ino: ino_t, |
||||
pub st_mode: mode_t, |
||||
pub st_nlink: nlink_t, |
||||
pub st_uid: uid_t, |
||||
pub st_gid: gid_t, |
||||
pub st_rdev: dev_t, |
||||
pub st_size: off_t, |
||||
pub st_atime: time_t, |
||||
pub st_spare1: c_long, |
||||
pub st_mtime: time_t, |
||||
pub st_spare2: c_long, |
||||
pub st_ctime: time_t, |
||||
pub st_spare3: c_long, |
||||
pub st_blksize: blksize_t, |
||||
pub st_blocks: blkcnt_t, |
||||
pub st_spare4: [c_long; 2usize], |
||||
} |
||||
|
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct statvfs { |
||||
pub f_bsize: c_ulong, |
||||
pub f_frsize: c_ulong, |
||||
pub f_blocks: fsblkcnt_t, |
||||
pub f_bfree: fsblkcnt_t, |
||||
pub f_bavail: fsblkcnt_t, |
||||
pub f_files: fsfilcnt_t, |
||||
pub f_ffree: fsfilcnt_t, |
||||
pub f_favail: fsfilcnt_t, |
||||
pub f_fsid: c_ulong, |
||||
pub f_flag: c_ulong, |
||||
pub f_namemax: c_ulong, |
||||
} |
||||
|
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
pub struct dirent { |
||||
pub d_ino: ino_t, |
||||
pub d_type: c_uchar, |
||||
pub d_name: [c_char; 256usize], |
||||
} |
||||
impl Clone for dirent { |
||||
fn clone(&self) -> Self { *self } |
||||
} |
@ -0,0 +1,230 @@
@@ -0,0 +1,230 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// Original implementation taken from rust-memchr
|
||||
// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
|
||||
|
||||
#[allow(dead_code)] |
||||
pub mod fallback { |
||||
use cmp; |
||||
use mem; |
||||
|
||||
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; |
||||
|
||||
/// Return `true` if `x` contains any zero byte.
|
||||
///
|
||||
/// From *Matters Computational*, J. Arndt
|
||||
///
|
||||
/// "The idea is to subtract one from each of the bytes and then look for
|
||||
/// bytes where the borrow propagated all the way to the most significant
|
||||
/// bit."
|
||||
#[inline] |
||||
fn contains_zero_byte(x: usize) -> bool { |
||||
x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0 |
||||
} |
||||
|
||||
#[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 align = (ptr as usize) & (usize_bytes- 1); |
||||
let mut offset; |
||||
if align > 0 { |
||||
offset = cmp::min(usize_bytes - align, len); |
||||
if let Some(index) = text[..offset].iter().position(|elt| *elt == x) { |
||||
return Some(index); |
||||
} |
||||
} else { |
||||
offset = 0; |
||||
} |
||||
|
||||
// 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) |
||||
} |
||||
|
||||
/// Return the last index matching the byte `a` in `text`.
|
||||
pub fn memrchr(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 tail, after the last word aligned address in text
|
||||
// - body, scan by 2 words at a time
|
||||
// - the first remaining bytes, < 2 word size
|
||||
let len = text.len(); |
||||
let ptr = text.as_ptr(); |
||||
let usize_bytes = mem::size_of::<usize>(); |
||||
|
||||
// search to an aligned boundary
|
||||
let end_align = (ptr as usize + len) & (usize_bytes - 1); |
||||
let mut offset; |
||||
if end_align > 0 { |
||||
offset = if end_align >= len { 0 } else { len - end_align }; |
||||
if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) { |
||||
return Some(offset + index); |
||||
} |
||||
} else { |
||||
offset = len; |
||||
} |
||||
|
||||
// search the body of the text
|
||||
let repeated_x = repeat_byte(x); |
||||
|
||||
while offset >= 2 * usize_bytes { |
||||
unsafe { |
||||
let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize); |
||||
let v = *(ptr.offset(offset as isize - 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 -= 2 * usize_bytes; |
||||
} |
||||
|
||||
// find the byte before the point the body loop stopped
|
||||
text[..offset].iter().rposition(|elt| *elt == x) |
||||
} |
||||
|
||||
// test fallback implementations on all platforms
|
||||
#[test] |
||||
fn matches_one() { |
||||
assert_eq!(Some(0), memchr(b'a', b"a")); |
||||
} |
||||
|
||||
#[test] |
||||
fn matches_begin() { |
||||
assert_eq!(Some(0), memchr(b'a', b"aaaa")); |
||||
} |
||||
|
||||
#[test] |
||||
fn matches_end() { |
||||
assert_eq!(Some(4), memchr(b'z', b"aaaaz")); |
||||
} |
||||
|
||||
#[test] |
||||
fn matches_nul() { |
||||
assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00")); |
||||
} |
||||
|
||||
#[test] |
||||
fn matches_past_nul() { |
||||
assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z")); |
||||
} |
||||
|
||||
#[test] |
||||
fn no_match_empty() { |
||||
assert_eq!(None, memchr(b'a', b"")); |
||||
} |
||||
|
||||
#[test] |
||||
fn no_match() { |
||||
assert_eq!(None, memchr(b'a', b"xyz")); |
||||
} |
||||
|
||||
#[test] |
||||
fn matches_one_reversed() { |
||||
assert_eq!(Some(0), memrchr(b'a', b"a")); |
||||
} |
||||
|
||||
#[test] |
||||
fn matches_begin_reversed() { |
||||
assert_eq!(Some(3), memrchr(b'a', b"aaaa")); |
||||
} |
||||
|
||||
#[test] |
||||
fn matches_end_reversed() { |
||||
assert_eq!(Some(0), memrchr(b'z', b"zaaaa")); |
||||
} |
||||
|
||||
#[test] |
||||
fn matches_nul_reversed() { |
||||
assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00")); |
||||
} |
||||
|
||||
#[test] |
||||
fn matches_past_nul_reversed() { |
||||
assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa")); |
||||
} |
||||
|
||||
#[test] |
||||
fn no_match_empty_reversed() { |
||||
assert_eq!(None, memrchr(b'a', b"")); |
||||
} |
||||
|
||||
#[test] |
||||
fn no_match_reversed() { |
||||
assert_eq!(None, memrchr(b'a', b"xyz")); |
||||
} |
||||
|
||||
#[test] |
||||
fn each_alignment_reversed() { |
||||
let mut data = [1u8; 64]; |
||||
let needle = 2; |
||||
let pos = 40; |
||||
data[pos] = needle; |
||||
for start in 0..16 { |
||||
assert_eq!(Some(pos - start), memrchr(needle, &data[start..])); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue