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 } |