1 | /* |
---|
2 | FUNCTION |
---|
3 | <<a64l>>, <<l64a>>---convert between radix-64 ASCII string and long |
---|
4 | |
---|
5 | INDEX |
---|
6 | a64l |
---|
7 | INDEX |
---|
8 | l64a |
---|
9 | |
---|
10 | SYNOPSIS |
---|
11 | #include <stdlib.h> |
---|
12 | long a64l(const char *<[input]>); |
---|
13 | char *l64a(long <[input]>); |
---|
14 | |
---|
15 | DESCRIPTION |
---|
16 | Conversion is performed between long and radix-64 characters. The |
---|
17 | <<l64a>> routine transforms up to 32 bits of input value starting from |
---|
18 | least significant bits to the most significant bits. The input value |
---|
19 | is split up into a maximum of 5 groups of 6 bits and possibly one |
---|
20 | group of 2 bits (bits 31 and 30). |
---|
21 | |
---|
22 | Each group of 6 bits forms a value from 0--63 which is translated into |
---|
23 | a character as follows: |
---|
24 | |
---|
25 | O+ |
---|
26 | o 0 = '.' |
---|
27 | o 1 = '/' |
---|
28 | o 2--11 = '0' to '9' |
---|
29 | o 12--37 = 'A' to 'Z' |
---|
30 | o 38--63 = 'a' to 'z' |
---|
31 | O- |
---|
32 | |
---|
33 | When the remaining bits are zero or all bits have been translated, a |
---|
34 | null terminator is appended to the string. An input value of 0 |
---|
35 | results in the empty string. |
---|
36 | |
---|
37 | The <<a64l>> function performs the reverse translation. Each |
---|
38 | character is used to generate a 6-bit value for up to 30 bits and then |
---|
39 | a 2-bit value to complete a 32-bit result. The null terminator means |
---|
40 | that the remaining digits are 0. An empty input string or NULL string |
---|
41 | results in 0L. An invalid string results in undefined behavior. If |
---|
42 | the size of a long is greater than 32 bits, the result is sign-extended. |
---|
43 | |
---|
44 | RETURNS |
---|
45 | <<l64a>> returns a null-terminated string of 0 to 6 characters. |
---|
46 | <<a64l>> returns the 32-bit translated value from the input character string. |
---|
47 | |
---|
48 | PORTABILITY |
---|
49 | <<l64a>> and <<a64l>> are non-ANSI and are defined by the Single Unix Specification. |
---|
50 | |
---|
51 | Supporting OS subroutines required: None. |
---|
52 | */ |
---|
53 | |
---|
54 | #include <_ansi.h> |
---|
55 | #include <stdlib.h> |
---|
56 | #include <limits.h> |
---|
57 | |
---|
58 | long |
---|
59 | a64l (const char *input) |
---|
60 | { |
---|
61 | const char *ptr; |
---|
62 | char ch; |
---|
63 | int i, digit; |
---|
64 | unsigned long result = 0; |
---|
65 | |
---|
66 | if (input == NULL) |
---|
67 | return 0; |
---|
68 | |
---|
69 | ptr = input; |
---|
70 | |
---|
71 | /* it easiest to go from most significant digit to least so find end of input or up |
---|
72 | to 6 characters worth */ |
---|
73 | for (i = 0; i < 6; ++i) |
---|
74 | { |
---|
75 | if (*ptr) |
---|
76 | ++ptr; |
---|
77 | } |
---|
78 | |
---|
79 | while (ptr > input) |
---|
80 | { |
---|
81 | ch = *(--ptr); |
---|
82 | |
---|
83 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) |
---|
84 | if (ch >= 'a') |
---|
85 | digit = (ch - 'a') + 38; |
---|
86 | else if (ch >= 'A') |
---|
87 | digit = (ch - 'A') + 12; |
---|
88 | else if (ch >= '0') |
---|
89 | digit = (ch - '0') + 2; |
---|
90 | else if (ch == '/') |
---|
91 | digit = 1; |
---|
92 | else |
---|
93 | digit = 0; |
---|
94 | #else /* !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) */ |
---|
95 | switch (ch) |
---|
96 | { |
---|
97 | case '/': |
---|
98 | digit = 1; |
---|
99 | break; |
---|
100 | case '0': |
---|
101 | case '1': |
---|
102 | case '2': |
---|
103 | case '3': |
---|
104 | case '4': |
---|
105 | case '5': |
---|
106 | case '6': |
---|
107 | case '7': |
---|
108 | case '8': |
---|
109 | case '9': |
---|
110 | digit = (ch - '0') + 2; |
---|
111 | break; |
---|
112 | case 'A': |
---|
113 | case 'B': |
---|
114 | case 'C': |
---|
115 | case 'D': |
---|
116 | case 'E': |
---|
117 | case 'F': |
---|
118 | case 'G': |
---|
119 | case 'H': |
---|
120 | case 'I': |
---|
121 | case 'J': |
---|
122 | case 'K': |
---|
123 | case 'L': |
---|
124 | case 'M': |
---|
125 | case 'N': |
---|
126 | case 'O': |
---|
127 | case 'P': |
---|
128 | case 'Q': |
---|
129 | case 'R': |
---|
130 | case 'S': |
---|
131 | case 'T': |
---|
132 | case 'U': |
---|
133 | case 'V': |
---|
134 | case 'W': |
---|
135 | case 'X': |
---|
136 | case 'Y': |
---|
137 | case 'Z': |
---|
138 | digit = (ch - 'A') + 12; |
---|
139 | break; |
---|
140 | case 'a': |
---|
141 | case 'b': |
---|
142 | case 'c': |
---|
143 | case 'd': |
---|
144 | case 'e': |
---|
145 | case 'f': |
---|
146 | case 'g': |
---|
147 | case 'h': |
---|
148 | case 'i': |
---|
149 | case 'j': |
---|
150 | case 'k': |
---|
151 | case 'l': |
---|
152 | case 'm': |
---|
153 | case 'n': |
---|
154 | case 'o': |
---|
155 | case 'p': |
---|
156 | case 'q': |
---|
157 | case 'r': |
---|
158 | case 's': |
---|
159 | case 't': |
---|
160 | case 'u': |
---|
161 | case 'v': |
---|
162 | case 'w': |
---|
163 | case 'x': |
---|
164 | case 'y': |
---|
165 | case 'z': |
---|
166 | digit = (ch - 'a') + 38; |
---|
167 | break; |
---|
168 | default: |
---|
169 | digit = 0; |
---|
170 | break; |
---|
171 | } |
---|
172 | #endif /* !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) */ |
---|
173 | |
---|
174 | result = (result << 6) + digit; |
---|
175 | } |
---|
176 | |
---|
177 | #if LONG_MAX > 2147483647 |
---|
178 | /* for implementations where long is > 32 bits, the result must be sign-extended */ |
---|
179 | if (result & 0x80000000) |
---|
180 | return (((long)-1 >> 32) << 32) + result; |
---|
181 | #endif |
---|
182 | |
---|
183 | return result; |
---|
184 | } |
---|
185 | |
---|
186 | |
---|
187 | |
---|
188 | |
---|