2013-12-09 22:04:24 +00:00
|
|
|
//
|
|
|
|
// scanf.c
|
|
|
|
// test
|
|
|
|
//
|
|
|
|
// Created by crinq on 05.12.13.
|
|
|
|
// Copyright (c) 2013 Rene Hopf. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "scanf.h"
|
|
|
|
|
2016-01-24 13:13:40 +00:00
|
|
|
int sscanf_(const char *buf, const char *format, ...){
|
2016-01-19 16:24:33 +00:00
|
|
|
int ret = 0;
|
2014-09-17 00:45:19 +00:00
|
|
|
|
2016-01-19 16:24:33 +00:00
|
|
|
va_list arg;
|
|
|
|
va_start(arg, format);
|
|
|
|
ret = vfsscanf_(buf, format, arg);
|
|
|
|
va_end(arg);
|
|
|
|
return(ret);
|
2014-09-17 00:45:19 +00:00
|
|
|
}
|
2013-12-09 22:04:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
int isBinDigit(char c){
|
2016-01-19 16:24:33 +00:00
|
|
|
return(c == '0' || c == '1');
|
2013-12-09 22:04:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int isChar(char c){
|
2016-01-19 16:24:33 +00:00
|
|
|
return((c <= 'Z' && c >= 'A') || (c <= 'z' && c >= 'a') || isDecDigit(c));
|
2013-12-09 22:04:24 +00:00
|
|
|
}
|
|
|
|
|
2014-11-16 22:42:01 +00:00
|
|
|
int isNameChar(char c){
|
2016-01-19 16:24:33 +00:00
|
|
|
return(isChar(c) || c == '_' || c == '-' || c == '.');
|
2014-11-16 22:42:01 +00:00
|
|
|
}
|
|
|
|
|
2013-12-09 22:04:24 +00:00
|
|
|
int isDecDigit(char c){
|
2016-01-19 16:24:33 +00:00
|
|
|
return(c >= '0' && c <= '9');
|
2013-12-09 22:04:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int isHexDigit(char c){
|
2016-01-19 16:24:33 +00:00
|
|
|
return((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'));
|
2013-12-09 22:04:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int isWhitespace(char c){
|
2016-01-19 16:24:33 +00:00
|
|
|
return(c == ' ' || c == '\t');
|
2013-12-09 22:04:24 +00:00
|
|
|
}
|
|
|
|
|
2014-09-17 00:45:19 +00:00
|
|
|
int vfsscanf_(const char *buf, const char *format, va_list arg){
|
2016-01-19 16:24:33 +00:00
|
|
|
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);
|
|
|
|
}
|