3 * - By John Hodge (thePowersGang)
6 * - *scanf family of functions
13 extern void _SysDebug(const char *format, ...);
36 int _vcscanf_int(int (*__getc)(void *), void (*__rewind)(void*), void *h, int base, int maxlen, long long *outval)
40 long long int ret = 0;
43 // Initialise output to something sane
47 // - maxlen == 0 means no limit
52 if( ich == '-' || ich == '+' ) {
53 sgn = (ich == '-' ? -1 : 1);
54 if( n_read == maxlen )
66 if( n_read == maxlen )
75 if( n_read == maxlen )
92 // Get the digit value
94 if( '0' <= ich && ich <= '0'+base-1 )
98 if( '0' <= ich && ich <= '9' )
100 if( 'A' <= ich && ich <= 'A'+base-10-1 )
101 next = ich - 'A' + 10;
102 if( 'a' <= ich && ich <= 'a'+base-10-1 )
103 next = ich - 'a' + 10;
105 // if it's not a digit, rewind and break
115 //_SysDebug("- %i/%i read, 0x%x val", n_read, maxlen, ret);
117 // Check if we've reached the limit
118 if( n_read == maxlen )
134 int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char *format, va_list ap)
137 int ret = 0, nch = 0;
139 while( (fch = *format++) )
147 long long *_longlong;
151 int maxlen = 0, offset = -1;
152 enum e_vcscanf_sizes size = _VCSCANF_UNDEF;
153 enum e_vcscanf_types valtype;
155 const char *set_start;
158 // Whitespace matches any ammount of whitespace (including none)
161 while( (ich = __getc(h)) && isspace(ich) )
166 // Any non-whitespace and non-% characters must match exactly
169 if( __getc(h) != fch )
181 if( __getc(h) != '%' )
187 // %n$ - Direct offset selection, shouldn't be mixed with just %
188 for( ; isdigit(fch); fch = *format++ )
189 maxlen = maxlen * 10 + (fch - '0');
195 // Supress assignemnt?
203 ptr._void = va_arg(ap, void*);
206 while( isdigit(fch) )
208 maxlen = maxlen * 10 + fch - '0';
217 size = _VCSCANF_SHORT;
221 size = _VCSCANF_CHAR;
227 size = _VCSCANF_LONG;
231 size = _VCSCANF_LONGLONG;
237 size = _VCSCANF_INTMAX;
242 size = _VCSCANF_SIZET;
247 size = _VCSCANF_PTRDIFF;
251 // 'long double' (a, A, e, E, f, F, g, G)
252 size = _VCSCANF_LONGDOUBLE;
262 nch += _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
263 valtype = _VCSCANF_INT;
265 // variable-base integer
267 nch += _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
268 valtype = _VCSCANF_INT;
272 nch += _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
273 valtype = _VCSCANF_INT;
275 // Hexadecimal integer
277 nch += _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
278 valtype = _VCSCANF_INT;
280 // strtod format float
285 valtype = _VCSCANF_REAL;
287 // `maxlen` or 1 characters
291 while( maxlen -- && (ich = __getc(h)) )
293 if(ptr._char) *ptr._char++ = ich;
296 valtype = _VCSCANF_NOTYPE;
298 // sequence of non-whitespace characters
304 while( maxlen -- && (ich = __getc(h)) && !isblank(ich) )
306 if(ptr._char) *ptr._char++ = ich;
309 if( maxlen >= 0 && ich )
311 valtype = _VCSCANF_NOTYPE;
313 // match a set of characters
322 // if the first character is ']' it's part of the set
324 // permissable character
327 } while( fch && fch != ']' );
330 while( maxlen -- && (ich = __getc(h)) && memchr(set_start, set_len, ich) )
332 if(ptr._char) *ptr._char++ = ich;
335 if( maxlen >= 0 && ich )
337 valtype = _VCSCANF_NOTYPE;
339 case 'p': // read back printf("%p")
340 valtype = _VCSCANF_NOTYPE;
342 case 'n': // number of read characters to this point
345 ret --; // negates the ret ++ at the end
347 valtype = _VCSCANF_NOTYPE;
350 // Implimentation defined
351 valtype = _VCSCANF_NOTYPE;
357 case _VCSCANF_NOTYPE:
358 // Used when assignment is done above
363 case _VCSCANF_UNDEF: *ptr._int = ival; break;
364 case _VCSCANF_CHAR: *ptr._char = ival; break;
365 case _VCSCANF_SHORT: *ptr._short = ival; break;
366 case _VCSCANF_LONG: *ptr._long = ival; break;
367 case _VCSCANF_LONGLONG: *ptr._longlong = ival; break;
382 int _vsscanf_getc(void *h)
384 const char **ibuf = h;
385 return *(*ibuf)++; // Dereference, read for return, increment
388 void _vsscanf_rewind(void *h)
390 const char **ibuf = h;
391 (*ibuf) --; // NOTE: Breaks if there's a rewind before a getc, but that shouldn't happen
394 int vscanf(const char *format, va_list ap)
396 return vfscanf(stdin, format, ap);
399 int vsscanf(const char *str, const char *format, va_list ap)
401 return _vcscanf(_vsscanf_getc, _vsscanf_rewind, &str, format, ap);
404 int _vfscanf_getc(void *h)
406 return fgetc(h); // TODO: Handle -1 -> 0
408 void _vfscanf_rewind(void *h)
410 fseek(h, -1, SEEK_CUR);
413 int vfscanf(FILE *stream, const char *format, va_list ap)
415 return _vcscanf(_vfscanf_getc, _vfscanf_rewind, stream, format, ap);
418 int scanf(const char *format, ...)
422 va_start(args, format);
423 rv = vfscanf(stdin, format, args);
427 int fscanf(FILE *stream, const char *format, ...)
431 va_start(args, format);
432 rv = vfscanf(stream, format, args);
436 int sscanf(const char *str, const char *format, ...)
440 va_start(args, format);
441 rv = vsscanf(str, format, args);