diff --git a/Cargo.lock b/Cargo.lock index b9ae70624b63502eca9408daea085773b2af9087..a0ced709f752811ba5efd6ce031b9a22dda7ab43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -507,6 +507,7 @@ name = "string" version = "0.1.0" dependencies = [ "cbindgen 0.5.0", + "compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins.git)", "errno 0.1.0", "platform 0.1.0", "stdlib 0.1.0", diff --git a/src/stdlib/src/lib.rs b/src/stdlib/src/lib.rs index dea8dbd13a4b17def216925f39324048faca1c66..228f561da69303d49bf749bd97bea7a96c3b6eb9 100644 --- a/src/stdlib/src/lib.rs +++ b/src/stdlib/src/lib.rs @@ -23,8 +23,29 @@ pub const EXIT_SUCCESS: c_int = 0; static mut ATEXIT_FUNCS: [Option<extern "C" fn()>; 32] = [None; 32]; #[no_mangle] -pub extern "C" fn a64l(s: *const c_char) -> c_long { - unimplemented!(); +pub unsafe extern "C" fn a64l(s: *const c_char) -> c_long { + if s as isize == 0 { + return 0; + } + let mut l: c_long = 0; + for x in 0..7 { + let c = *((s as isize + x) as *const c_char); + if c == 0 { + // string is null terminated + return l; + } + // ASCII to base64 conversion: + let mut bits: c_long = if c < 58 { + (c - 46) as c_long // ./0123456789 + } else if c < 91 { + (c - 53) as c_long // A-Z + } else { + (c - 59) as c_long // a-z + }; + bits <<= 6 * x; + l |= bits; + } + return l; } #[no_mangle] diff --git a/tests/.gitignore b/tests/.gitignore index c5a743e74f6964efc7476545fcce4229e2653fc7..d0bc0d66b343fcc3e240bfbcf4eb4d1a286f25a5 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -29,6 +29,7 @@ /setid /sprintf /stdlib/strtol +/stdlib/a64l /string/strncmp /string/strcspn /string/strchr diff --git a/tests/Makefile b/tests/Makefile index ea41ffa7a2a7761ab75e4e116579d9ef4276f051..8a626402c063dec9558d912e76b33b1d0906d024 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -24,6 +24,7 @@ BINS=\ sleep \ sprintf \ stdlib/strtol \ + stdlib/a64l \ string/strncmp \ string/strcspn \ string/strchr \ diff --git a/tests/stdlib/a64l.c b/tests/stdlib/a64l.c new file mode 100644 index 0000000000000000000000000000000000000000..8036d9e3fb0c85391effadde4986a17fc66d8bbc --- /dev/null +++ b/tests/stdlib/a64l.c @@ -0,0 +1,22 @@ +#include <stdlib.h> +#include <stdio.h> + +int main(int argc, char* argv[]) { + char * s = "azAZ9."; // test boundaries + long l = a64l(s); + if (l != 194301926) { + printf("Invalid result: a64l(%s) = %ld\n", s, l); + return 1; + } + printf("Correct a64l: %s = %ld\n", s, l); + + + s = "azA"; // test null terminated string + l = a64l(s); + if (l != 53222) { + printf("Invalid result: a64l(%s) = %ld\n", s, l); + return 1; + } + printf("Correct a64l: %s = %ld\n", s, l); + return 0; +}