src/ucx/printf.c

changeset 579
e10457d74fe1
parent 490
d218607f5a7e
equal deleted inserted replaced
578:eb48f716b31c 579:e10457d74fe1
32 #include <string.h> 32 #include <string.h>
33 33
34 #ifndef CX_PRINTF_SBO_SIZE 34 #ifndef CX_PRINTF_SBO_SIZE
35 #define CX_PRINTF_SBO_SIZE 512 35 #define CX_PRINTF_SBO_SIZE 512
36 #endif 36 #endif
37 const unsigned cx_printf_sbo_size = CX_PRINTF_SBO_SIZE;
37 38
38 int cx_fprintf( 39 int cx_fprintf(
39 void *stream, 40 void *stream,
40 cx_write_func wfc, 41 cx_write_func wfc,
41 char const *fmt, 42 const char *fmt,
42 ... 43 ...
43 ) { 44 ) {
44 int ret; 45 int ret;
45 va_list ap; 46 va_list ap;
46 va_start(ap, fmt); 47 va_start(ap, fmt);
50 } 51 }
51 52
52 int cx_vfprintf( 53 int cx_vfprintf(
53 void *stream, 54 void *stream,
54 cx_write_func wfc, 55 cx_write_func wfc,
55 char const *fmt, 56 const char *fmt,
56 va_list ap 57 va_list ap
57 ) { 58 ) {
58 char buf[CX_PRINTF_SBO_SIZE]; 59 char buf[CX_PRINTF_SBO_SIZE];
59 va_list ap2; 60 va_list ap2;
60 va_copy(ap2, ap); 61 va_copy(ap2, ap);
61 int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap); 62 int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap);
62 if (ret < 0) { 63 if (ret < 0) {
64 va_end(ap2);
63 return ret; 65 return ret;
64 } else if (ret < CX_PRINTF_SBO_SIZE) { 66 } else if (ret < CX_PRINTF_SBO_SIZE) {
67 va_end(ap2);
65 return (int) wfc(buf, 1, ret, stream); 68 return (int) wfc(buf, 1, ret, stream);
66 } else { 69 } else {
67 int len = ret + 1; 70 int len = ret + 1;
68 char *newbuf = malloc(len); 71 char *newbuf = malloc(len);
69 if (!newbuf) { 72 if (!newbuf) { // LCOV_EXCL_START
73 va_end(ap2);
70 return -1; 74 return -1;
71 } 75 } // LCOV_EXCL_STOP
72 76
73 ret = vsnprintf(newbuf, len, fmt, ap2); 77 ret = vsnprintf(newbuf, len, fmt, ap2);
78 va_end(ap2);
74 if (ret > 0) { 79 if (ret > 0) {
75 ret = (int) wfc(newbuf, 1, ret, stream); 80 ret = (int) wfc(newbuf, 1, ret, stream);
76 } 81 }
77 free(newbuf); 82 free(newbuf);
78 } 83 }
79 return ret; 84 return ret;
80 } 85 }
81 86
82 cxmutstr cx_asprintf_a( 87 cxmutstr cx_asprintf_a(
83 CxAllocator const *allocator, 88 const CxAllocator *allocator,
84 char const *fmt, 89 const char *fmt,
85 ... 90 ...
86 ) { 91 ) {
87 va_list ap; 92 va_list ap;
88 cxmutstr ret;
89 va_start(ap, fmt); 93 va_start(ap, fmt);
90 ret = cx_vasprintf_a(allocator, fmt, ap); 94 cxmutstr ret = cx_vasprintf_a(allocator, fmt, ap);
91 va_end(ap); 95 va_end(ap);
92 return ret; 96 return ret;
93 } 97 }
94 98
95 cxmutstr cx_vasprintf_a( 99 cxmutstr cx_vasprintf_a(
96 CxAllocator const *a, 100 const CxAllocator *a,
97 char const *fmt, 101 const char *fmt,
98 va_list ap 102 va_list ap
99 ) { 103 ) {
100 cxmutstr s; 104 cxmutstr s;
101 s.ptr = NULL; 105 s.ptr = NULL;
102 s.length = 0; 106 s.length = 0;
103 char buf[CX_PRINTF_SBO_SIZE]; 107 char buf[CX_PRINTF_SBO_SIZE];
104 va_list ap2; 108 va_list ap2;
105 va_copy(ap2, ap); 109 va_copy(ap2, ap);
106 int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap); 110 int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap);
107 if (ret > 0 && ret < CX_PRINTF_SBO_SIZE) { 111 if (ret >= 0 && ret < CX_PRINTF_SBO_SIZE) {
108 s.ptr = cxMalloc(a, ret + 1); 112 s.ptr = cxMalloc(a, ret + 1);
109 if (s.ptr) { 113 if (s.ptr) {
110 s.length = (size_t) ret; 114 s.length = (size_t) ret;
111 memcpy(s.ptr, buf, ret); 115 memcpy(s.ptr, buf, ret);
112 s.ptr[s.length] = '\0'; 116 s.ptr[s.length] = '\0';
122 } else { 126 } else {
123 s.length = (size_t) ret; 127 s.length = (size_t) ret;
124 } 128 }
125 } 129 }
126 } 130 }
131 va_end(ap2);
127 return s; 132 return s;
128 } 133 }
129 134
135 int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, ... ) {
136 va_list ap;
137 va_start(ap, fmt);
138 int ret = cx_vsprintf_a(alloc, str, len, fmt, ap);
139 va_end(ap);
140 return ret;
141 }
142
143 int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, va_list ap) {
144 va_list ap2;
145 va_copy(ap2, ap);
146 int ret = vsnprintf(*str, *len, fmt, ap);
147 if ((unsigned) ret >= *len) {
148 unsigned newlen = ret + 1;
149 char *ptr = cxRealloc(alloc, *str, newlen);
150 if (ptr) {
151 int newret = vsnprintf(ptr, newlen, fmt, ap2);
152 if (newret < 0) {
153 cxFree(alloc, ptr);
154 } else {
155 *len = newlen;
156 *str = ptr;
157 ret = newret;
158 }
159 }
160 }
161 va_end(ap2);
162 return ret;
163 }
164
165 int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, ... ) {
166 va_list ap;
167 va_start(ap, fmt);
168 int ret = cx_vsprintf_sa(alloc, buf, len, str, fmt, ap);
169 va_end(ap);
170 return ret;
171 }
172
173 int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, va_list ap) {
174 va_list ap2;
175 va_copy(ap2, ap);
176 int ret = vsnprintf(buf, *len, fmt, ap);
177 *str = buf;
178 if ((unsigned) ret >= *len) {
179 unsigned newlen = ret + 1;
180 char *ptr = cxMalloc(alloc, newlen);
181 if (ptr) {
182 int newret = vsnprintf(ptr, newlen, fmt, ap2);
183 if (newret < 0) {
184 cxFree(alloc, ptr);
185 } else {
186 *len = newlen;
187 *str = ptr;
188 ret = newret;
189 }
190 }
191 }
192 va_end(ap2);
193 return ret;
194 }

mercurial