add some format info print function
[compress.git] / fprintf.c
CommitLineData
5f83300c
LM
1/*
2 File name : fprintf.c
3 Date of creation : 05/12/2022
4 Version : 1.0
5 Copyright : Soft'n'design
6 Author : Laurent Mazet <mazet@softndesign.org>
7
8 Description : This file contains embedded printf
9
10 History :
11 - initial version
12*/
13
14#include <stdarg.h>
15#include <stddef.h>
16#include <stdio.h>
17
b40343bc 18inline unsigned int nextpow (unsigned int x, int base) {
5f83300c
LM
19 unsigned int n = 0;
20 while (x) {
21 n++;
b40343bc 22 x = x / base;
5f83300c
LM
23 }
24 return (n == 0) ? 1 : n;
25}
26
27/* simple fprintf function */
28
5e0c5bc8 29size_t myfprintf (FILE *fid, const char *fmt, ...)
5f83300c
LM
30{
31 char buffer[1024 + 1] = { 0 };
32 char *str = buffer;
33
34 va_list ap;
35 va_start (ap, fmt);
36 while (*fmt) {
37 char *s;
38 int d = 0;
39 unsigned int u;
5f83300c
LM
40 char c = *fmt++;
41
42 /* copy standard char */
43 if (c != '%') {
44 *str++ = c;
45 } else {
46 int t = 0;
b40343bc
LM
47 char w = '0';
48 size_t i, sz = 0;
49 void *p = NULL;
50
51 /* stamp */
52 if ((*fmt == ' ') || (*fmt == '0')) {
53 w = *fmt++;
54 }
55
56 /* size */
57 if ((*fmt >= '1') && (*fmt <= '9')) {
58 sz = *fmt++ - '0';
59 }
5f83300c
LM
60
61 /* process format char */
62 switch (*fmt++) {
63 case 'c': /* char */
64 c = (char) va_arg (ap, int);
65 *str++ = c;
66 break;
67 case 'd': /* int */
68 d = va_arg (ap, int);
69 if (d < 0) {
70 *str++ = '-';
71 d = -d;
72 }
73 t = 1;
74 /* fall through */
75 case 'u': /* unsigned int */
76 u = (t) ? (unsigned int)d : va_arg (ap, unsigned int);
b40343bc 77 for (i = nextpow (u, 10), s = str; i > 0; i--, s++) {
5f83300c
LM
78 str[i - 1] = '0' + (u % 10);
79 u /= 10;
80 }
81 str = s;
82 break;
83 case 'p': /* pointer */
5f83300c
LM
84 *str++ = '0';
85 *str++ = 'x';
b40343bc
LM
86 w = '0';
87 sz = sizeof (void *) * 2;
88 p = va_arg (ap, void *);
89 /* fall through */
90 case 'x': /* integer hexa */
91 if (!p) {
92 u = va_arg (ap, unsigned int);
93 p = (void *)u;
94 if (sz == 0) {
95 sz = nextpow (u, 16);
96 }
97 }
98 for (i = sz, t = 1; i > 0; i--) {
5f83300c 99 char x = (char)(((uintptr_t)p >> (i * 4 - 4)) & 0xf);
b40343bc
LM
100 if ((t == 1) && (x == 0)) {
101 *str++ = w;
102 } else {
103 *str++ = (x > 9) ? 'a' + x - 10 : '0' + x;
104 t = 0;
105 }
5f83300c
LM
106 }
107 break;
108 case 's': /* string */
109 s = va_arg (ap, char *);
110 while (s && *s)
111 *str++ = *s++;
112 break;
113 default:
114 *str++ = '?';
115 }
116 }
117 }
118 va_end (ap);
119
120 /* output string */
121 size_t n = str - buffer;
122 if (n < sizeof (buffer) - 1) {
123 fwrite (buffer, n, 1, fid);
124 return n;
125 }
126 return 0;
127}
128
b40343bc 129/* vim: set ts=4 sw=4 et: */