µGFX  2.9
version 2.9
gfile_printg.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  * Printg Routines
10  ********************************************************/
11 
12 #include "../../gfx.h"
13 
14 #if GFX_USE_GFILE && GFILE_NEED_PRINTG
15 
16 #include <stdarg.h>
17 
18 #define MAX_FILLER 11
19 #define FLOAT_PRECISION 100000
20 
21 int fnprintg(GFILE *f, int maxlen, const char *fmt, ...) {
22  int res;
23  va_list ap;
24 
25  va_start(ap, fmt);
26  res = vfnprintg(f, maxlen, fmt, ap);
27  va_end(ap);
28  return res;
29 }
30 
31 static char *ltoa_wd(char *p, long num, unsigned radix, long divisor) {
32  int i;
33  char * q;
34 
35  if (!divisor) divisor = num;
36 
37  q = p + MAX_FILLER;
38  do {
39  i = (int)(num % radix);
40  i += '0';
41  if (i > '9')
42  i += 'A' - '0' - 10;
43  *--q = i;
44  num /= radix;
45  } while ((divisor /= radix) != 0);
46 
47  i = (int)(p + MAX_FILLER - q);
48  do {
49  *p++ = *q++;
50  } while (--i);
51 
52  return p;
53 }
54 
55 int vfnprintg(GFILE *f, int maxlen, const char *fmt, va_list arg) {
56  int ret;
57  char *p, *s, c, filler;
58  int i, precision, width;
59  gBool is_long, left_align;
60  long l;
61  #if GFILE_ALLOW_FLOATS
62  float fpv;
63  char tmpbuf[2*MAX_FILLER + 1];
64  #else
65  char tmpbuf[MAX_FILLER + 1];
66  #endif
67 
68  ret = 0;
69  if (maxlen < 0)
70  return 0;
71  if (!maxlen)
72  maxlen = -1;
73 
74  while (*fmt) {
75  if (*fmt != '%') {
76  gfileWrite(f, fmt, 1);
77  ret++; if (!--maxlen) return ret;
78  fmt++;
79  continue;
80  }
81  fmt++;
82 
83  p = s = tmpbuf;
84  left_align = gFalse;
85  filler = ' ';
86  width = 0;
87  precision = 0;
88 
89  if (*fmt == '-') {
90  fmt++;
91  left_align = gTrue;
92  }
93  if (*fmt == '0') {
94  fmt++;
95  filler = '0';
96  }
97 
98  while (1) {
99  c = *fmt++;
100  if (c >= '0' && c <= '9') {
101  c -= '0';
102  width = width * 10 + c;
103  } else if (c == '*')
104  width = va_arg(arg, int);
105  else
106  break;
107  }
108  if (c == '.') {
109  while (1) {
110  c = *fmt++;
111  if (c >= '0' && c <= '9') {
112  c -= '0';
113  precision = precision * 10 + c;
114  } else if (c == '*')
115  precision = va_arg(arg, int);
116  else
117  break;
118  }
119  }
120  /* Long modifier.*/
121  if (c == 'l' || c == 'L') {
122  is_long = gTrue;
123  if (*fmt)
124  c = *fmt++;
125  }
126  else
127  is_long = (c >= 'A') && (c <= 'Z');
128 
129  /* Command decoding.*/
130  switch (c) {
131  case 0:
132  return ret;
133  case 'c':
134  filler = ' ';
135  *p++ = va_arg(arg, int);
136  break;
137  case 's':
138  filler = ' ';
139  if ((s = va_arg(arg, char *)) == 0)
140  s = "(null)";
141  if (precision == 0)
142  precision = 32767;
143  for (p = s; *p && (--precision >= 0); p++);
144  break;
145  case 'D':
146  case 'd':
147  if (is_long)
148  l = va_arg(arg, long);
149  else
150  l = va_arg(arg, int);
151  if (l < 0) {
152  *p++ = '-';
153  l = -l;
154  }
155  p = ltoa_wd(p, l, 10, 0);
156  break;
157  #if GFILE_ALLOW_FLOATS
158  case 'f':
159  fpv = (float) va_arg(arg, double);
160  if (fpv < 0) {
161  *p++ = '-';
162  fpv = -fpv;
163  }
164  l = fpv;
165  p = ltoa_wd(p, l, 10, 0);
166  *p++ = '.';
167  l = (fpv - l) * FLOAT_PRECISION;
168  p = ltoa_wd(p, l, 10, FLOAT_PRECISION / 10);
169  break;
170  #endif
171  case 'X':
172  case 'x':
173  c = 16;
174  goto unsigned_common;
175  case 'U':
176  case 'u':
177  c = 10;
178  goto unsigned_common;
179  case 'O':
180  case 'o':
181  c = 8;
182  unsigned_common:
183  if (is_long)
184  l = va_arg(arg, long);
185  else
186  l = va_arg(arg, int);
187  p = ltoa_wd(p, l, c, 0);
188  break;
189  default:
190  *p++ = c;
191  break;
192  }
193 
194  i = (int)(p - s);
195  if ((width -= i) < 0)
196  width = 0;
197  if (!left_align)
198  width = -width;
199  if (width < 0) {
200  if (*s == '-' && filler == '0') {
201  gfileWrite(f, s++, 1);
202  ret++; if (!--maxlen) return ret;
203  i--;
204  }
205  do {
206  gfileWrite(f, &filler, 1);
207  ret++; if (!--maxlen) return ret;
208  } while (++width != 0);
209  }
210  while (--i >= 0) {
211  gfileWrite(f, s++, 1);
212  ret++; if (!--maxlen) return ret;
213  }
214  while (width) {
215  gfileWrite(f, &filler, 1);
216  ret++; if (!--maxlen) return ret;
217  width--;
218  }
219  }
220  return ret;
221 }
222 
223 #endif //GFX_USE_GFILE && GFILE_NEED_PRINTG
struct GFILE GFILE
A file pointer.
Definition: gfile.h:34
gMemSize gfileWrite(GFILE *f, const void *buf, gMemSize len)
Write to file.