/* * This file is subject to the terms of the GFX License. If a copy of * the license was not distributed with this file, you can obtain one at: * * http://ugfx.io/license.html */ /******************************************************** * Scang Routines ********************************************************/ #include "../../gfx.h" #if GFX_USE_GFILE && GFILE_NEED_SCANG int fscang(GFILE *f, const char *fmt, ...) { int res; va_list ap; va_start(ap, fmt); res = vfscang(f, fmt, ap); va_end(ap); return res; } int vfscang(GFILE *f, const char *fmt, va_list arg) { int res, width, size, base; unsigned long num; char c; gBool assign, negate; char *p; for(res = 0; *fmt; fmt++) { switch(*fmt) { case ' ': case '\t': case '\r': case '\n': case '\v': case '\f': break; case '%': fmt++; assign = gTrue; negate = gFalse; width = 0; size = 1; num = 0; if (*fmt == '*') { fmt++; assign = gFalse; } while(*fmt >= '0' && *fmt <= '9') width = width * 10 + (*fmt++ - '0'); if (*fmt == 'h') { fmt++; size = 0; } else if (*fmt == 'l') { fmt++; size = 2; } else if (*fmt == 'L') { fmt++; size = 3; } switch(*fmt) { case 0: return res; case '%': goto matchchar; case 'c': if (!width) { while(1) { if (!gfileRead(f, &c, 1)) return res; switch(c) { case ' ': case '\t': case '\r': case '\n': case '\v': case '\f': continue; } break; } width = 1; } else { if (!gfileRead(f, &c, 1)) return res; } if (assign) { p = va_arg(arg, char *); res++; *p++ = c; } while(--width) { if (!gfileRead(f, &c, 1)) return res; if (assign) *p++ = c; } break; case 's': while(1) { if (!gfileRead(f, &c, 1)) return res; switch(c) { case ' ': case '\t': case '\r': case '\n': case '\v': case '\f': continue; } break; } if (assign) { p = va_arg(arg, char *); res++; *p++ = c; } if (width) { while(--width) { if (!gfileRead(f, &c, 1)) { if (assign) *((char *)p) = 0; return res; } if (assign) *p++ = c; } } else { while(1) { if (!gfileRead(f, &c, 1)) { if (assign) *((char *)p) = 0; return res; } switch(c) { case ' ': case '\t': case '\r': case '\n': case '\v': case '\f': break; default: if (assign) *p++ = c; continue; } break; } //ungetch(c); } if (assign) *p = 0; break; case 'd': base = 10; goto getnum; case 'i': base = -1; goto getnum; case 'o': base = 8; goto getnum; case 'u': base = 10; goto getnum; case 'x': base = 16; goto getnum; case 'b': base = 2; getnum: while(1) { if (!gfileRead(f, &c, 1)) return res; switch(c) { case ' ': case '\t': case '\r': case '\n': case '\v': case '\f': continue; } break; } if (c == '-' && *fmt != 'u') { negate = gTrue; if ((width && !--width) || !gfileRead(f, &c, 1)) return res; } if (base == -1) { if (c == '0') { if ((width && !--width) || !gfileRead(f, &c, 1)) goto assignnum; switch(c) { case 'x': case 'X': base = 16; if ((width && !--width) || !gfileRead(f, &c, 1)) return res; break; case 'b': case 'B': base = 2; if ((width && !--width) || !gfileRead(f, &c, 1)) return res; break; default: base = 8; break; } } else base = 10; } while(1) { if (c >= '0' && c <= '9' && c - '0' < base) num = num * base + (c - '0'); else if (c >= 'A' && c <= 'F' && base == 16) num = num * base + (c - ('A'-10)); else if (c >= 'a' && c <= 'f' && base == 16) num = num * base + (c - ('a'-10)); else { // ungetch(c) break; } if ((width && !--width) || !gfileRead(f, &c, 1)) break; } assignnum: if (negate) num = -num; if (assign) { switch(size) { case 0: // short p = (char *)va_arg(arg, short *); res++; *((short *)p) = (short)num; case 1: // int p = (char *)va_arg(arg, int *); res++; *((int *)p) = (int)num; case 2: case 3: // long p = (char *)va_arg(arg, long *); res++; *((long *)p) = (long)num; } } break; #if GFILE_ALLOW_FLOATS case 'e': case 'f': case 'g': // TODO #endif default: return res; } break; default: matchchar: while(1) { if (!gfileRead(f, &c, 1)) return res; switch(c) { case ' ': case '\t': case '\r': case '\n': case '\v': case '\f': continue; } break; } if (c != *fmt) return res; break; } } return res; } #endif //GFX_USE_GFILE && GFILE_NEED_SCANG