Mail Archives: djgpp-workers/2001/05/30/11:59:25
When looking through the POSIX draft Mark pointed out, I
saw a pair of functions mentioned that wouldn't be too
hard to implement, so I did.
These would go into stdlib.h, so a src/lib/posix/stdlib
directory would have to be created.
NOTE: I always get confused about which is the least/most
significant digit, so I may have done the a64l conversion
the wrong way around.
--- nul Tue May 29 22:09:11 2001
+++ radix64.c Tue May 29 22:04:48 2001
@@ -0,0 +1,106 @@
+/* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+long
+a64l(const char* s)
+{
+ int i = 0;
+ long value = 0;
+
+ if (s == NULL || *s == '\0')
+ return 0L;
+
+ for (i = 0; i < 6; ++i, ++s)
+ {
+ if (*s == '\0')
+ break;
+ /* Detect overflow; return the conversion of '/2BIG/' */
+ if (value > (LONG_MAX >> 6))
+ return 1144341633L;
+ value <<= 6;
+ if (*s == '.') /* 0 */
+ value += 0;
+ else if (*s == '/') /* 1 */
+ ++value;
+ else if (*s >= '0' && *s <= '9') /* 2-11 */
+ value += (*s - '0') + 2;
+ else if (*s >= 'A' && *s <= 'Z') /* 12-37 */
+ value += (*s - 'A') + 12;
+ else if (*s >= 'a' && *s <= 'z') /* 38-63 */
+ value += (*s - 'a') + 38;
+ else /* invalid digit */
+ return 0L;
+ }
+ return value;
+}
+
+char*
+l64a(long value)
+{
+ static char radix64[7] = { "" };
+ char *s = radix64 + 5;
+
+ memset (radix64, 0, sizeof radix64);
+
+ if (value <= 0)
+ return radix64;
+
+ while (value && s >= radix64)
+ {
+ int digit = value & 0x3f;
+ value >>= 6;
+
+ if (digit == 0)
+ *s-- = '.';
+ else if (digit == 1)
+ *s-- = '/';
+ else if (digit < 12)
+ *s-- = '0' + (digit - 2);
+ else if (digit < 38)
+ *s-- = 'A' + (digit - 12);
+ else
+ *s-- = 'a' + (digit - 38);
+ }
+ return ++s;
+}
+
+#ifdef TEST
+#include <stdio.h>
+
+int
+main(void)
+{
+ printf ("a64l(\"/.\") -> %ld\n", a64l("/."));
+ printf ("a64l(\"DJGPP\") -> %ld\n", a64l("DJGPP"));
+ printf ("a64l(\"/.Rules!\") -> %ld\n", a64l("/.Rules!"));
+ printf ("a64l(\"EliRules!\") -> %ld\n", a64l("EliRules!"));
+ printf ("a64l(NULL) -> %ld\n", a64l(NULL));
+ printf ("a64l(\"\") -> %ld\n", a64l(""));
+ printf ("a64l(\"Not Radix64\") -> %ld\n", a64l("Not Radix64"));
+
+ printf ("l64a(1234) -> '%s'\n", l64a(1234));
+ printf ("l64a(64) -> '%s'\n", l64a(64));
+ printf ("l64a(7) -> '%s'\n", l64a(7));
+ printf ("l64a(0) -> '%s'\n", l64a(0));
+ printf ("l64a(-88) -> '%s'\n", l64a(-88));
+
+ printf ("a64l(l64a(1234)) -> %ld\n", a64l(l64a(1234)));
+ printf ("a64l(l64a(64)) -> %ld\n", a64l(l64a(64)));
+ printf ("a64l(l64a(7)) -> %ld\n", a64l(l64a(7)));
+ printf ("a64l(l64a(0)) -> %ld\n", a64l(l64a(0)));
+ printf ("a64l(l64a(-88)) -> %ld\n", a64l(l64a(-88)));
+
+ printf ("l64a(a64l(\"/.\")) -> '%s'\n", l64a(a64l("/.")));
+ printf ("l64a(a64l(\"DJGPP\")) -> '%s'\n", l64a(a64l("DJGPP")));
+ printf ("l64a(a64l(\"/.Rules!\")) -> '%s'\n", l64a(a64l("/.Rules!")));
+ printf ("l64a(a64l(\"EliRules!\")) -> '%s'\n",
l64a(a64l("EliRules!")));
+ printf ("l64a(a64l(NULL)) -> '%s'\n", l64a(a64l(NULL)));
+ printf ("l64a(a64l(\"\")) -> '%s'\n", l64a(a64l("")));
+ printf ("l64a(a64l(\"Not Radix64\")) -> '%s'\n", l64a(a64l("Not
Radix64")));
+
+ return 0;
+}
+#endif
--- nul Tue May 29 22:09:15 2001
+++ radix64.txh Tue May 29 22:08:02 2001
@@ -0,0 +1,77 @@
+@node a64l, string
+@subheading Syntax
+
+@example
+#include <stdlib.h>
+
+long a64l(const char *s);
+@end example
+
+@subheading Description
+
+This function takes a pointer to a radix-64 representation, with the
+first digit the least significant, and returns the corresponding
+@code{long} value.
+
+If @var{s} contains more than six characters, only the first six are
+used. If the first six characters of @var{s} contain a null terminator,
+only those characters before the null terminator are used.
+@code{a64l()} will scan the string from left to right, with the least
+significant digit on the left, decoding each character as a 6-bit radix-64
+number. If the @code{long} type contains more than 32 bits, the result is
+sign-extended.
+The result of @code{a64l()} is undefined if @var{s} is a null pointer, or
+the string it points to was not generated by a previous call to
+@code{l64a()}.
+
+For a description of the radix-64 representation, @ref{l64a}.
+
+@subheading Return Value
+
+Returns the @code{long} value resulting from the conversion of the contents
+of @var{s}, or 0L is @var{s} is NULL, points to an empty string, or points
+to an invalid string. If the result would overflow a signed long, the
+conversion of @samp{'/2BIG/'} (1144341633) is returned.
+
+@subheading Portability
+
+@portability !ansi, posix
+
+
+@node l64a, string
+@subheading Syntax
+
+@example
+#include <stdlib.h>
+
+char *l64a(long value);
+@end example
+
+@subheading Description
+
+This function takes a @code{long} argument and returns a pointer to its
+radix-64 representation. The result is undefined if @var{value} is
+negative.
+
+@subheading Return Value
+
+A pointer to a static buffer containing the radix-64 representation of
+@var{value}. Subsequent calls will overwrite the contents of this buffer.
+If @var{value} is 0L, this will return an empty string.
+
+@subheading Radix-64
+@cindex radix-64
+
+The radix-64 @sc{ascii} representation is a notation whereby 32-bit
integers
+are represented by up to 6 @sc{ascii} characters; each character represents
+a single radix-64 digit.
+If the @code{long} type is more than 32 bits in size, only the low-order
+32 bits are used.
+The characters used to represent digits are @samp{.} (dot) for 0, @samp{/}
+for 1, @samp{0} through @samp{9} for 2 to 11, @samp{A} through @samp{Z} for
+12 to 37, and @samp{a} through @samp{z} for 38 to 63.
+
+@subheading Portability
+
+@portability !ansi, posix
+
- Raw text -