1 : /* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */
2 :
3 : #ifndef USTR_FMT_H
4 : #error " Include ustr-fmt.h before this file."
5 : #endif
6 :
7 : #if USTR_CONF_HAVE_VA_COPY
8 :
9 : # if USTR_CONF_HAVE_RETARDED_VSNPRINTF
10 : USTR_CONF_i_PROTO
11 : int ustr__retard_vfmt_ret(const char *fmt, va_list ap)
12 : {
13 : size_t sz = USTR__RETARDED_SNPRINTF_MIN;
14 : char *ptr = 0;
15 : int ret = -1;
16 : va_list nap;
17 :
18 : if (USTR_CONF_VSNPRINTF_BEG != vsnprintf)
19 : return (-1);
20 :
21 : if (!(ptr = USTR_CONF_MALLOC(sz)))
22 : return (-1);
23 :
24 : USTR__VA_COPY(nap, ap);
25 : while ((ret = vsnprintf(ptr, sz, fmt, nap)) == -1)
26 : {
27 : char *tmp = 0;
28 :
29 : va_end(nap);
30 :
31 : sz *= 2;
32 :
33 : if ((sz >= USTR__RETARDED_SNPRINTF_MAX) ||
34 : !(tmp = USTR_CONF_REALLOC(ptr, sz)))
35 : {
36 : USTR_CONF_FREE(ptr);
37 : return (-1);
38 : }
39 :
40 : USTR__VA_COPY(nap, ap);
41 : }
42 : va_end(nap);
43 :
44 : /* We could probably do the memcpy optimization here, with a bit of jumping
45 : * through hoops (and a different interface ... but I prefer the single code
46 : * path to sane platforms that I'm likely to be testing on. */
47 : USTR_CONF_FREE(ptr);
48 :
49 : return (ret);
50 : }
51 : # endif
52 :
53 : USTR_CONF_i_PROTO
54 : int ustrp__add_vfmt_lim(struct Ustr_pool *p, struct Ustr **ps1, size_t lim,
55 : const char *fmt, va_list ap)
56 32 : { /* you might think we want to just use ustr_wstr()
57 : * if ustr_size() - ustr_len() > 0 ... however the problem there is about
58 : * screwing up the data when we fail. Which we just don't do */
59 32 : char *tmp = 0;
60 32 : size_t os1len = 0;
61 : va_list nap;
62 32 : int rc = -1;
63 : char buf[USTR__SNPRINTF_LOCAL];
64 :
65 16 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
66 :
67 32 : USTR__VA_COPY(nap, ap);
68 32 : rc = USTR_CONF_VSNPRINTF_BEG(buf, sizeof(buf), fmt, nap);
69 32 : va_end(nap);
70 :
71 32 : if ((rc == -1) && ((rc = ustr__retard_vfmt_ret(fmt, ap)) == -1))
72 4 : return (USTR_FALSE);
73 :
74 28 : if (lim && ((size_t)rc > lim))
75 8 : rc = lim;
76 :
77 28 : if ((size_t)rc < sizeof(buf)) /* everything is done */
78 16 : return (ustrp__add_buf(p, ps1, buf, rc));
79 :
80 12 : os1len = ustr_len(*ps1);
81 12 : if (!ustrp__add_undef(p, ps1, rc))
82 4 : return (USTR_FALSE);
83 :
84 8 : tmp = ustr_wstr(*ps1) + os1len;
85 :
86 8 : USTR_CONF_VSNPRINTF_END(tmp, rc + 1, fmt, ap);
87 :
88 4 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
89 :
90 8 : return (USTR_TRUE);
91 : }
92 : USTR_CONF_I_PROTO
93 : int ustr_add_vfmt_lim(struct Ustr **ps1, size_t lim, const char *fmt,va_list ap)
94 20 : { return (ustrp__add_vfmt_lim(0, ps1, lim, fmt, ap)); }
95 : USTR_CONF_I_PROTO int ustrp_add_vfmt_lim(struct Ustr_pool *p,struct Ustrp **ps1,
96 : size_t lim, const char *fmt,va_list ap)
97 12 : {
98 12 : struct Ustr *tmp = &(*ps1)->s;
99 12 : int ret = ustrp__add_vfmt_lim(p, &tmp, lim, fmt, ap);
100 12 : *ps1 = USTRP(tmp);
101 12 : return (ret);
102 : }
103 :
104 : USTR_CONF_I_PROTO
105 : int ustr_add_fmt_lim(struct Ustr **ps1, size_t lim, const char *fmt, ...)
106 4 : {
107 : va_list ap;
108 4 : int ret = -1;
109 :
110 4 : va_start(ap, fmt);
111 4 : ret = ustr_add_vfmt_lim(ps1, lim, fmt, ap);
112 4 : va_end(ap);
113 :
114 4 : return (ret);
115 : }
116 :
117 : USTR_CONF_I_PROTO
118 : int ustrp_add_fmt_lim(struct Ustr_pool *p, struct Ustrp **ps1, size_t lim,
119 : const char *fmt, ...)
120 4 : {
121 : va_list ap;
122 4 : int ret = -1;
123 :
124 4 : va_start(ap, fmt);
125 4 : ret = ustrp_add_vfmt_lim(p, ps1, lim, fmt, ap);
126 4 : va_end(ap);
127 :
128 4 : return (ret);
129 : }
130 :
131 : USTR_CONF_I_PROTO int ustr_add_vfmt(struct Ustr **ps1,const char*fmt,va_list ap)
132 16 : { return (ustr_add_vfmt_lim(ps1, 0, fmt, ap)); }
133 :
134 : USTR_CONF_I_PROTO int ustrp_add_vfmt(struct Ustr_pool *p, struct Ustrp **ps1,
135 : const char *fmt, va_list ap)
136 8 : { return (ustrp_add_vfmt_lim(p, ps1, 0, fmt, ap)); }
137 :
138 : USTR_CONF_I_PROTO int ustr_add_fmt(struct Ustr **ps1, const char *fmt, ...)
139 16 : {
140 : va_list ap;
141 16 : int ret = -1;
142 :
143 16 : va_start(ap, fmt);
144 16 : ret = ustr_add_vfmt(ps1, fmt, ap);
145 16 : va_end(ap);
146 :
147 16 : return (ret);
148 : }
149 :
150 : USTR_CONF_I_PROTO
151 : int ustrp_add_fmt(struct Ustr_pool *p, struct Ustrp **ps1, const char *fmt, ...)
152 8 : {
153 : va_list ap;
154 8 : int ret = -1;
155 :
156 8 : va_start(ap, fmt);
157 8 : ret = ustrp_add_vfmt(p, ps1, fmt, ap);
158 8 : va_end(ap);
159 :
160 8 : return (ret);
161 : }
162 :
163 : USTR_CONF_i_PROTO
164 : struct Ustr *ustrp__dupx_vfmt_lim(struct Ustr_pool *p, size_t sz, size_t rbytes,
165 : int exact, int emem, size_t lim,
166 : const char *fmt, va_list ap)
167 60 : { /* NOTE: Copy and pasted so we don't have to allocate twice, just to get the
168 : * options */
169 60 : struct Ustr *ret = USTR_NULL;
170 : va_list nap;
171 60 : int rc = -1;
172 : char buf[USTR__SNPRINTF_LOCAL];
173 :
174 60 : USTR__VA_COPY(nap, ap);
175 60 : rc = USTR_CONF_VSNPRINTF_BEG(buf, sizeof(buf), fmt, nap);
176 60 : va_end(nap);
177 :
178 60 : if ((rc == -1) && ((rc = ustr__retard_vfmt_ret(fmt, ap)) == -1))
179 4 : return (USTR_FALSE);
180 :
181 56 : if (lim && ((size_t)rc > lim))
182 20 : rc = lim;
183 :
184 56 : if ((size_t)rc < sizeof(buf)) /* everything is done */
185 40 : return (ustrp__dupx_buf(p, sz, rbytes, exact, emem, buf, rc));
186 :
187 16 : if (!(ret = ustrp__dupx_undef(p, sz, rbytes, exact, emem, rc)))
188 4 : return (USTR_FALSE);
189 :
190 12 : USTR_CONF_VSNPRINTF_END(ustr_wstr(ret), rc + 1, fmt, ap);
191 :
192 6 : USTR_ASSERT(ustrp__assert_valid(!!p, ret));
193 :
194 12 : return (ret);
195 : }
196 :
197 : USTR_CONF_I_PROTO
198 : struct Ustr *ustr_dupx_vfmt_lim(size_t sz, size_t rbytes, int exact,
199 : int emem,size_t lim,const char *fmt, va_list ap)
200 32 : { return (ustrp__dupx_vfmt_lim(0, sz, rbytes, exact, emem, lim, fmt, ap)); }
201 : USTR_CONF_I_PROTO
202 : struct Ustrp *ustrp_dupx_vfmt_lim(struct Ustr_pool *p, size_t sz, size_t rb,
203 : int exact, int emem, size_t lim,
204 : const char *fmt, va_list ap)
205 28 : { return (USTRP(ustrp__dupx_vfmt_lim(p, sz, rb, exact, emem, lim, fmt, ap))); }
206 :
207 : USTR_CONF_I_PROTO
208 : struct Ustr *ustr_dupx_fmt_lim(size_t sz, size_t rbytes, int exact,
209 : int emem, size_t lim, const char *fmt, ...)
210 4 : {
211 : va_list ap;
212 4 : struct Ustr *ret = USTR_NULL;
213 :
214 4 : va_start(ap, fmt);
215 4 : ret = ustr_dupx_vfmt_lim(sz, rbytes, exact, emem, lim, fmt, ap);
216 4 : va_end(ap);
217 :
218 4 : return (ret);
219 : }
220 :
221 : USTR_CONF_I_PROTO
222 : struct Ustrp *ustrp_dupx_fmt_lim(struct Ustr_pool *p, size_t sz, size_t rbytes,
223 : int exact, int emem, size_t lim,
224 : const char *fmt, ...)
225 :
226 4 : {
227 : va_list ap;
228 4 : struct Ustrp *ret = USTRP_NULL;
229 :
230 4 : va_start(ap, fmt);
231 4 : ret = ustrp_dupx_vfmt_lim(p, sz, rbytes, exact, emem, lim, fmt, ap);
232 4 : va_end(ap);
233 :
234 4 : return (ret);
235 : }
236 :
237 : USTR_CONF_I_PROTO
238 : struct Ustr *ustr_dupx_vfmt(size_t sz, size_t rbytes, int exact,
239 : int emem, const char *fmt, va_list ap)
240 24 : { return (ustr_dupx_vfmt_lim(sz, rbytes, exact, emem, 0, fmt, ap)); }
241 :
242 : USTR_CONF_I_PROTO
243 : struct Ustrp *ustrp_dupx_vfmt(struct Ustr_pool *p, size_t sz, size_t rbytes,
244 : int exact, int emem, const char *fmt, va_list ap)
245 20 : { return (ustrp_dupx_vfmt_lim(p, sz, rbytes, exact, emem, 0, fmt, ap)); }
246 :
247 : USTR_CONF_I_PROTO struct Ustr *ustr_dupx_fmt(size_t sz, size_t rbytes,int exact,
248 : int emem, const char *fmt, ...)
249 4 : {
250 : va_list ap;
251 4 : struct Ustr *ret = USTR_NULL;
252 :
253 4 : va_start(ap, fmt);
254 4 : ret = ustr_dupx_vfmt(sz, rbytes, exact, emem, fmt, ap);
255 4 : va_end(ap);
256 :
257 4 : return (ret);
258 : }
259 :
260 : USTR_CONF_I_PROTO
261 : struct Ustrp *ustrp_dupx_fmt(struct Ustr_pool *p, size_t sz, size_t rbytes,
262 : int exact, int emem, const char *fmt, ...)
263 :
264 4 : {
265 : va_list ap;
266 4 : struct Ustrp *ret = USTRP_NULL;
267 :
268 4 : va_start(ap, fmt);
269 4 : ret = ustrp_dupx_vfmt(p, sz, rbytes, exact, emem, fmt, ap);
270 4 : va_end(ap);
271 :
272 4 : return (ret);
273 : }
274 :
275 : USTR_CONF_I_PROTO
276 : struct Ustr *ustr_dup_vfmt_lim(size_t lim, const char *fmt, va_list ap)
277 4 : { return (ustr_dupx_vfmt_lim(USTR__DUPX_DEF, lim, fmt, ap)); }
278 :
279 : USTR_CONF_I_PROTO
280 : struct Ustrp *ustrp_dup_vfmt_lim(struct Ustr_pool *p, size_t lim,
281 : const char *fmt, va_list ap)
282 10 : { return (ustrp_dupx_vfmt_lim(p, USTR__DUPX_DEF, lim, fmt, ap)); }
283 :
284 : USTR_CONF_I_PROTO
285 : struct Ustr *ustr_dup_fmt_lim(size_t lim, const char *fmt, ...)
286 4 : {
287 : va_list ap;
288 4 : struct Ustr *ret = USTR_NULL;
289 :
290 4 : va_start(ap, fmt);
291 4 : ret = ustr_dup_vfmt_lim(lim, fmt, ap);
292 4 : va_end(ap);
293 :
294 4 : return (ret);
295 : }
296 :
297 : USTR_CONF_I_PROTO
298 : struct Ustrp *ustrp_dup_fmt_lim(struct Ustr_pool *p, size_t lim,
299 : const char *fmt, ...)
300 :
301 8 : {
302 : va_list ap;
303 8 : struct Ustrp *ret = USTRP_NULL;
304 :
305 8 : va_start(ap, fmt);
306 8 : ret = ustrp_dup_vfmt_lim(p, lim, fmt, ap);
307 8 : va_end(ap);
308 :
309 8 : return (ret);
310 : }
311 :
312 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_vfmt(const char *fmt, va_list ap)
313 16 : { return (ustr_dupx_vfmt(USTR__DUPX_DEF, fmt, ap)); }
314 :
315 : USTR_CONF_I_PROTO
316 : struct Ustrp *ustrp_dup_vfmt(struct Ustr_pool *p, const char *fmt, va_list ap)
317 12 : { return (ustrp_dupx_vfmt(p, USTR__DUPX_DEF, fmt, ap)); }
318 :
319 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_fmt(const char *fmt, ...)
320 16 : {
321 : va_list ap;
322 16 : struct Ustr *ret = USTR_NULL;
323 :
324 16 : va_start(ap, fmt);
325 16 : ret = ustr_dup_vfmt(fmt, ap);
326 16 : va_end(ap);
327 :
328 16 : return (ret);
329 : }
330 :
331 : USTR_CONF_I_PROTO
332 : struct Ustrp *ustrp_dup_fmt(struct Ustr_pool *p, const char *fmt, ...)
333 12 : {
334 : va_list ap;
335 12 : struct Ustrp *ret = USTRP_NULL;
336 :
337 12 : va_start(ap, fmt);
338 12 : ret = ustrp_dup_vfmt(p, fmt, ap);
339 12 : va_end(ap);
340 :
341 12 : return (ret);
342 : }
343 : #endif
344 :
|