Merge branch 'l64a' into 'master'
Implement l64a() See merge request redox-os/relibc!227
This commit is contained in:
+40
-10
@@ -35,6 +35,7 @@ pub const MB_CUR_MAX: c_int = 4;
|
||||
pub const MB_LEN_MAX: c_int = 4;
|
||||
|
||||
static mut ATEXIT_FUNCS: [Option<extern "C" fn()>; 32] = [None; 32];
|
||||
static mut L64A_BUFFER: [c_char; 7] = [0; 7]; // up to 6 digits plus null terminator
|
||||
static mut RNG: Option<XorShiftRng> = None;
|
||||
|
||||
lazy_static! {
|
||||
@@ -51,26 +52,27 @@ pub unsafe extern "C" fn a64l(s: *const c_char) -> c_long {
|
||||
if s.is_null() {
|
||||
return 0;
|
||||
}
|
||||
let mut l: c_long = 0;
|
||||
// POSIX says only the low-order 32 bits are used.
|
||||
let mut l: i32 = 0;
|
||||
// a64l does not support more than 6 characters at once
|
||||
for x in 0..6 {
|
||||
let c = *s.offset(x);
|
||||
if c == 0 {
|
||||
// string is null terminated
|
||||
return l;
|
||||
return c_long::from(l);
|
||||
}
|
||||
// ASCII to base64 conversion:
|
||||
let mut bits: c_long = if c < 58 {
|
||||
(c - 46) as c_long // ./0123456789
|
||||
let mut bits: i32 = if c < 58 {
|
||||
(c - 46) as i32 // ./0123456789
|
||||
} else if c < 91 {
|
||||
(c - 53) as c_long // A-Z
|
||||
(c - 53) as i32 // A-Z
|
||||
} else {
|
||||
(c - 59) as c_long // a-z
|
||||
(c - 59) as i32 // a-z
|
||||
};
|
||||
bits <<= 6 * x;
|
||||
l |= bits;
|
||||
}
|
||||
l
|
||||
c_long::from(l)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -368,9 +370,37 @@ pub unsafe extern "C" fn jrand48(xsubi: *mut c_ushort) -> c_long {
|
||||
lcg48::int32_from_x(new_xi)
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn l64a(value: c_long) -> *mut c_char {
|
||||
unimplemented!();
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn l64a(value: c_long) -> *mut c_char {
|
||||
// POSIX says we should only consider the lower 32 bits of value.
|
||||
let value_as_i32 = value as i32;
|
||||
|
||||
/* If we pretend to extend the 32-bit value with 4 binary zeros, we
|
||||
* would get a 36-bit integer. The number of base-64 digits to be
|
||||
* left unused can then be found by taking the number of leading
|
||||
* zeros, dividing by 6 and rounding down (i.e. using integer
|
||||
* division). */
|
||||
let num_output_digits = 6 - (value_as_i32.leading_zeros() + 4) / 6;
|
||||
|
||||
// Reset buffer (and have null terminator in place for any result)
|
||||
L64A_BUFFER = [0; 7];
|
||||
|
||||
for i in 0..num_output_digits as usize {
|
||||
let digit_value = ((value_as_i32 >> 6 * i) & 63) as c_char;
|
||||
|
||||
if digit_value < 12 {
|
||||
// ./0123456789 for values 0 to 11. b'.' == 46
|
||||
L64A_BUFFER[i] = 46 + digit_value;
|
||||
} else if digit_value < 38 {
|
||||
// A-Z for values 12 to 37. b'A' == 65, 65-12 == 53
|
||||
L64A_BUFFER[i] = 53 + digit_value;
|
||||
} else {
|
||||
// a-z for values 38 to 63. b'a' == 97, 97-38 == 59
|
||||
L64A_BUFFER[i] = 59 + digit_value;
|
||||
}
|
||||
}
|
||||
|
||||
L64A_BUFFER.as_mut_ptr()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -1,2 +1,42 @@
|
||||
Correct a64l: azAZ9. = 194301926
|
||||
Correct a64l: azA = 53222
|
||||
l64a(0):
|
||||
l64a(1): /
|
||||
l64a(2): 0
|
||||
l64a(11): 9
|
||||
l64a(12): A
|
||||
l64a(37): Z
|
||||
l64a(38): a
|
||||
l64a(63): z
|
||||
l64a(64): ./
|
||||
l64a(65): //
|
||||
l64a(4095): zz
|
||||
l64a(4096): ../
|
||||
l64a(262143): zzz
|
||||
l64a(262144): .../
|
||||
l64a(16777215): zzzz
|
||||
l64a(16777216): ..../
|
||||
l64a(1073741823): zzzzz
|
||||
l64a(1073741824): ...../
|
||||
l64a(2147483647): zzzzz/
|
||||
a64l(l64a(0)): 0
|
||||
a64l(l64a(1)): 1
|
||||
a64l(l64a(2)): 2
|
||||
a64l(l64a(11)): 11
|
||||
a64l(l64a(12)): 12
|
||||
a64l(l64a(37)): 37
|
||||
a64l(l64a(38)): 38
|
||||
a64l(l64a(63)): 63
|
||||
a64l(l64a(64)): 64
|
||||
a64l(l64a(65)): 65
|
||||
a64l(l64a(4095)): 4095
|
||||
a64l(l64a(4096)): 4096
|
||||
a64l(l64a(262143)): 262143
|
||||
a64l(l64a(262144)): 262144
|
||||
a64l(l64a(16777215)): 16777215
|
||||
a64l(l64a(16777216)): 16777216
|
||||
a64l(l64a(1073741823)): 1073741823
|
||||
a64l(l64a(1073741824)): 1073741824
|
||||
a64l(l64a(2147483647)): 2147483647
|
||||
l64a(x) (lower 32 bits of x are 1985229328): E61Jq/
|
||||
a64l(l64a(x)) (lower 32 bits of x are 1985229328): 1985229328
|
||||
|
||||
@@ -20,4 +20,34 @@ int main(void) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
printf("Correct a64l: %s = %ld\n", s, l);
|
||||
|
||||
/* Test near boundaries of digit character mapping, and near
|
||||
* boundaries for number of digits */
|
||||
long l64a_test_values[] = {0, 1, 2, 11, 12, 37, \
|
||||
38, 63, \
|
||||
64, 65, 4095, \
|
||||
4096, 262143, \
|
||||
262144, 16777215, \
|
||||
16777216, 1073741823, \
|
||||
1073741824, 2147483647};
|
||||
|
||||
// l64a tests
|
||||
for (size_t i = 0; i < sizeof(l64a_test_values)/sizeof(long); i++) {
|
||||
printf("l64a(%ld): %s\n", l64a_test_values[i], l64a(l64a_test_values[i]));
|
||||
}
|
||||
|
||||
// a64l(l64a(x)) round-trip tests
|
||||
for (size_t i = 0; i < sizeof(l64a_test_values)/sizeof(long); i++) {
|
||||
printf("a64l(l64a(%ld)): %ld\n", l64a_test_values[i], a64l(l64a(l64a_test_values[i])));
|
||||
}
|
||||
|
||||
/* For testing 32-bit truncation behavior (for platforms where long
|
||||
* is larger than 32 bits). Note that the behavior for a64l() and
|
||||
* l64a() is unspecified for negative values. */
|
||||
int64_t test_value_64bit = 0x7edcba9876543210;
|
||||
printf("l64a(x) (lower 32 bits of x are %ld): %s\n", ((long)test_value_64bit) & 0xffffffff, l64a((long)test_value_64bit));
|
||||
|
||||
/* Test for trunctation in l64a(a64(x)) round trip (POSIX says the
|
||||
* result of that is "x in the low-order 32-bits". */
|
||||
printf("a64l(l64a(x)) (lower 32 bits of x are %ld): %ld\n", ((long)test_value_64bit) & 0xffffffff, a64l(l64a((long)test_value_64bit)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user