summaryrefslogtreecommitdiff
path: root/cesar/lib/src/atox.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/lib/src/atox.c')
-rw-r--r--cesar/lib/src/atox.c383
1 files changed, 383 insertions, 0 deletions
diff --git a/cesar/lib/src/atox.c b/cesar/lib/src/atox.c
new file mode 100644
index 0000000000..9dd8160710
--- /dev/null
+++ b/cesar/lib/src/atox.c
@@ -0,0 +1,383 @@
+/**{{{
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ }}}*/
+/**
+ * \file lib/src/atox.c
+ * \brief ASCII string convertions
+ * \ingroup lib
+ */
+#include "lib/atox.h"
+
+#define LONG_MAX 2147483647L
+#define LONG_MIN (-LONG_MAX-1)
+#define LONG_LONG_MAX 9223372036854775807LL
+#define LONG_LONG_MIN (-LONG_LONG_MAX-1)
+#define ULONG_MAX (LONG_MAX * 2UL + 1)
+#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1)
+
+static inline int isupper(int c)
+{
+ return (('A' <= c) && (c <= 'Z'));
+} //isupper
+
+static inline int islower(int c)
+{
+ return (('a' <= c) && (c <= 'z'));
+} //islower
+
+static inline int isalpha(int c)
+{
+ return ( islower(c) || isupper(c) );
+} //isalpha
+
+static inline int isdigit(int c)
+{
+ return ( ('0' <= c) && (c <= '9') );
+} //isdigit
+
+static inline int isspace(int c)
+{
+ return ( (c == ' ') || (c == '\f') || (c == '\n') || (c == '\r') ||
+ (c == '\t') || (c == '\v') );
+} //isspace
+
+static unsigned long long strtoull(const char *nptr, char **endptr, int base)
+{
+ const char *s = nptr;
+ unsigned long long acc;
+ int c;
+ unsigned long long cutoff;
+ int neg = 0, any, cutlim;
+
+ if (endptr != 0)
+ return -1;
+ //
+ // See strtoll for comments as to the logic used.
+ //
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long long)ULONG_LONG_MAX / (unsigned long long)base;
+ cutlim = (unsigned long long)ULONG_LONG_MAX % (unsigned long long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim)))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_LONG_MAX;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+
+ return acc;
+} //strtoull
+
+unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+ const char *s = nptr;
+ unsigned long acc;
+ int c;
+ unsigned long cutoff;
+ int neg = 0, any, cutlim;
+
+ if (endptr != 0)
+ return -1;
+ //
+ // See strtol for comments as to the logic used.
+ //
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
+ cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim)))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_MAX;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+
+ return acc;
+} //strtoul
+
+long long strtoll(const char *nptr, char **endptr, int base)
+{
+ const char *s = nptr;
+ unsigned long long acc;
+ int c;
+ unsigned long long cutoff;
+ int neg = 0, any, cutlim;
+
+ if (endptr != 0)
+ return -1;
+
+ //
+ // Skip white space and pick up leading +/- sign if any.
+ // If base is 0, allow 0x for hex and 0 for octal, else
+ // assume decimal; if base is already 16, allow 0x.
+ //
+
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ //
+ // Compute the cutoff value between legal numbers and illegal
+ // numbers. That is the largest legal value, divided by the
+ // base. An input number that is greater than this value, if
+ // followed by a legal input character, is too big. One that
+ // is equal to this value may be valid or not; the limit
+ // between valid and invalid numbers is then based on the last
+ // digit. For instance, if the range for long longs is
+ // [-2147483648..2147483647] and the input base is 10,
+ // cutoff will be set to 214748364 and cutlim to either
+ // 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ // a value > 214748364, or equal but the next digit is > 7 (or 8),
+ // the number is too big, and we will return a range error.
+ //
+ // Set any if any `digits' consumed; make it negative to indicate
+ // overflow.
+ //
+
+ cutoff = neg ? -(unsigned long long)LONG_LONG_MIN : LONG_LONG_MAX;
+ cutlim = cutoff % (unsigned long long)base;
+ cutoff /= (unsigned long long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim)))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_LONG_MIN : LONG_LONG_MAX;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+
+ return acc;
+} // strtoll()
+
+static long strtol(const char *nptr, char **endptr, int base)
+{
+ const char *s = nptr;
+ unsigned long acc;
+ int c;
+ unsigned long cutoff;
+ int neg = 0, any, cutlim;
+
+ if (endptr != 0)
+ return -1;
+
+ //
+ // Skip white space and pick up leading +/- sign if any.
+ // If base is 0, allow 0x for hex and 0 for octal, else
+ // assume decimal; if base is already 16, allow 0x.
+ //
+
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ //
+ // Compute the cutoff value between legal numbers and illegal
+ // numbers. That is the largest legal value, divided by the
+ // base. An input number that is greater than this value, if
+ // followed by a legal input character, is too big. One that
+ // is equal to this value may be valid or not; the limit
+ // between valid and invalid numbers is then based on the last
+ // digit. For instance, if the range for longs is
+ // [-2147483648..2147483647] and the input base is 10,
+ // cutoff will be set to 214748364 and cutlim to either
+ // 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ // a value > 214748364, or equal but the next digit is > 7 (or 8),
+ // the number is too big, and we will return a range error.
+ //
+ // Set any if any `digits' consumed; make it negative to indicate
+ // overflow.
+ //
+
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim)))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+
+ return acc;
+} //strtol
+
+int atoi(const char *nptr)
+{
+ int retval;
+
+ retval = (int) strtol(nptr, (char **)0, 10);
+
+ return retval;
+} //atoi
+
+
+long atol(const char *nptr)
+{
+ long retval;
+
+ retval = strtol(nptr, (char **)0, 10);
+
+ return retval;
+} //atol
+
+long long atoll(const char *nptr)
+{
+ long long retval;
+
+ retval = strtoll(nptr, (char **)0, 10);
+
+ return retval;
+} //atoll
+
+unsigned long atoul(const char *nptr)
+{
+ unsigned long retval;
+
+ retval = strtoul(nptr, (char **)0, 10);
+
+ return retval;
+} //atoul
+
+unsigned long long atoull(const char *nptr)
+{
+ unsigned long long retval;
+
+ retval = strtoull(nptr, (char **)0, 10);
+
+ return retval;
+} //atoull
+