fix red... lets branch
[kugel-rb.git] / firmware / common / sscanf.c
blob5fbe81f3e014e9d78f17097a9265c7df200a5699
1 #include <stdarg.h>
2 #include <string.h>
3 #include <stdbool.h>
5 static inline bool isspace(char c)
7 return (c == ' ') || (c == '\t') || (c == '\n');
10 static inline bool isdigit(char c)
12 return (c >= '0') && (c <= '9');
15 static inline bool isxdigit(char c)
17 return ((c >= '0') && (c <= '9'))
18 || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F'));
21 static int parse_dec(int (*peek)(void *userp),
22 void (*pop)(void *userp),
23 void *userp,
24 long *vp)
26 long v = 0;
27 int n = 0;
28 int minus = 0;
29 char ch;
31 if ((*peek)(userp) == '-')
33 (*pop)(userp);
34 n++;
35 minus = 1;
38 ch = (*peek)(userp);
39 if (!isdigit(ch))
40 return -1;
44 v = v * 10 + ch - '0';
45 (*pop)(userp);
46 n++;
47 ch = (*peek)(userp);
48 } while (isdigit(ch));
50 *vp = minus ? -v : v;
51 return n;
54 static int parse_chars(int (*peek)(void *userp),
55 void (*pop)(void *userp),
56 void *userp,
57 char *vp,
58 bool fake)
60 int n = 0;
62 char *pt=vp;
64 while (!isspace((*peek)(userp)))
66 if(fake==false)
67 *(pt++) = (*peek)(userp);
69 n++;
70 (*pop)(userp);
73 if(fake==false)
74 (*pt)='\0';
76 return n;
79 static int parse_hex(int (*peek)(void *userp),
80 void (*pop)(void *userp),
81 void *userp,
82 unsigned long *vp)
84 unsigned long v = 0;
85 int n = 0;
86 char ch;
88 ch = (*peek)(userp);
89 if (!isxdigit(ch))
90 return -1;
94 if (ch >= 'a')
95 ch = ch - 'a' + 10;
96 else if (ch >= 'A')
97 ch = ch - 'A' + 10;
98 else
99 ch = ch - '0';
100 v = v * 16 + ch;
101 (*pop)(userp);
102 n++;
103 ch = (*peek)(userp);
104 } while (isxdigit(ch));
106 *vp = v;
107 return n;
110 static int skip_spaces(int (*peek)(void *userp),
111 void (*pop)(void *userp),
112 void *userp)
114 int n = 0;
115 while (isspace((*peek)(userp))) {
116 n++;
117 (*pop)(userp);
119 return n;
122 static int scan(int (*peek)(void *userp),
123 void (*pop)(void *userp),
124 void *userp,
125 const char *fmt,
126 va_list ap)
128 char ch;
129 int n = 0;
130 int n_chars = 0;
131 int r;
132 long lval;
133 bool skip=false;
134 unsigned long ulval;
136 while ((ch = *fmt++) != '\0')
138 bool literal = false;
140 if (ch == '%')
142 ch = *fmt++;
144 if(ch== '*') /* We should process this, but not store it in an arguement */
146 ch=*fmt++;
147 skip=true;
149 else
151 skip=false;
154 switch (ch)
156 case 'x':
157 n_chars += skip_spaces(peek, pop, userp);
158 if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
160 if(skip==false)
162 *(va_arg(ap, unsigned int *)) = ulval;
163 n++;
165 n_chars += r;
167 else
168 return n;
169 break;
170 case 'd':
171 n_chars += skip_spaces(peek, pop, userp);
172 if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
174 if(skip==false)
176 *(va_arg(ap, int *)) = lval;
177 n++;
179 n_chars += r;
181 else
182 return n;
183 break;
184 case 'n':
185 if(skip==false)
187 *(va_arg(ap, int *)) = n_chars;
188 n++;
190 break;
191 case 'l':
192 n_chars += skip_spaces(peek, pop, userp);
193 ch = *fmt++;
194 switch (ch)
196 case 'x':
197 if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
199 if(skip==false)
201 *(va_arg(ap, unsigned long *)) = ulval;
202 n++;
204 n_chars += r;
206 else
207 return n;
208 break;
209 case 'd':
210 if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
212 if(skip==false)
214 *(va_arg(ap, long *)) = lval;
215 n++;
217 n_chars += r;
219 else
220 return n;
221 break;
222 case '\0':
223 return n;
224 default:
225 literal = true;
226 break;
228 break;
229 case 's':
230 n_chars += skip_spaces(peek, pop, userp);
231 n_chars += parse_chars(peek,pop, userp,skip?0:va_arg(ap, char *), skip );
232 if(skip==false)
234 n++;
236 break;
237 case '\0':
238 return n;
239 default:
240 literal = true;
241 break;
243 } else
244 literal = true;
246 if (literal)
248 n_chars += skip_spaces(peek, pop, userp);
249 if ((*peek)(userp) != ch)
250 continue;
251 else
253 (*pop)(userp);
254 n_chars++;
258 return n;
261 static int sspeek(void *userp)
263 return **((char **)userp);
266 static void sspop(void *userp)
268 (*((char **)userp))++;
271 int sscanf(const char *s, const char *fmt, ...)
273 int r;
274 va_list ap;
275 const char *p;
277 p = s;
278 va_start(ap, fmt);
279 r = scan(sspeek, sspop, &p, fmt, ap);
280 va_end(ap);
281 return r;