| /* |
| 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: |
| |
| O+ |
| o 0 = '.' |
| o 1 = '/' |
| o 2--11 = '0' to '9' |
| o 12--37 = 'A' to 'Z' |
| o 38--63 = 'a' to 'z' |
| O- |
| |
| When the remaining bits are zero or all bits have been translated, a |
| null terminator is appended to the string. An input value of 0 |
| results in the empty string. |
| |
| The <<a64l>> function 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 null 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 greater than 32 bits, the result is sign-extended. |
| |
| RETURNS |
| <<l64a>> returns a null-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) |
| { |
| const 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; |
| } |
| |
| |
| |
| |