From eec80b496b8de2ee332b4ae04fbe00c7c93525b3 Mon Sep 17 00:00:00 2001 From: Fenrir Date: Fri, 7 Jul 2017 11:39:39 -0600 Subject: [PATCH] Use libc from crates.io The libc crate has newlib bindings now, so we don't have to maintain them in-tree anymore --- ctr-libc/Cargo.toml | 14 -- ctr-libc/README.md | 1 - ctr-libc/src/constants.rs | 131 ------------------ ctr-libc/src/functions.rs | 39 ------ ctr-libc/src/lib.rs | 177 ------------------------ ctr-std/Cargo.toml | 7 +- ctr-std/src/lib.rs | 2 +- ctr-std/src/sys/unix/memchr.rs | 21 +-- ctr-std/src/sys_common/memchr.rs | 230 +++++++++++++++++++++++++++++++ ctr-std/src/sys_common/mod.rs | 5 +- ctru-sys/Cargo.toml | 5 +- ctru-sys/src/lib.rs | 2 +- 12 files changed, 244 insertions(+), 390 deletions(-) delete mode 100644 ctr-libc/Cargo.toml delete mode 100644 ctr-libc/README.md delete mode 100644 ctr-libc/src/constants.rs delete mode 100644 ctr-libc/src/functions.rs delete mode 100644 ctr-libc/src/lib.rs create mode 100644 ctr-std/src/sys_common/memchr.rs diff --git a/ctr-libc/Cargo.toml b/ctr-libc/Cargo.toml deleted file mode 100644 index 5bc4c6b..0000000 --- a/ctr-libc/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "ctr-libc" -version = "0.1.0" -authors = ["Fenrir ", "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 = [] diff --git a/ctr-libc/README.md b/ctr-libc/README.md deleted file mode 100644 index ce5eb41..0000000 --- a/ctr-libc/README.md +++ /dev/null @@ -1 +0,0 @@ -Extended libc bindings for use with ctr-std. This library is experimental. Use of some functions might result in undefined symbols. diff --git a/ctr-libc/src/constants.rs b/ctr-libc/src/constants.rs deleted file mode 100644 index 7da4842..0000000 --- a/ctr-libc/src/constants.rs +++ /dev/null @@ -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; diff --git a/ctr-libc/src/functions.rs b/ctr-libc/src/functions.rs deleted file mode 100644 index a0d21ac..0000000 --- a/ctr-libc/src/functions.rs +++ /dev/null @@ -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; -} diff --git a/ctr-libc/src/lib.rs b/ctr-libc/src/lib.rs deleted file mode 100644 index 50ead9d..0000000 --- a/ctr-libc/src/lib.rs +++ /dev/null @@ -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 or the MIT license -// , 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 } -} diff --git a/ctr-std/Cargo.toml b/ctr-std/Cargo.toml index b7f6da1..8f3bb7e 100644 --- a/ctr-std/Cargo.toml +++ b/ctr-std/Cargo.toml @@ -6,11 +6,12 @@ license = "MIT/Apache 2.0" [dependencies.compiler_builtins] git = "https://github.com/rust-lang-nursery/compiler-builtins" -[dependencies.ctr-libc] -path = "../ctr-libc" +[dependencies.libc] +version = "0.2" +default-features = false [dependencies.ctru-sys] path = "../ctru-sys" [dependencies.alloc_system] -version = "0.1.1" +version = "0.1" diff --git a/ctr-std/src/lib.rs b/ctr-std/src/lib.rs index 7a520b8..de28fc1 100644 --- a/ctr-std/src/lib.rs +++ b/ctr-std/src/lib.rs @@ -63,12 +63,12 @@ extern crate collections as core_collections; extern crate alloc; extern crate std_unicode; extern crate alloc_system; +extern crate libc; // compiler-rt intrinsics extern crate compiler_builtins; // 3ds-specific dependencies -extern crate ctr_libc as libc; extern crate ctru_sys as libctru; // The standard macros that are not built-in to the compiler. diff --git a/ctr-std/src/sys/unix/memchr.rs b/ctr-std/src/sys/unix/memchr.rs index d7e9c2b..ae8e3d0 100644 --- a/ctr-std/src/sys/unix/memchr.rs +++ b/ctr-std/src/sys/unix/memchr.rs @@ -28,24 +28,11 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option { } pub fn memrchr(needle: u8, haystack: &[u8]) -> Option { - - #[cfg(target_os = "linux")] + // turns out that newlib doesn't have memrchr(), so we + // use the fallback version instead fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option { - use libc; - - // GNU's memrchr() will - unlike memchr() - error if haystack is empty. - if haystack.is_empty() {return None} - let p = unsafe { - libc::memrchr( - haystack.as_ptr() as *const libc::c_void, - needle as libc::c_int, - haystack.len()) - }; - if p.is_null() { - None - } else { - Some(p as usize - (haystack.as_ptr() as usize)) - } + ::sys_common::memchr::fallback::memrchr(needle, haystack) } + memrchr_specific(needle, haystack) } diff --git a/ctr-std/src/sys_common/memchr.rs b/ctr-std/src/sys_common/memchr.rs new file mode 100644 index 0000000..3824a5f --- /dev/null +++ b/ctr-std/src/sys_common/memchr.rs @@ -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 or the MIT license +// , 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 { + // 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::(); + + // 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 { + // 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::(); + + // 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..])); + } + } +} diff --git a/ctr-std/src/sys_common/mod.rs b/ctr-std/src/sys_common/mod.rs index 936ff80..6f47466 100644 --- a/ctr-std/src/sys_common/mod.rs +++ b/ctr-std/src/sys_common/mod.rs @@ -27,6 +27,7 @@ pub mod at_exit_imp; pub mod condvar; pub mod io; +pub mod memchr; pub mod mutex; pub mod poison; pub mod remutex; @@ -76,10 +77,6 @@ pub fn at_exit(f: F) -> Result<(), ()> { if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())} } -macro_rules! rtabort { - ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*))) -} - // Computes (value*numer)/denom without overflow, as long as both // (numer*denom) and the overall result fit into i64 (which is the case // for our time conversions). diff --git a/ctru-sys/Cargo.toml b/ctru-sys/Cargo.toml index 99e347b..38eeca8 100644 --- a/ctru-sys/Cargo.toml +++ b/ctru-sys/Cargo.toml @@ -4,5 +4,6 @@ version = "0.3.0" authors = ["Ronald Kinard "] license = "https://en.wikipedia.org/wiki/Zlib_License" -[dependencies] -ctr-libc = { path = "../ctr-libc" } +[dependencies.libc] +version = "0.2" +default-features = false diff --git a/ctru-sys/src/lib.rs b/ctru-sys/src/lib.rs index 5bbc54d..d2b54aa 100644 --- a/ctru-sys/src/lib.rs +++ b/ctru-sys/src/lib.rs @@ -8,7 +8,7 @@ #![allow(non_camel_case_types, non_snake_case, overflowing_literals)] #![feature(untagged_unions)] -extern crate ctr_libc as libc; +extern crate libc; pub mod applets; pub mod console;