imme-dongle.tar.gz
[imme-dongle] / linux / parse.c
1 #include <stdint.h>
2 #include <stdbool.h>
3 #include "parse.h"
4
5 #include <string.h>     /* memcmp */
6
7 /*******************************************************************************/
8
9 bool memstrcmp(const uint8_t *start, const uint8_t *end, const char *str)
10 {
11     uint32_t len = strlen(str);
12
13     if (len != end-start)
14         return false;
15
16     return memcmp(start, str, len) == 0;
17 }
18
19
20 // hex nibble to int
21 static uint8_t digit_to_int(uint8_t ch)
22 {
23     uint8_t r;
24     if (ch >= 'a')
25         r = 'a' - 10;
26     else
27     {
28         if (ch >= 'A')
29             r = 'A' - 10;
30         else
31         {
32             if (ch <= '9')
33                 r = '0';
34             else
35                 r = 0;
36         }
37     }
38
39     return ch - r;
40 }
41
42 // parse binary, hex and decimal numbers
43 bool parse_number(const uint8_t *str, uint8_t len, uint32_t *result)
44 {
45     uint8_t base = 10;
46     uint8_t i;
47     uint8_t c;
48     uint8_t digit;
49
50     *result = 0;
51
52     for (i=0;i<len;i++)
53     {
54         c = str[i];
55
56         if (*result == 0)
57         {
58             if ((i == 0 || i == 1) && c == 'b')     // 0b/b for binary
59             {
60                 if (len < 2)
61                     return false;
62                 base = 2;
63                 continue;
64             }
65             else
66             if (i==0 && c == 'h')       // h for hex
67             {
68                 if (len < 2)
69                     return false;
70                 base = 16;
71                 continue;
72             }
73             else
74             if (i == 1 && c == 'x')     // 0x for hex
75             {
76                 if (len < 3)
77                     return false;
78                 base = 16;
79                 continue;
80             }
81         }
82
83         digit = digit_to_int(c);
84
85         if (digit < base)
86             *result = (*result) * base + digit;
87         else
88             return false;
89     }
90     return true;
91 }
92
93 /*******************************************************************************/
94
95 // find the next token in the buffer given by *tok_start to line_end
96 // on success, returns true, *tok_start points at first byte of found token, *tok_end points at first character after end of token
97 bool tok(uint8_t const **tok_start, uint8_t const **tok_end, const uint8_t *line_end)
98 {
99     // skip whitespace on front
100     while(*tok_start != line_end)
101     {
102         if (**tok_start == ' ' || **tok_start == '\t')
103             (*tok_start)++;
104         else
105             break;
106     }
107     // *tok_start is now first non-whitespace character in token
108
109     *tok_end = *tok_start;
110     // skip to end of token
111     while(*tok_end != line_end)
112     {
113         if (**tok_end == ' ' || **tok_end == '\t')
114             break;
115         else
116             (*tok_end)++;
117     }
118     // *tok_end is now first whitespace character after token or line_end
119
120     return *tok_end != *tok_start;
121 }
122
123 // advance tok_start/tok_end to next token and read number value into i
124 bool tok_num(const uint8_t **tok_start, const uint8_t **tok_end, const uint8_t *line_end, uint32_t *i)
125 {
126     if (tok(tok_start, tok_end, line_end))
127     {
128         if (parse_number(*tok_start, (*tok_end)-(*tok_start), i))
129         {
130             *tok_start = *tok_end;  // skip past token
131             return true;
132         }
133         else
134         {
135 //            *tok_start = *tok_end;  // skip past token
136         }
137     }
138
139     return false;
140 }
141
142 /*******************************************************************************/
143