Add the identifying header
[kugel-rb.git] / apps / plugins / lua / fscanf.c
blob9f5f129d3cc46d5dcc879b73b069f7c851384503
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copied from firmware/common/sscanf.c
11 * Original author: Tomasz Malesinski
13 * Copyright (C) 2010 Maurus Cuelenaere
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
25 #include "rocklibc.h"
27 static int parse_dec(int (*peek)(void *userp),
28 void (*pop)(void *userp),
29 void *userp,
30 long *vp)
32 long v = 0;
33 int n = 0;
34 int minus = 0;
35 char ch;
37 if ((*peek)(userp) == '-')
39 (*pop)(userp);
40 n++;
41 minus = 1;
44 ch = (*peek)(userp);
45 if (!isdigit(ch))
46 return -1;
50 v = v * 10 + ch - '0';
51 (*pop)(userp);
52 n++;
53 ch = (*peek)(userp);
54 } while (isdigit(ch));
56 *vp = minus ? -v : v;
57 return n;
60 static int parse_chars(int (*peek)(void *userp),
61 void (*pop)(void *userp),
62 void *userp,
63 char *vp,
64 bool fake)
66 int n = 0;
68 char *pt=vp;
70 while (!isspace((*peek)(userp)))
72 if(fake==false)
73 *(pt++) = (*peek)(userp);
75 n++;
76 (*pop)(userp);
79 if(fake==false)
80 (*pt)='\0';
82 return n;
85 static int parse_hex(int (*peek)(void *userp),
86 void (*pop)(void *userp),
87 void *userp,
88 unsigned long *vp)
90 unsigned long v = 0;
91 int n = 0;
92 char ch;
94 ch = (*peek)(userp);
95 if (!isxdigit(ch))
96 return -1;
100 if (ch >= 'a')
101 ch = ch - 'a' + 10;
102 else if (ch >= 'A')
103 ch = ch - 'A' + 10;
104 else
105 ch = ch - '0';
106 v = v * 16 + ch;
107 (*pop)(userp);
108 n++;
109 ch = (*peek)(userp);
110 } while (isxdigit(ch));
112 *vp = v;
113 return n;
116 static int skip_spaces(int (*peek)(void *userp),
117 void (*pop)(void *userp),
118 void *userp)
120 int n = 0;
121 while (isspace((*peek)(userp))) {
122 n++;
123 (*pop)(userp);
125 return n;
128 static int scan(int (*peek)(void *userp),
129 void (*pop)(void *userp),
130 void *userp,
131 const char *fmt,
132 va_list ap)
134 char ch;
135 int n = 0;
136 int n_chars = 0;
137 int r;
138 long lval;
139 bool skip=false;
140 unsigned long ulval;
142 while ((ch = *fmt++) != '\0')
144 bool literal = false;
146 if (ch == '%')
148 ch = *fmt++;
150 if(ch== '*') /* We should process this, but not store it in an argument */
152 ch=*fmt++;
153 skip=true;
155 else
157 skip=false;
160 switch (ch)
162 case 'x':
163 n_chars += skip_spaces(peek, pop, userp);
164 if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
166 if(skip==false)
168 *(va_arg(ap, unsigned int *)) = ulval;
169 n++;
171 n_chars += r;
173 else
174 return n;
175 break;
176 case 'd':
177 n_chars += skip_spaces(peek, pop, userp);
178 if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
180 if(skip==false)
182 *(va_arg(ap, int *)) = lval;
183 n++;
185 n_chars += r;
187 else
188 return n;
189 break;
190 case 'n':
191 if(skip==false)
193 *(va_arg(ap, int *)) = n_chars;
194 n++;
196 break;
197 case 'l':
198 n_chars += skip_spaces(peek, pop, userp);
199 ch = *fmt++;
200 switch (ch)
202 case 'x':
203 if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
205 if(skip==false)
207 *(va_arg(ap, unsigned long *)) = ulval;
208 n++;
210 n_chars += r;
212 else
213 return n;
214 break;
215 case 'd':
216 if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
218 if(skip==false)
220 *(va_arg(ap, long *)) = lval;
221 n++;
223 n_chars += r;
225 else
226 return n;
227 break;
228 case '\0':
229 return n;
230 default:
231 literal = true;
232 break;
234 break;
235 case 's':
236 n_chars += skip_spaces(peek, pop, userp);
237 n_chars += parse_chars(peek,pop, userp,skip?0:va_arg(ap, char *), skip );
238 if(skip==false)
240 n++;
242 break;
243 case '\0':
244 return n;
245 default:
246 literal = true;
247 break;
249 } else
250 literal = true;
252 if (literal)
254 n_chars += skip_spaces(peek, pop, userp);
255 if ((*peek)(userp) != ch)
256 continue;
257 else
259 (*pop)(userp);
260 n_chars++;
264 return n;
267 static int fspeek(void *userp)
269 int fd = *((int*) userp);
270 char buf = 0;
271 if(rb->read(fd, &buf, 1) == 1)
272 rb->lseek(fd, -1, SEEK_CUR);
273 return buf;
276 static void fspop(void *userp)
278 int fd = *((int*) userp);
279 rb->lseek(fd, 1, SEEK_CUR);
282 int PREFIX(fscanf)(int fd, const char *fmt, ...)
284 int r;
285 va_list ap;
287 va_start(ap, fmt);
288 r = scan(fspeek, fspop, &fd, fmt, ap);
289 va_end(ap);
290 return r;