From d4d808fcc81ba5e6e08dadca832da901ce0e2aaa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20W=C3=BCrl?= <bastiwuerl@gmail.com>
Date: Sun, 11 Mar 2018 11:48:05 +0100
Subject: [PATCH] Add implementation for a64l

---
 Cargo.lock            |  1 +
 src/stdlib/src/lib.rs | 25 +++++++++++++++++++++++--
 tests/.gitignore      |  1 +
 tests/Makefile        |  1 +
 tests/stdlib/a64l.c   | 22 ++++++++++++++++++++++
 5 files changed, 48 insertions(+), 2 deletions(-)
 create mode 100644 tests/stdlib/a64l.c

diff --git a/Cargo.lock b/Cargo.lock
index b9ae70624..a0ced709f 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 dea8dbd13..228f561da 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 c5a743e74..d0bc0d66b 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 ea41ffa7a..8a626402c 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 000000000..8036d9e3f
--- /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;
+}
-- 
GitLab