source: trunk/libs/newlib/src/newlib/libc/stdlib/a64l.c @ 577

Last change on this file since 577 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 3.6 KB
Line 
1/*
2FUNCTION
3<<a64l>>, <<l64a>>---convert between radix-64 ASCII string and long
4
5INDEX
6        a64l
7INDEX
8        l64a
9
10SYNOPSIS
11        #include <stdlib.h>
12        long a64l(const char *<[input]>);
13        char *l64a(long <[input]>);
14
15DESCRIPTION
16Conversion is performed between long and radix-64 characters.  The
17<<l64a>> routine transforms up to 32 bits of input value starting from
18least significant bits to the most significant bits.  The input value
19is split up into a maximum of 5 groups of 6 bits and possibly one
20group of 2 bits (bits 31 and 30).
21
22Each group of 6 bits forms a value from 0--63 which is translated into
23a character as follows:
24
25O+
26o     0 = '.'
27o     1 = '/'
28o     2--11 = '0' to '9'
29o     12--37 = 'A' to 'Z'
30o     38--63 = 'a' to 'z'
31O-
32
33When the remaining bits are zero or all bits have been translated, a
34null terminator is appended to the string.  An input value of 0
35results in the empty string.
36
37The <<a64l>> function performs the reverse translation.  Each
38character is used to generate a 6-bit value for up to 30 bits and then
39a 2-bit value to complete a 32-bit result.  The null terminator means
40that the remaining digits are 0.  An empty input string or NULL string
41results in 0L.  An invalid string results in undefined behavior.  If
42the size of a long is greater than 32 bits, the result is sign-extended.
43
44RETURNS
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
48PORTABILITY
49<<l64a>> and <<a64l>> are non-ANSI and are defined by the Single Unix Specification.
50
51Supporting OS subroutines required: None.
52*/
53
54#include <_ansi.h>
55#include <stdlib.h>
56#include <limits.h>
57
58long
59a64l (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
Note: See TracBrowser for help on using the repository browser.