]> mj.ucw.cz Git - libucw.git/blob - ucw/strtonum.c
UCW: Cosmetic cleanups of strtonum
[libucw.git] / ucw / strtonum.c
1 /*
2  *      UCW Library -- Conversions of Strings to Numbers
3  *
4  *      (c) 2010 Daniel Fiala <danfiala@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include "ucw/lib.h"
11 #include "ucw/string.h"
12 #include "ucw/chartype.h"
13 #include "ucw/strtonum.h"
14
15 static const char err_numeric_overflow[] = "Numeric overflow";
16 static const char err_no_digits[] = "Number contains no digits";
17 static const char err_invalid_character[] = "Invalid character";
18 static const char err_unknown_base[] = "Unknown base";
19
20 static uns detect_base(const char *p, const uns flags)
21 {
22   if ((flags & STN_BASES) && *p == '0')
23     {
24       switch (p[1] & 0xDF)
25         {
26           case 'X':
27             if (flags & STN_HEX)
28               {
29                 return 16;
30               }
31             break;
32
33           case 'B':
34             if (flags & STN_BIN)
35               {
36                 return 2;
37               }
38             break;
39
40           case 'O':
41             if (flags & STN_OCT)
42               {
43                 return 8;
44               }
45             break;
46         }
47     }
48
49   return 0;
50 }
51
52 static const char *str_to_num_init(const char **pp, const uns flags, uns *sign, uns *base)
53 {
54   ASSERT(*pp);
55
56   const char *err = NULL;
57   const char *p = *pp;
58
59   // Parse sign
60   *sign = 0;
61   if (flags & (STN_SIGNS))
62     {
63       if (*p == '-' && (flags & STN_MINUS))
64         {
65           *sign = 1;
66           p++;
67         }
68       else if (*p == '+' && (flags & STN_PLUS))
69         p++;
70     }
71
72   const uns prefix_base = detect_base(p, flags);
73   if (prefix_base)
74     {
75       p += 2;
76       *base = prefix_base;
77     }
78   else
79     {
80       *base = flags & STN_DBASES_MASK;
81     }
82
83   *pp = p;
84   return err;
85 }
86
87 static inline uns get_digit(const uns c)
88 {
89   if (c <= '9')
90     {
91       return c - '0';
92     }
93   else
94     {
95       const int a = c & 0xDF;
96       unsigned d = a - 'A';
97       d &= 0xFF;
98       d += 10;
99       return d;
100     }
101 }
102
103 #define STN_TYPE uns
104 #define STN_SUFFIX uns
105 #include "ucw/strtonum-gen.h"
106
107 #define STN_TYPE uintmax_t
108 #define STN_SUFFIX uintmax
109 #include "ucw/strtonum-gen.h"