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;
158 const char *set_start;
161 // Whitespace matches any ammount of whitespace (including none)
164 while( (ich = __getc(h)) && isspace(ich) )
170 // Any non-whitespace and non-% characters must match exactly
173 if( __getc(h) != fch )
185 if( __getc(h) != '%' )
191 // %n$ - Direct offset selection, shouldn't be mixed with just %
193 for( ; isdigit(fch); fch = *format++ )
194 maxlen = maxlen * 10 + (fch - '0');
201 // Supress assignemnt?
209 ptr._void = va_arg(ap, void*);
212 while( isdigit(fch) )
214 maxlen = maxlen * 10 + fch - '0';
223 size = _VCSCANF_SHORT;
227 size = _VCSCANF_CHAR;
233 size = _VCSCANF_LONG;
237 size = _VCSCANF_LONGLONG;
243 size = _VCSCANF_INTMAX;
248 size = _VCSCANF_SIZET;
253 size = _VCSCANF_PTRDIFF;
257 // 'long double' (a, A, e, E, f, F, g, G)
258 size = _VCSCANF_LONGDOUBLE;
268 nnewch = _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
269 if(nnewch==0) fail=1;
271 valtype = _VCSCANF_INT;
273 // variable-base integer
275 nnewch = _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
276 if(nnewch==0) fail=1;
278 valtype = _VCSCANF_INT;
282 nnewch = _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
283 if(nnewch==0) fail=1;
285 valtype = _VCSCANF_INT;
287 // Hexadecimal integer
289 nnewch = _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
290 if(nnewch==0) fail=1;
292 valtype = _VCSCANF_INT;
294 // strtod format float
299 valtype = _VCSCANF_REAL;
301 // `maxlen` or 1 characters
305 while( maxlen -- && (ich = __getc(h)) )
307 if(ptr._char) *ptr._char++ = ich;
310 valtype = _VCSCANF_NOTYPE;
312 // sequence of non-whitespace characters
318 while( maxlen -- && (ich = __getc(h)) && !isspace(ich) )
320 if(ptr._char) *ptr._char++ = ich;
323 if( maxlen >= 0 && ich )
325 if(ptr._char) *ptr._char++ = 0;
326 valtype = _VCSCANF_NOTYPE;
328 // match a set of characters
337 // if the first character is ']' it's part of the set
339 // permissable character
342 } while( fch && fch != ']' );
347 while( maxlen -- && (ich = __getc(h)) && memchr(set_start, set_len, ich) )
349 if(ptr._char) *ptr._char++ = ich;
352 if( maxlen >= 0 && ich )
354 if(ptr._char) *ptr._char++ = 0;
355 valtype = _VCSCANF_NOTYPE;
357 case 'p': // read back printf("%p")
358 valtype = _VCSCANF_NOTYPE;
360 case 'n': // number of read characters to this point
363 ret --; // negates the ret ++ at the end
365 valtype = _VCSCANF_NOTYPE;
368 // Implimentation defined
369 valtype = _VCSCANF_NOTYPE;
378 case _VCSCANF_NOTYPE:
379 // Used when assignment is done above
384 case _VCSCANF_UNDEF: *ptr._int = ival; break;
385 case _VCSCANF_CHAR: *ptr._char = ival; break;
386 case _VCSCANF_SHORT: *ptr._short = ival; break;
387 case _VCSCANF_LONG: *ptr._long = ival; break;
388 case _VCSCANF_LONGLONG: *ptr._longlong = ival; break;
403 int _vsscanf_getc(void *h)
405 const char **ibuf = h;
406 return *(*ibuf)++; // Dereference, read for return, increment
409 void _vsscanf_rewind(void *h)
411 const char **ibuf = h;
412 (*ibuf) --; // NOTE: Breaks if there's a rewind before a getc, but that shouldn't happen
415 int vscanf(const char *format, va_list ap)
417 return vfscanf(stdin, format, ap);
420 int vsscanf(const char *str, const char *format, va_list ap)
422 return _vcscanf(_vsscanf_getc, _vsscanf_rewind, &str, format, ap);
425 int _vfscanf_getc(void *h)
428 return ch == -1 ? 0 : ch;
430 void _vfscanf_rewind(void *h)
432 fseek(h, -1, SEEK_CUR);
435 int vfscanf(FILE *stream, const char *format, va_list ap)
437 return _vcscanf(_vfscanf_getc, _vfscanf_rewind, stream, format, ap);
440 int scanf(const char *format, ...)
444 va_start(args, format);
445 rv = vfscanf(stdin, format, args);
449 int fscanf(FILE *stream, const char *format, ...)
453 va_start(args, format);
454 rv = vfscanf(stream, format, args);
458 int sscanf(const char *str, const char *format, ...)
462 va_start(args, format);
463 rv = vsscanf(str, format, args);