]> mj.ucw.cz Git - libucw.git/blob - ucw/strtonum.c
Released as 6.5.17.
[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 uint detect_base(const char **pp, const uint flags)
16 {
17   if ((flags & STN_BASES0) && **pp == '0')
18     {
19       switch ( (*pp)[1] )
20         {
21           case 'x':
22           case 'X':
23             if (flags & STN_HEX)
24               {
25                 *pp += 2;
26                 return 16;
27               }
28             break;
29
30           case 'b':
31           case 'B':
32             if (flags & STN_BIN)
33               {
34                 *pp += 2;
35                 return 2;
36               }
37             break;
38
39           case 'o':
40           case 'O':
41             if (flags & STN_OCT)
42               {
43                 *pp += 2;
44                 return 8;
45               }
46             break;
47
48           case '0'...'7':
49             if (flags & STN_OCT0)
50               {
51                 (*pp)++;
52                 return 8;
53               }
54             break;
55         }
56     }
57
58   return 0;
59 }
60
61 static const char *str_to_num_init(const char **pp, const uint flags, uint *sign, uint *base)
62 {
63   ASSERT(*pp);
64
65   const char *err = NULL;
66   const char *p = *pp;
67
68   // Parse sign
69   *sign = 0;
70   if (flags & (STN_SIGNS))
71     {
72       if (*p == '-' && (flags & STN_MINUS))
73         {
74           *sign = 1;
75           p++;
76         }
77       else if (*p == '+' && (flags & STN_PLUS))
78         p++;
79     }
80
81   *base = detect_base(&p, flags) ? : flags & STN_DBASES_MASK;
82
83   *pp = p;
84   return err;
85 }
86
87 static inline uint get_digit(const uint c)
88 {
89   if (c <= '9')
90     return c - '0';
91   else
92     {
93       const int a = c & 0xDF;
94       uint d = a - 'A';
95       d &= 0xFF;
96       d += 10;
97       return d;
98     }
99 }
100
101 #define STN_TYPE uint
102 #define STN_SUFFIX uint
103 #include <ucw/strtonum-gen.h>
104
105 #define STN_TYPE u32
106 #define STN_SUFFIX u32
107 #include <ucw/strtonum-gen.h>
108
109 #define STN_TYPE u64
110 #define STN_SUFFIX u64
111 #include <ucw/strtonum-gen.h>
112
113 #define STN_TYPE uintmax_t
114 #define STN_SUFFIX uintmax
115 #include <ucw/strtonum-gen.h>
116
117 // FIXME: For backward compatibility, will be removed soon
118 #define STN_TYPE uns
119 #define STN_SUFFIX uns
120 #include <ucw/strtonum-gen.h>