// // scanf.c // test // // Created by crinq on 05.12.13. // Copyright (c) 2013 Rene Hopf. All rights reserved. // #include "scanf.h" int sscanf_(const char *buf, const char *format, ...){ int ret = 0; va_list arg; va_start(arg, format); ret = vfsscanf_(buf, format, arg); va_end(arg); return(ret); } int isBinDigit(char c){ return(c == '0' || c == '1'); } int isChar(char c){ return((c <= 'Z' && c >= 'A') || (c <= 'z' && c >= 'a') || isDecDigit(c)); } int isNameChar(char c){ return(isChar(c) || c == '_' || c == '-' || c == '.'); } int isDecDigit(char c){ return(c >= '0' && c <= '9'); } int isHexDigit(char c){ return((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')); } int isWhitespace(char c){ return(c == ' ' || c == '\t'); } int vfsscanf_(const char *buf, const char *format, va_list arg){ int buffer_pos = 0; int format_pos = 0; int string_pos = 0; int ret = 0; int found = 0; int *i; float *f; char *c; int invert; float tf; int state = 0; // 0 = last char = normal char // 1 = last char = '%' // 2 = last char = '\' while(format[format_pos]){ found = 0; switch(state){ case 0: switch(format[format_pos]){ case '%': state = 1; format_pos++; continue; break; case '\'': state = 2; format_pos++; continue; break; case ' ': // parse whithespaces while(isWhitespace(buf[buffer_pos])){ buffer_pos++; found++; } found++; break; default: if(format[format_pos] != buf[buffer_pos++]){ return(ret); } found++; } break; case 1: switch(format[format_pos]){ case '%': if(buf[buffer_pos++] != '%'){ return(ret); } found++; break; case 'c': c = va_arg(arg, char *); *c = buf[buffer_pos++]; found++; break; case 's': string_pos = 0; c = va_arg(arg, char *); //while(isChar(buf[buffer_pos])){ while(!isWhitespace(buf[buffer_pos])){ c[string_pos] = buf[buffer_pos++]; string_pos++; c[string_pos] = '\0'; found++; } break; case 'N': string_pos = 0; c = va_arg(arg, char *); //while(isChar(buf[buffer_pos])){ while(isNameChar(buf[buffer_pos])){ c[string_pos] = buf[buffer_pos++]; string_pos++; c[string_pos] = '\0'; found++; } break; case 'i': i = va_arg(arg, int *); *i = 0; invert = 1; if(buf[buffer_pos] == '-'){ invert = -1; buffer_pos++; } else if(buf[buffer_pos] == '+'){ buffer_pos++; } while(isDecDigit(buf[buffer_pos])){ *i *= 10; *i += buf[buffer_pos++] - '0'; found++; } *i *= invert; break; case 'b': i = va_arg(arg, int *); *i = 0; invert = 1; if(buf[buffer_pos] == '-'){ invert = -1; buffer_pos++; } else if(buf[buffer_pos] == '+'){ buffer_pos++; } if(!(buf[buffer_pos] == 'b' || buf[buffer_pos] == 'B')){ return(ret); } buffer_pos++; while(isBinDigit(buf[buffer_pos])){ *i *= 2; *i += buf[buffer_pos++] - '0'; found++; } *i *= invert; break; case 'h': i = va_arg(arg, int *); *i = 0; invert = 1; if(buf[buffer_pos] == '-'){ invert = -1; buffer_pos++; } else if(buf[buffer_pos] == '+'){ buffer_pos++; } if(buf[buffer_pos++] != '0'){ return(ret); } if(buf[buffer_pos++] != 'x'){ return(ret); } while(isHexDigit(buf[buffer_pos])){ *i *= 16; if(buf[buffer_pos] < 'A'){ *i += buf[buffer_pos++] - '0'; } else if(buf[buffer_pos] < 'a'){ *i += buf[buffer_pos++] - 'A' + 10; } else{ *i += buf[buffer_pos++] - 'a' + 10; } found++; } *i *= invert; break; case 'f': f = va_arg(arg, float *); *f = 0; tf = 10; invert = 1; if(buf[buffer_pos] == '-'){ invert = -1; buffer_pos++; } else if(buf[buffer_pos] == '+'){ buffer_pos++; } while(isDecDigit(buf[buffer_pos])){ *f *= 10; *f += buf[buffer_pos++] - '0'; found++; } if(buf[buffer_pos] == '.'){ buffer_pos++; while(isDecDigit(buf[buffer_pos])){ *f += (buf[buffer_pos++] - '0') / tf; tf *= 10; found++; } } *f *= invert; break; default: return(ret); break; } state = 0; break; case 2: switch(format[format_pos]){ case '\'': if(buf[buffer_pos++] != '\''){ return(ret); } found++; break; case 'n': if(buf[buffer_pos++] != '\n'){ return(ret); } found++; break; default: return(ret); break; } state = 0; break; default: break; } format_pos++; if(!found){ return(ret); } ret++; } return(ret); }