diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2002-05-06 20:44:54 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2002-05-06 20:44:54 +0000 |
commit | c33c3635f7a20a40af570342d9a7609d4a22c39e (patch) | |
tree | d1ed761cf5ae28675e0529e0cc14f7e072848376 /newlib/libc/stdlib/a64l.c | |
parent | f78e59a8f90f72609c153d4db493c2d43e6ca379 (diff) | |
download | newlib-c33c3635f7a20a40af570342d9a7609d4a22c39e.zip newlib-c33c3635f7a20a40af570342d9a7609d4a22c39e.tar.gz newlib-c33c3635f7a20a40af570342d9a7609d4a22c39e.tar.bz2 |
2002-05-06 Jeff Johnston <jjohnstn@redhat.com>
* libc/include/sys/reent.h (_l64a_buf): New reentrant area.
(_REENT_L64A_BUF): New macro for accessing area.
* libc/stdlib/Makefile.am: Add a64l.c and l64a.c.
* libc/stdlib/Makefile.in: Regenerated.
* libc/stdlib/a64l.c: New file.
* libc/stdlib/l64a.c: New file.
Diffstat (limited to 'newlib/libc/stdlib/a64l.c')
-rw-r--r-- | newlib/libc/stdlib/a64l.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/newlib/libc/stdlib/a64l.c b/newlib/libc/stdlib/a64l.c new file mode 100644 index 0000000..9a56a91 --- /dev/null +++ b/newlib/libc/stdlib/a64l.c @@ -0,0 +1,192 @@ +/* +FUNCTION +<<a64l>>,<<l64a>>---convert between radix-64 ascii string and long + +INDEX + a64l +INDEX + l64a + +ANSI_SYNOPSIS + #include <stdlib.h> + long a64l(const char *<[input]>); + char *l64a(long <[input]>); + +TRAD_SYNOPSIS + #include <stdlib.h> + long a64l(<[input]>) + const char *<[input]>; + + char *l64a(<[input]>) + long <[input]>; + +DESCRIPTION +Conversion is performed between long and radix-64 characters. The <<l64a>> routine +transforms up to 32-bits of input value starting from least significant bits to +the most significant bits. The input value is split up into a maximum of 5 +groups of 6-bits and possibly one group of 2 bits (bits 31 and 30). + +Each group of 6 bits forms a value from 0-63 which is translated into a character +as follows: + + 0 = '.' + 1 = '/' + 2-11 = '0' to '9' + 12-37 = 'A' to 'Z' + 38-63 = 'a' to 'z' + +When remaining bits are zero or all bits have been translated, a nul terminator +is appended to the string. An input value of 0 results in the empty string. + +The <<a64l>> performs the reverse translation. Each character is used to generate +a 6-bit value for up to 30 bits and then a 2-bit value to complete a 32-bit result. +The nul terminator means that the remaining digits are 0. An empty input string or +NULL string results in 0L. An invalid string results in undefined behavior. +If the size of a long is > 32 bits, the result is sign-extended. + +RETURNS +<<l64a>> returns a nul-terminated string of 0 to 6 characters. +<<a64l>> returns the 32-bit translated value from the input character string. + +PORTABILITY +<<l64a>> and <<a64l>> are non-ANSI and are defined by the Single Unix Specification. + +Supporting OS subroutines required: None. +*/ + +#include <_ansi.h> +#include <stdlib.h> +#include <limits.h> + +long +_DEFUN (a64l, (input), + const char *input) +{ + char *ptr; + char ch; + int i, digit; + unsigned long result = 0; + + if (input == NULL) + return 0; + + ptr = input; + + /* it easiest to go from most significant digit to least so find end of input or up + to 6 characters worth */ + for (i = 0; i < 6; ++i) + { + if (*ptr) + ++ptr; + } + + while (ptr > input) + { + ch = *(--ptr); + +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + if (ch >= 'a') + digit = (ch - 'a') + 38; + else if (ch >= 'A') + digit = (ch - 'A') + 12; + else if (ch >= '0') + digit = (ch - '0') + 2; + else if (ch == '/') + digit = 1; + else + digit = 0; +#else /* !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) */ + switch (ch) + { + case '/': + digit = 1; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + digit = (ch - '0') + 2; + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + digit = (ch - 'A') + 12; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + digit = (ch - 'A') + 38; + break; + default: + digit = 0; + break; + } +#endif /* !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) */ + + result = (result << 6) + digit; + } + +#if LONG_MAX > 2147483647 + /* for implementations where long is > 32 bits, the result must be sign-extended */ + if (result & 0x80000000) + return (((long)-1 >> 32) << 32) + result; +#endif + + return result; +} + + + + |