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;
153 enum e_vcscanf_sizes size = _VCSCANF_UNDEF;
154 enum e_vcscanf_types valtype;
156 const char *set_start;
159 // Whitespace matches any ammount of whitespace (including none)
162 while( (ich = __getc(h)) && isspace(ich) )
167 // Any non-whitespace and non-% characters must match exactly
170 if( __getc(h) != fch )
182 if( __getc(h) != '%' )
188 // %n$ - Direct offset selection, shouldn't be mixed with just %
190 for( ; isdigit(fch); fch = *format++ )
191 maxlen = maxlen * 10 + (fch - '0');
198 // Supress assignemnt?
206 ptr._void = va_arg(ap, void*);
209 while( isdigit(fch) )
211 maxlen = maxlen * 10 + fch - '0';
220 size = _VCSCANF_SHORT;
224 size = _VCSCANF_CHAR;
230 size = _VCSCANF_LONG;
234 size = _VCSCANF_LONGLONG;
240 size = _VCSCANF_INTMAX;
245 size = _VCSCANF_SIZET;
250 size = _VCSCANF_PTRDIFF;
254 // 'long double' (a, A, e, E, f, F, g, G)
255 size = _VCSCANF_LONGDOUBLE;
265 nch += _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
266 valtype = _VCSCANF_INT;
268 // variable-base integer
270 nch += _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
271 valtype = _VCSCANF_INT;
275 nch += _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
276 valtype = _VCSCANF_INT;
278 // Hexadecimal integer
280 nch += _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
281 valtype = _VCSCANF_INT;
283 // strtod format float
288 valtype = _VCSCANF_REAL;
290 // `maxlen` or 1 characters
294 while( maxlen -- && (ich = __getc(h)) )
296 if(ptr._char) *ptr._char++ = ich;
299 valtype = _VCSCANF_NOTYPE;
301 // sequence of non-whitespace characters
307 while( maxlen -- && (ich = __getc(h)) && !isblank(ich) )
309 if(ptr._char) *ptr._char++ = ich;
312 if( maxlen >= 0 && ich )
314 valtype = _VCSCANF_NOTYPE;
316 // match a set of characters
325 // if the first character is ']' it's part of the set
327 // permissable character
330 } while( fch && fch != ']' );
333 while( maxlen -- && (ich = __getc(h)) && memchr(set_start, set_len, ich) )
335 if(ptr._char) *ptr._char++ = ich;
338 if( maxlen >= 0 && ich )
340 valtype = _VCSCANF_NOTYPE;
342 case 'p': // read back printf("%p")
343 valtype = _VCSCANF_NOTYPE;
345 case 'n': // number of read characters to this point
348 ret --; // negates the ret ++ at the end
350 valtype = _VCSCANF_NOTYPE;
353 // Implimentation defined
354 valtype = _VCSCANF_NOTYPE;
360 case _VCSCANF_NOTYPE:
361 // Used when assignment is done above
366 case _VCSCANF_UNDEF: *ptr._int = ival; break;
367 case _VCSCANF_CHAR: *ptr._char = ival; break;
368 case _VCSCANF_SHORT: *ptr._short = ival; break;
369 case _VCSCANF_LONG: *ptr._long = ival; break;
370 case _VCSCANF_LONGLONG: *ptr._longlong = ival; break;
385 int _vsscanf_getc(void *h)
387 const char **ibuf = h;
388 return *(*ibuf)++; // Dereference, read for return, increment
391 void _vsscanf_rewind(void *h)
393 const char **ibuf = h;
394 (*ibuf) --; // NOTE: Breaks if there's a rewind before a getc, but that shouldn't happen
397 int vscanf(const char *format, va_list ap)
399 return vfscanf(stdin, format, ap);
402 int vsscanf(const char *str, const char *format, va_list ap)
404 return _vcscanf(_vsscanf_getc, _vsscanf_rewind, &str, format, ap);
407 int _vfscanf_getc(void *h)
409 return fgetc(h); // TODO: Handle -1 -> 0
411 void _vfscanf_rewind(void *h)
413 fseek(h, -1, SEEK_CUR);
416 int vfscanf(FILE *stream, const char *format, va_list ap)
418 return _vcscanf(_vfscanf_getc, _vfscanf_rewind, stream, format, ap);
421 int scanf(const char *format, ...)
425 va_start(args, format);
426 rv = vfscanf(stdin, format, args);
430 int fscanf(FILE *stream, const char *format, ...)
434 va_start(args, format);
435 rv = vfscanf(stream, format, args);
439 int sscanf(const char *str, const char *format, ...)
443 va_start(args, format);
444 rv = vsscanf(str, format, args);