source: EcnlProtoTool/trunk/prototool/src/xprintf.c@ 279

Last change on this file since 279 was 279, checked in by coas-nagasima, 7 years ago

ファイルを追加、更新。

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 9.8 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1999 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 *
22 * Purpose:
23 * A merge of Bjorn Reese's format() function and Daniel's dsprintf()
24 * 1.0. A full blooded printf() clone with full support for <num>$
25 * everywhere (parameters, widths and precisions) including variabled
26 * sized parameters (like doubles, long longs, long doubles and even
27 * void * in 64-bit architectures).
28 *
29 * Current restrictions:
30 * - Max 128 parameters
31 * - No 'long double' support.
32 *
33 * If you ever want truly portable and good *printf() clones, the project that
34 * took on from here is named 'Trio' and you find more details on the trio web
35 * page at https://daniel.haxx.se/trio/
36 */
37
38/*------------------------------------------------------------------------/
39/ Universal string handler for user console interface
40/-------------------------------------------------------------------------/
41/
42/ Copyright (C) 2011, ChaN, all right reserved.
43/
44/ * This software is a free software and there is NO WARRANTY.
45/ * No restriction on use. You can use, modify and redistribute it for
46/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
47/ * Redistributions of source code must retain the above copyright notice.
48/
49/-------------------------------------------------------------------------*/
50
51#include <stdarg.h>
52#include <stdio.h>
53#include <string.h>
54#include <stdlib.h>
55
56struct nsprintf {
57 char *buffer;
58 size_t length;
59 size_t max;
60};
61
62struct asprintf {
63 char *buffer; /* allocated buffer */
64 size_t len; /* length of string */
65 size_t alloc; /* length of alloc */
66 int fail; /* (!= 0) if an alloc has failed and thus
67 the output is not the complete data */
68};
69
70#define OUTCHAR(x) \
71 do{ \
72 if(stream((unsigned char)(x), (FILE *)data) != -1) \
73 done++; \
74 else \
75 return done; /* return immediately on failure */ \
76 } while(0)
77
78
79static int dprintf_formatf(
80 void *data,
81 int(*stream)(int, FILE *),
82 const char *fmt,
83 va_list arp)
84{
85 unsigned int r, i, j, w, f;
86 unsigned long v;
87 char s[16], c, d, *p;
88
89 /* Number of characters written. */
90 int done = 0;
91
92 for (;;) {
93 c = *fmt++; /* Get a char */
94 if (!c) break; /* End of format? */
95 if (c != '%') { /* Pass through it if not a % sequense */
96 OUTCHAR(c); continue;
97 }
98 f = 0;
99 c = *fmt++; /* Get first char of the sequense */
100 if (c == '0') { /* Flag: '0' padded */
101 f = 1; c = *fmt++;
102 }
103 else {
104 if (c == '-') { /* Flag: left justified */
105 f = 2; c = *fmt++;
106 }
107 }
108 for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */
109 w = w * 10 + c - '0';
110 if (c == 'l' || c == 'L') { /* Prefix: Size is long int */
111 f |= 4; c = *fmt++;
112 }
113 else if (c == 'h') { /* Prefix: Size is short int */
114 f |= 16; c = *fmt++;
115 }
116 if (!c) break; /* End of format? */
117 d = c;
118 if (d >= 'a') d -= 0x20;
119 switch (d) { /* Type is... */
120 case 'S': /* String */
121 p = va_arg(arp, char*);
122 for (j = 0; p[j]; j++);
123 while (!(f & 2) && j++ < w) OUTCHAR(' ');
124 for (; *p; p++)
125 OUTCHAR(*p);
126 while (j++ < w) OUTCHAR(' ');
127 continue;
128 case 'C': /* Character */
129 OUTCHAR((char)va_arg(arp, int)); continue;
130 case 'B': /* Binary */
131 r = 2; break;
132 case 'O': /* Octal */
133 r = 8; break;
134 case 'D': /* Signed decimal */
135 case 'U': /* Unsigned decimal */
136 r = 10; break;
137 case 'X': /* Hexdecimal */
138 r = 16; break;
139 default: /* Unknown type (passthrough) */
140 OUTCHAR(c); continue;
141 }
142
143 /* Get an argument and put it in numeral */
144 v = (f & 4) ? va_arg(arp, long)
145 : ((f & 16) ? ((d == 'D') ? (long)va_arg(arp, short) : (long)va_arg(arp, unsigned short))
146 : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int)));
147 if (d == 'D' && (v & 0x80000000)) {
148 v = 0 - v;
149 f |= 8;
150 }
151 i = 0;
152 do {
153 d = (char)(v % r); v /= r;
154 if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
155 s[i++] = d + '0';
156 } while (v && i < sizeof(s));
157 if (f & 8) s[i++] = '-';
158 j = i; d = (f & 1) ? '0' : ' ';
159 while (!(f & 2) && j++ < w) OUTCHAR(d);
160 do OUTCHAR(s[--i]); while (i);
161 while (j++ < w) OUTCHAR(' ');
162 }
163 return done;
164}
165/* fputc() look-alike */
166static int addbyter(int output, FILE *data)
167{
168 struct nsprintf *infop=(struct nsprintf *)data;
169 unsigned char outc = (unsigned char)output;
170
171 if(infop->length < infop->max) {
172 /* only do this if we haven't reached max length yet */
173 infop->buffer[0] = outc; /* store */
174 infop->buffer++; /* increase pointer */
175 infop->length++; /* we are now one byte larger */
176 return outc; /* fputc() returns like this on success */
177 }
178 return -1;
179}
180
181int vsnprintf(char *buffer, size_t maxlength, const char *format,
182 va_list ap_save)
183{
184 int retcode;
185 struct nsprintf info;
186
187 info.buffer = buffer;
188 info.length = 0;
189 info.max = maxlength;
190
191 retcode = dprintf_formatf(&info, addbyter, format, ap_save);
192 if(info.max) {
193 /* we terminate this with a zero byte */
194 if(info.max == info.length)
195 /* we're at maximum, scrap the last letter */
196 info.buffer[-1] = 0;
197 else
198 info.buffer[0] = 0;
199 }
200 return retcode;
201}
202
203int snprintf(char *buffer, size_t maxlength, const char *format, ...)
204{
205 int retcode;
206 va_list ap_save; /* argument pointer */
207 va_start(ap_save, format);
208 retcode = vsnprintf(buffer, maxlength, format, ap_save);
209 va_end(ap_save);
210 return retcode;
211}
212
213/* fputc() look-alike */
214static int alloc_addbyter(int output, FILE *data)
215{
216 struct asprintf *infop=(struct asprintf *)data;
217 unsigned char outc = (unsigned char)output;
218
219 if(!infop->buffer) {
220 infop->buffer = malloc(32);
221 if(!infop->buffer) {
222 infop->fail = 1;
223 return -1; /* fail */
224 }
225 infop->alloc = 32;
226 infop->len =0;
227 }
228 else if(infop->len+1 >= infop->alloc) {
229 char *newptr;
230
231 newptr = realloc(infop->buffer, infop->alloc*2);
232
233 if(!newptr) {
234 infop->fail = 1;
235 return -1; /* fail */
236 }
237 infop->buffer = newptr;
238 infop->alloc *= 2;
239 }
240
241 infop->buffer[ infop->len ] = outc;
242
243 infop->len++;
244
245 return outc; /* fputc() returns like this on success */
246}
247
248char *aprintf(const char *format, ...)
249{
250 va_list ap_save; /* argument pointer */
251 int retcode;
252 struct asprintf info;
253
254 info.buffer = NULL;
255 info.len = 0;
256 info.alloc = 0;
257 info.fail = 0;
258
259 va_start(ap_save, format);
260 retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
261 va_end(ap_save);
262 if((-1 == retcode) || info.fail) {
263 if(info.alloc)
264 free(info.buffer);
265 return NULL;
266 }
267 if(info.alloc) {
268 info.buffer[info.len] = 0; /* we terminate this with a zero byte */
269 return info.buffer;
270 }
271 else
272 return strdup("");
273}
274
275char *vaprintf(const char *format, va_list ap_save)
276{
277 int retcode;
278 struct asprintf info;
279
280 info.buffer = NULL;
281 info.len = 0;
282 info.alloc = 0;
283 info.fail = 0;
284
285 retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
286 if((-1 == retcode) || info.fail) {
287 if(info.alloc)
288 free(info.buffer);
289 return NULL;
290 }
291
292 if(info.alloc) {
293 info.buffer[info.len] = 0; /* we terminate this with a zero byte */
294 return info.buffer;
295 }
296 else
297 return strdup("");
298}
299
300int vasprintf(char **dst, const char *format, va_list ap_save)
301{
302 int retcode;
303 struct asprintf info;
304
305 info.buffer = NULL;
306 info.len = 0;
307 info.alloc = 0;
308 info.fail = 0;
309
310 retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
311 if ((-1 == retcode) || info.fail) {
312 if (info.alloc)
313 free(info.buffer);
314 return -1;
315 }
316
317 if (info.alloc) {
318 info.buffer[info.len] = 0; /* we terminate this with a zero byte */
319 *dst = info.buffer;
320 return info.len;
321 }
322 else {
323 *dst = strdup("");
324 return 0;
325 }
326}
327
328static int storebuffer(int output, FILE *data)
329{
330 char **buffer = (char **)data;
331 unsigned char outc = (unsigned char)output;
332 **buffer = outc;
333 (*buffer)++;
334 return outc; /* act like fputc() ! */
335}
336
337int sprintf(char *buffer, const char *format, ...)
338{
339 va_list ap_save; /* argument pointer */
340 int retcode;
341 va_start(ap_save, format);
342 retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
343 va_end(ap_save);
344 *buffer=0; /* we terminate this with a zero byte */
345 return retcode;
346}
347
348int printf(const char *format, ...)
349{
350 int retcode;
351 va_list ap_save; /* argument pointer */
352 va_start(ap_save, format);
353
354 retcode = dprintf_formatf(stdout, fputc, format, ap_save);
355 va_end(ap_save);
356 return retcode;
357}
358
359int fprintf(FILE *whereto, const char *format, ...)
360{
361 int retcode;
362 va_list ap_save; /* argument pointer */
363 va_start(ap_save, format);
364 retcode = dprintf_formatf(whereto, fputc, format, ap_save);
365 va_end(ap_save);
366 return retcode;
367}
368
369int vsprintf(char *buffer, const char *format, va_list ap_save)
370{
371 int retcode;
372 retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
373 *buffer=0; /* we terminate this with a zero byte */
374 return retcode;
375}
376
377int vprintf(const char *format, va_list ap_save)
378{
379 return dprintf_formatf(stdout, fputc, format, ap_save);
380}
381
382int vfprintf(FILE *whereto, const char *format, va_list ap_save)
383{
384 return dprintf_formatf(whereto, fputc, format, ap_save);
385}
Note: See TracBrowser for help on using the repository browser.