2
0

mod.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. //! string implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/string.h.html
  2. use crate::unix::header::string::slice::memchr;
  3. use crate::unix::header::{errno::*, signal};
  4. use crate::unix::platform;
  5. use cbitset::BitSet256;
  6. use core::{mem, ptr, slice, usize};
  7. #[no_mangle]
  8. pub unsafe extern "C" fn memccpy(
  9. dest: *mut ::c_void,
  10. src: *const ::c_void,
  11. c: ::c_int,
  12. n: ::size_t,
  13. ) -> *mut ::c_void {
  14. let to = memchr(src, c, n);
  15. if to.is_null() {
  16. return to;
  17. }
  18. let dist = (to as usize) - (src as usize);
  19. if memcpy(dest, src, dist).is_null() {
  20. return ptr::null_mut();
  21. }
  22. (dest as *mut u8).add(dist + 1) as *mut ::c_void
  23. }
  24. #[no_mangle]
  25. pub unsafe extern "C" fn memchr(
  26. haystack: *const ::c_void,
  27. needle: ::c_int,
  28. len: ::size_t,
  29. ) -> *mut ::c_void {
  30. let haystack = slice::from_raw_parts(haystack as *const u8, len as usize);
  31. match memchr::memchr(needle as u8, haystack) {
  32. Some(index) => haystack[index..].as_ptr() as *mut ::c_void,
  33. None => ptr::null_mut(),
  34. }
  35. }
  36. #[no_mangle]
  37. pub unsafe extern "C" fn memcmp(s1: *const ::c_void, s2: *const ::c_void, n: ::size_t) -> ::c_int {
  38. let (div, rem) = (n / mem::size_of::<usize>(), n % mem::size_of::<usize>());
  39. let mut a = s1 as *const usize;
  40. let mut b = s2 as *const usize;
  41. for _ in 0..div {
  42. if *a != *b {
  43. for i in 0..mem::size_of::<usize>() {
  44. let c = *(a as *const u8).add(i);
  45. let d = *(b as *const u8).add(i);
  46. if c != d {
  47. return c as ::c_int - d as ::c_int;
  48. }
  49. }
  50. unreachable!()
  51. }
  52. a = a.offset(1);
  53. b = b.offset(1);
  54. }
  55. let mut a = a as *const u8;
  56. let mut b = b as *const u8;
  57. for _ in 0..rem {
  58. if *a != *b {
  59. return *a as ::c_int - *b as ::c_int;
  60. }
  61. a = a.offset(1);
  62. b = b.offset(1);
  63. }
  64. 0
  65. }
  66. #[no_mangle]
  67. pub unsafe extern "C" fn memcpy(
  68. s1: *mut ::c_void,
  69. s2: *const ::c_void,
  70. n: ::size_t,
  71. ) -> *mut ::c_void {
  72. let mut i = 0;
  73. while i + 7 < n {
  74. *(s1.add(i) as *mut u64) = *(s2.add(i) as *const u64);
  75. i += 8;
  76. }
  77. while i < n {
  78. *(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i);
  79. i += 1;
  80. }
  81. s1
  82. }
  83. #[no_mangle]
  84. pub unsafe extern "C" fn memmove(
  85. s1: *mut ::c_void,
  86. s2: *const ::c_void,
  87. n: ::size_t,
  88. ) -> *mut ::c_void {
  89. if s2 < s1 as *const ::c_void {
  90. // copy from end
  91. let mut i = n;
  92. while i != 0 {
  93. i -= 1;
  94. *(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i);
  95. }
  96. } else {
  97. // copy from beginning
  98. let mut i = 0;
  99. while i < n {
  100. *(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i);
  101. i += 1;
  102. }
  103. }
  104. s1
  105. }
  106. #[no_mangle]
  107. pub unsafe extern "C" fn memrchr(
  108. haystack: *const ::c_void,
  109. needle: ::c_int,
  110. len: ::size_t,
  111. ) -> *mut ::c_void {
  112. let haystack = slice::from_raw_parts(haystack as *const u8, len as usize);
  113. match memchr::memrchr(needle as u8, haystack) {
  114. Some(index) => haystack[index..].as_ptr() as *mut ::c_void,
  115. None => ptr::null_mut(),
  116. }
  117. }
  118. #[no_mangle]
  119. pub unsafe extern "C" fn memset(s: *mut ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void {
  120. for i in 0..n {
  121. *(s as *mut u8).add(i) = c as u8;
  122. }
  123. s
  124. }
  125. #[no_mangle]
  126. pub unsafe extern "C" fn strchr(mut s: *const ::c_char, c: ::c_int) -> *mut ::c_char {
  127. let c = c as ::c_char;
  128. while *s != 0 {
  129. if *s == c {
  130. return s as *mut ::c_char;
  131. }
  132. s = s.offset(1);
  133. }
  134. ptr::null_mut()
  135. }
  136. #[no_mangle]
  137. pub unsafe extern "C" fn strcmp(s1: *const ::c_char, s2: *const ::c_char) -> ::c_int {
  138. strncmp(s1, s2, usize::MAX)
  139. }
  140. #[no_mangle]
  141. pub unsafe extern "C" fn strcoll(s1: *const ::c_char, s2: *const ::c_char) -> ::c_int {
  142. // relibc has no locale stuff (yet)
  143. strcmp(s1, s2)
  144. }
  145. #[no_mangle]
  146. pub unsafe extern "C" fn strcpy(dst: *mut ::c_char, src: *const ::c_char) -> *mut ::c_char {
  147. let mut i = 0;
  148. loop {
  149. let byte = *src.offset(i);
  150. *dst.offset(i) = byte;
  151. if byte == 0 {
  152. break;
  153. }
  154. i += 1;
  155. }
  156. dst
  157. }
  158. pub unsafe fn inner_strspn(s1: *const ::c_char, s2: *const ::c_char, cmp: bool) -> ::size_t {
  159. let mut s1 = s1 as *const u8;
  160. let mut s2 = s2 as *const u8;
  161. // The below logic is effectively ripped from the musl implementation. It
  162. // works by placing each byte as it's own bit in an array of numbers. Each
  163. // number can hold up to 8 * mem::size_of::<usize>() bits. We need 256 bits
  164. // in total, to fit one byte.
  165. let mut set = BitSet256::new();
  166. while *s2 != 0 {
  167. set.insert(*s2 as usize);
  168. s2 = s2.offset(1);
  169. }
  170. let mut i = 0;
  171. while *s1 != 0 {
  172. if set.contains(*s1 as usize) != cmp {
  173. break;
  174. }
  175. i += 1;
  176. s1 = s1.offset(1);
  177. }
  178. i
  179. }
  180. #[no_mangle]
  181. pub unsafe extern "C" fn strcspn(s1: *const ::c_char, s2: *const ::c_char) -> ::size_t {
  182. inner_strspn(s1, s2, false)
  183. }
  184. #[no_mangle]
  185. pub unsafe extern "C" fn strdup(s1: *const ::c_char) -> *mut ::c_char {
  186. strndup(s1, usize::MAX)
  187. }
  188. #[no_mangle]
  189. pub unsafe extern "C" fn strndup(s1: *const ::c_char, size: ::size_t) -> *mut ::c_char {
  190. let len = strnlen(s1, size);
  191. // the "+ 1" is to account for the NUL byte
  192. let buffer = platform::alloc(len + 1) as *mut ::c_char;
  193. if buffer.is_null() {
  194. platform::errno = ENOMEM as ::c_int;
  195. } else {
  196. //memcpy(buffer, s1, len)
  197. for i in 0..len {
  198. *buffer.add(i) = *s1.add(i);
  199. }
  200. *buffer.add(len) = 0;
  201. }
  202. buffer
  203. }
  204. #[no_mangle]
  205. pub unsafe extern "C" fn strerror(errnum: ::c_int) -> *mut ::c_char {
  206. use core::fmt::Write;
  207. static mut strerror_buf: [u8; 256] = [0; 256];
  208. let mut w = platform::StringWriter(strerror_buf.as_mut_ptr(), strerror_buf.len());
  209. if errnum >= 0 && errnum < STR_ERROR.len() as ::c_int {
  210. let _ = w.write_str(STR_ERROR[errnum as usize]);
  211. } else {
  212. let _ = w.write_fmt(format_args!("Unknown error {}", errnum));
  213. }
  214. strerror_buf.as_mut_ptr() as *mut ::c_char
  215. }
  216. #[no_mangle]
  217. pub unsafe extern "C" fn strerror_r(
  218. errnum: ::c_int,
  219. buf: *mut ::c_char,
  220. buflen: ::size_t,
  221. ) -> ::c_int {
  222. let msg = strerror(errnum);
  223. let len = strlen(msg);
  224. if len >= buflen {
  225. if buflen != 0 {
  226. memcpy(buf as *mut ::c_void, msg as *const ::c_void, buflen - 1);
  227. *buf.add(buflen - 1) = 0;
  228. }
  229. return ERANGE as ::c_int;
  230. }
  231. memcpy(buf as *mut ::c_void, msg as *const ::c_void, len + 1);
  232. 0
  233. }
  234. #[no_mangle]
  235. pub unsafe extern "C" fn strlen(s: *const ::c_char) -> ::size_t {
  236. strnlen(s, usize::MAX)
  237. }
  238. #[no_mangle]
  239. pub unsafe extern "C" fn strnlen(s: *const ::c_char, size: ::size_t) -> ::size_t {
  240. let mut i = 0;
  241. while i < size {
  242. if *s.add(i) == 0 {
  243. break;
  244. }
  245. i += 1;
  246. }
  247. i as ::size_t
  248. }
  249. #[no_mangle]
  250. pub unsafe extern "C" fn strnlen_s(s: *const ::c_char, size: ::size_t) -> ::size_t {
  251. if s.is_null() {
  252. 0
  253. } else {
  254. strnlen(s, size)
  255. }
  256. }
  257. #[no_mangle]
  258. pub unsafe extern "C" fn strcat(s1: *mut ::c_char, s2: *const ::c_char) -> *mut ::c_char {
  259. strncat(s1, s2, usize::MAX)
  260. }
  261. #[no_mangle]
  262. pub unsafe extern "C" fn strncat(
  263. s1: *mut ::c_char,
  264. s2: *const ::c_char,
  265. n: ::size_t,
  266. ) -> *mut ::c_char {
  267. let len = strlen(s1 as *const ::c_char);
  268. let mut i = 0;
  269. while i < n {
  270. let b = *s2.add(i);
  271. if b == 0 {
  272. break;
  273. }
  274. *s1.add(len + i) = b;
  275. i += 1;
  276. }
  277. *s1.add(len + i) = 0;
  278. s1
  279. }
  280. #[no_mangle]
  281. pub unsafe extern "C" fn strncmp(s1: *const ::c_char, s2: *const ::c_char, n: ::size_t) -> ::c_int {
  282. let s1 = core::slice::from_raw_parts(s1 as *const ::c_uchar, n);
  283. let s2 = core::slice::from_raw_parts(s2 as *const ::c_uchar, n);
  284. for (&a, &b) in s1.iter().zip(s2.iter()) {
  285. let val = (a as ::c_int) - (b as ::c_int);
  286. if a != b || a == 0 {
  287. return val;
  288. }
  289. }
  290. 0
  291. }
  292. #[no_mangle]
  293. pub unsafe extern "C" fn strncpy(
  294. dst: *mut ::c_char,
  295. src: *const ::c_char,
  296. n: ::size_t,
  297. ) -> *mut ::c_char {
  298. let mut i = 0;
  299. while *src.add(i) != 0 && i < n {
  300. *dst.add(i) = *src.add(i);
  301. i += 1;
  302. }
  303. for i in i..n {
  304. *dst.add(i) = 0;
  305. }
  306. dst
  307. }
  308. #[no_mangle]
  309. pub unsafe extern "C" fn strpbrk(s1: *const ::c_char, s2: *const ::c_char) -> *mut ::c_char {
  310. let p = s1.add(strcspn(s1, s2));
  311. if *p != 0 {
  312. p as *mut ::c_char
  313. } else {
  314. ptr::null_mut()
  315. }
  316. }
  317. #[no_mangle]
  318. pub unsafe extern "C" fn strrchr(s: *const ::c_char, c: ::c_int) -> *mut ::c_char {
  319. let len = strlen(s) as isize;
  320. let c = c as i8;
  321. let mut i = len - 1;
  322. while i >= 0 {
  323. if *s.offset(i) == c {
  324. return s.offset(i) as *mut ::c_char;
  325. }
  326. i -= 1;
  327. }
  328. ptr::null_mut()
  329. }
  330. #[no_mangle]
  331. pub unsafe extern "C" fn strsignal(sig: ::c_int) -> *const ::c_char {
  332. signal::_signal_strings
  333. .get(sig as usize)
  334. .unwrap_or(&signal::_signal_strings[0]) // Unknown signal message
  335. .as_ptr() as *const ::c_char
  336. }
  337. #[no_mangle]
  338. pub unsafe extern "C" fn strspn(s1: *const ::c_char, s2: *const ::c_char) -> ::size_t {
  339. inner_strspn(s1, s2, true)
  340. }
  341. unsafe fn inner_strstr(
  342. mut haystack: *const ::c_char,
  343. needle: *const ::c_char,
  344. mask: ::c_char,
  345. ) -> *mut ::c_char {
  346. while *haystack != 0 {
  347. let mut i = 0;
  348. loop {
  349. if *needle.offset(i) == 0 {
  350. // We reached the end of the needle, everything matches this far
  351. return haystack as *mut ::c_char;
  352. }
  353. if *haystack.offset(i) & mask != *needle.offset(i) & mask {
  354. break;
  355. }
  356. i += 1;
  357. }
  358. haystack = haystack.offset(1);
  359. }
  360. ptr::null_mut()
  361. }
  362. #[no_mangle]
  363. pub unsafe extern "C" fn strstr(
  364. haystack: *const ::c_char,
  365. needle: *const ::c_char,
  366. ) -> *mut ::c_char {
  367. inner_strstr(haystack, needle, !0)
  368. }
  369. #[no_mangle]
  370. pub unsafe extern "C" fn strcasestr(
  371. haystack: *const ::c_char,
  372. needle: *const ::c_char,
  373. ) -> *mut ::c_char {
  374. inner_strstr(haystack, needle, !32)
  375. }
  376. #[no_mangle]
  377. pub unsafe extern "C" fn strtok(s1: *mut ::c_char, delimiter: *const ::c_char) -> *mut ::c_char {
  378. static mut HAYSTACK: *mut ::c_char = ptr::null_mut();
  379. strtok_r(s1, delimiter, &mut HAYSTACK)
  380. }
  381. #[no_mangle]
  382. pub unsafe extern "C" fn strtok_r(
  383. s: *mut ::c_char,
  384. delimiter: *const ::c_char,
  385. lasts: *mut *mut ::c_char,
  386. ) -> *mut ::c_char {
  387. // Loosely based on GLIBC implementation
  388. let mut haystack = s;
  389. if haystack.is_null() {
  390. if (*lasts).is_null() {
  391. return ptr::null_mut();
  392. }
  393. haystack = *lasts;
  394. }
  395. // Skip past any extra delimiter left over from previous call
  396. haystack = haystack.add(strspn(haystack, delimiter));
  397. if *haystack == 0 {
  398. *lasts = ptr::null_mut();
  399. return ptr::null_mut();
  400. }
  401. // Build token by injecting null byte into delimiter
  402. let token = haystack;
  403. haystack = strpbrk(token, delimiter);
  404. if !haystack.is_null() {
  405. haystack.write(0);
  406. haystack = haystack.add(1);
  407. *lasts = haystack;
  408. } else {
  409. *lasts = ptr::null_mut();
  410. }
  411. token
  412. }
  413. #[no_mangle]
  414. pub unsafe extern "C" fn strxfrm(s1: *mut ::c_char, s2: *const ::c_char, n: ::size_t) -> ::size_t {
  415. // relibc has no locale stuff (yet)
  416. let len = strlen(s2);
  417. if len < n {
  418. strcpy(s1, s2);
  419. }
  420. len
  421. }
  422. #[no_mangle]
  423. pub unsafe extern "C" fn strlcpy(
  424. dst: *mut ::c_char,
  425. src: *const ::c_char,
  426. n: ::size_t,
  427. ) -> ::size_t {
  428. let mut i = 0;
  429. while *src.add(i) != 0 && i < n {
  430. *dst.add(i) = *src.add(i);
  431. i += 1;
  432. }
  433. *dst.add(i) = 0;
  434. i as ::size_t
  435. }
  436. #[no_mangle]
  437. pub unsafe extern "C" fn strlcat(
  438. dst: *mut ::c_char,
  439. src: *const ::c_char,
  440. n: ::size_t,
  441. ) -> ::size_t {
  442. let len = strlen(dst) as isize;
  443. let d = dst.offset(len);
  444. strlcpy(d, src, n)
  445. }