µGFX  2.9
version 2.9
gfile_scang.c
1 /*
2  * This file is subject to the terms of the GFX License. If a copy of
3  * the license was not distributed with this file, you can obtain one at:
4  *
5  * http://ugfx.io/license.html
6  */
7 
8 /********************************************************
9  * Scang Routines
10  ********************************************************/
11 
12 #include "../../gfx.h"
13 
14 #if GFX_USE_GFILE && GFILE_NEED_SCANG
15 
16 int fscang(GFILE *f, const char *fmt, ...) {
17  int res;
18  va_list ap;
19 
20  va_start(ap, fmt);
21  res = vfscang(f, fmt, ap);
22  va_end(ap);
23  return res;
24 }
25 
26 int vfscang(GFILE *f, const char *fmt, va_list arg) {
27  int res, width, size, base;
28  unsigned long num;
29  char c;
30  gBool assign, negate;
31  char *p;
32 
33  for(res = 0; *fmt; fmt++) {
34  switch(*fmt) {
35  case ' ': case '\t': case '\r': case '\n': case '\v': case '\f':
36  break;
37 
38  case '%':
39  fmt++;
40  assign = gTrue;
41  negate = gFalse;
42  width = 0;
43  size = 1;
44  num = 0;
45 
46  if (*fmt == '*') {
47  fmt++;
48  assign = gFalse;
49  }
50  while(*fmt >= '0' && *fmt <= '9')
51  width = width * 10 + (*fmt++ - '0');
52  if (*fmt == 'h') {
53  fmt++;
54  size = 0;
55  } else if (*fmt == 'l') {
56  fmt++;
57  size = 2;
58  } else if (*fmt == 'L') {
59  fmt++;
60  size = 3;
61  }
62  switch(*fmt) {
63  case 0:
64  return res;
65  case '%':
66  goto matchchar;
67  case 'c':
68  if (!width) {
69  while(1) {
70  if (!gfileRead(f, &c, 1)) return res;
71  switch(c) {
72  case ' ': case '\t': case '\r':
73  case '\n': case '\v': case '\f': continue;
74  }
75  break;
76  }
77  width = 1;
78  } else {
79  if (!gfileRead(f, &c, 1)) return res;
80  }
81  if (assign) {
82  p = va_arg(arg, char *);
83  res++;
84  *p++ = c;
85  }
86  while(--width) {
87  if (!gfileRead(f, &c, 1)) return res;
88  if (assign) *p++ = c;
89  }
90  break;
91  case 's':
92  while(1) {
93  if (!gfileRead(f, &c, 1)) return res;
94  switch(c) {
95  case ' ': case '\t': case '\r':
96  case '\n': case '\v': case '\f': continue;
97  }
98  break;
99  }
100  if (assign) {
101  p = va_arg(arg, char *);
102  res++;
103  *p++ = c;
104  }
105  if (width) {
106  while(--width) {
107  if (!gfileRead(f, &c, 1)) {
108  if (assign) *((char *)p) = 0;
109  return res;
110  }
111  if (assign) *p++ = c;
112  }
113  } else {
114  while(1) {
115  if (!gfileRead(f, &c, 1)) {
116  if (assign) *((char *)p) = 0;
117  return res;
118  }
119  switch(c) {
120  case ' ': case '\t': case '\r':
121  case '\n': case '\v': case '\f': break;
122  default:
123  if (assign) *p++ = c;
124  continue;
125  }
126  break;
127  }
128  //ungetch(c);
129  }
130  if (assign) *p = 0;
131  break;
132  case 'd': base = 10; goto getnum;
133  case 'i': base = -1; goto getnum;
134  case 'o': base = 8; goto getnum;
135  case 'u': base = 10; goto getnum;
136  case 'x': base = 16; goto getnum;
137  case 'b': base = 2;
138  getnum:
139  while(1) {
140  if (!gfileRead(f, &c, 1)) return res;
141  switch(c) {
142  case ' ': case '\t': case '\r':
143  case '\n': case '\v': case '\f': continue;
144  }
145  break;
146  }
147  if (c == '-' && *fmt != 'u') {
148  negate = gTrue;
149  if ((width && !--width) || !gfileRead(f, &c, 1)) return res;
150  }
151  if (base == -1) {
152  if (c == '0') {
153  if ((width && !--width) || !gfileRead(f, &c, 1)) goto assignnum;
154  switch(c) {
155  case 'x': case 'X':
156  base = 16;
157  if ((width && !--width) || !gfileRead(f, &c, 1)) return res;
158  break;
159  case 'b': case 'B':
160  base = 2;
161  if ((width && !--width) || !gfileRead(f, &c, 1)) return res;
162  break;
163  default:
164  base = 8;
165  break;
166  }
167  } else
168  base = 10;
169  }
170  while(1) {
171  if (c >= '0' && c <= '9' && c - '0' < base)
172  num = num * base + (c - '0');
173  else if (c >= 'A' && c <= 'F' && base == 16)
174  num = num * base + (c - ('A'-10));
175  else if (c >= 'a' && c <= 'f' && base == 16)
176  num = num * base + (c - ('a'-10));
177  else {
178  // ungetch(c)
179  break;
180  }
181  if ((width && !--width) || !gfileRead(f, &c, 1))
182  break;
183  }
184 
185  assignnum:
186  if (negate)
187  num = -num;
188 
189  if (assign) {
190  switch(size) {
191  case 0: // short
192  p = (char *)va_arg(arg, short *);
193  res++;
194  *((short *)p) = (short)num;
195  case 1: // int
196  p = (char *)va_arg(arg, int *);
197  res++;
198  *((int *)p) = (int)num;
199  case 2: case 3: // long
200  p = (char *)va_arg(arg, long *);
201  res++;
202  *((long *)p) = (long)num;
203  }
204  }
205  break;
206 
207  #if GFILE_ALLOW_FLOATS
208  case 'e': case 'f': case 'g':
209  // TODO
210  #endif
211  default:
212  return res;
213  }
214 
215  break;
216 
217  default:
218  matchchar:
219  while(1) {
220  if (!gfileRead(f, &c, 1)) return res;
221  switch(c) {
222  case ' ': case '\t': case '\r':
223  case '\n': case '\v': case '\f': continue;
224  }
225  break;
226  }
227  if (c != *fmt) return res;
228  break;
229  }
230  }
231  return res;
232 }
233 
234 #endif //GFX_USE_GFILE && GFILE_NEED_SCANG
gMemSize gfileRead(GFILE *f, void *buf, gMemSize len)
Read from file.
struct GFILE GFILE
A file pointer.
Definition: gfile.h:34