aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFenrir <[email protected]>2017-07-07 11:39:39 -0600
committerFenrir <[email protected]>2017-07-07 12:38:43 -0600
commiteec80b496b8de2ee332b4ae04fbe00c7c93525b3 (patch)
treef809316596ccf906c46c420c72fadbc568db871f
parentMerge pull request #30 from kentaromiura/compile_again (diff)
downloadctru-rs-eec80b496b8de2ee332b4ae04fbe00c7c93525b3.tar.xz
ctru-rs-eec80b496b8de2ee332b4ae04fbe00c7c93525b3.zip
Use libc from crates.io
The libc crate has newlib bindings now, so we don't have to maintain them in-tree anymore
-rw-r--r--ctr-libc/Cargo.toml14
-rw-r--r--ctr-libc/README.md1
-rw-r--r--ctr-libc/src/constants.rs131
-rw-r--r--ctr-libc/src/functions.rs39
-rw-r--r--ctr-libc/src/lib.rs177
-rw-r--r--ctr-std/Cargo.toml7
-rw-r--r--ctr-std/src/lib.rs2
-rw-r--r--ctr-std/src/sys/unix/memchr.rs21
-rw-r--r--ctr-std/src/sys_common/memchr.rs230
-rw-r--r--ctr-std/src/sys_common/mod.rs5
-rw-r--r--ctru-sys/Cargo.toml5
-rw-r--r--ctru-sys/src/lib.rs2
12 files changed, 244 insertions, 390 deletions
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 <[email protected]>", "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 <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 }
-}
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<usize> {
}
pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-
- #[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<usize> {
- 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 <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..]));
+ }
+ }
+}
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: FnOnce() + Send + 'static>(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 <[email protected]>"]
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;