1 : /* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */
2 :
3 : #ifndef USTR_SC_H
4 : #error " Include ustr-sc.h before this file."
5 : #endif
6 :
7 : USTR_CONF_i_PROTO
8 : void ustrp__sc_free_shared(struct Ustr_pool *p, struct Ustr **ps1)
9 8 : {
10 4 : USTR_ASSERT(ps1);
11 :
12 8 : if (!*ps1)
13 4 : return;
14 :
15 3 : USTR_ASSERT(ustr_shared(*ps1));
16 :
17 4 : ustr_setf_owner(*ps1);
18 4 : ustrp__sc_free(p, ps1);
19 : }
20 : USTR_CONF_I_PROTO void ustr_sc_free_shared(struct Ustr **ps1)
21 4 : { ustrp__sc_free_shared(0, ps1); }
22 : USTR_CONF_I_PROTO
23 : void ustrp_sc_free_shared(struct Ustr_pool *p, struct Ustrp **ps1)
24 4 : {
25 4 : struct Ustr *tmp = &(*ps1)->s;
26 4 : ustrp__sc_free_shared(p, &tmp);
27 4 : *ps1 = USTRP(tmp);
28 4 : }
29 :
30 : USTR_CONF_i_PROTO
31 : struct Ustr *ustrp__sc_dupx(struct Ustr_pool *p,
32 : size_t sz, size_t rbytes, int exact, int emem,
33 : struct Ustr **ps1)
34 16 : {
35 16 : struct Ustr *ret = ustrp__dupx(p, sz, rbytes, exact, emem, *ps1);
36 16 : struct Ustr *tmp = USTR_NULL;
37 :
38 16 : if (!ret)
39 8 : return (USTR_NULL);
40 :
41 28 : if (!ustr__dupx_cmp_eq(sz, rbytes, exact, emem, USTR__DUPX_FROM(*ps1)))
42 4 : return (ret); /* different config. so just return */
43 :
44 : /* swap, we only _need_ to do this when ret != *ps1 ... but it doesn't matter
45 : * if we always do it. */
46 4 : tmp = *ps1;
47 4 : *ps1 = ret;
48 4 : ret = tmp;
49 :
50 4 : return (ret);
51 : }
52 : USTR_CONF_I_PROTO
53 : struct Ustr *ustr_sc_dupx(size_t sz, size_t rbytes, int exact, int emem,
54 : struct Ustr **ps1)
55 8 : { return (ustrp__sc_dupx(0, sz, rbytes, exact, emem, ps1)); }
56 : USTR_CONF_I_PROTO
57 : struct Ustrp *ustrp_sc_dupx(struct Ustr_pool *p, size_t sz, size_t rbytes,
58 : int exact, int emem, struct Ustrp **ps1)
59 8 : {
60 8 : struct Ustr *tmp = &(*ps1)->s;
61 8 : struct Ustr *ret = ustrp__sc_dupx(p, sz, rbytes, exact, emem, &tmp);
62 8 : *ps1 = USTRP(tmp);
63 8 : return (USTRP(ret));
64 : }
65 :
66 : USTR_CONF_i_PROTO
67 : struct Ustr *ustrp__sc_dup(struct Ustr_pool *p, struct Ustr **ps1)
68 16 : {
69 16 : struct Ustr *ret = ustrp__dup(p, *ps1);
70 16 : struct Ustr *tmp = USTR_NULL;
71 :
72 16 : if (!ret)
73 4 : return (USTR_NULL);
74 :
75 : /* swap, we only _need_ to do this when ret != *ps1 ... but it doesn't matter
76 : * if we always do it. */
77 12 : tmp = *ps1;
78 12 : *ps1 = ret;
79 12 : ret = tmp;
80 :
81 12 : return (ret);
82 : }
83 : USTR_CONF_I_PROTO struct Ustr *ustr_sc_dup(struct Ustr **ps1)
84 8 : { return (ustrp__sc_dup(0, ps1)); }
85 : USTR_CONF_I_PROTO
86 : struct Ustrp *ustrp_sc_dup(struct Ustr_pool *p, struct Ustrp **ps1)
87 8 : {
88 8 : struct Ustr *tmp = &(*ps1)->s;
89 8 : struct Ustr *ret = ustrp__sc_dup(p, &tmp);
90 8 : *ps1 = USTRP(tmp);
91 8 : return (USTRP(ret));
92 : }
93 :
94 : USTR_CONF_i_PROTO void ustr__reverse(char *ptr, size_t pos, size_t len)
95 472 : {
96 472 : size_t clen = len;
97 :
98 472 : --pos;
99 1768 : while (len > (clen / 2))
100 : {
101 824 : const size_t boff = pos + (clen - len);
102 824 : const size_t eoff = pos + (len - 1);
103 824 : char tmp = ptr[boff];
104 :
105 824 : ptr[boff] = ptr[eoff];
106 824 : ptr[eoff] = tmp;
107 :
108 824 : --len;
109 : }
110 472 : }
111 :
112 : USTR_CONF_i_PROTO int ustrp__sc_reverse(struct Ustr_pool *p, struct Ustr **ps1)
113 104 : {
114 104 : if (!ustrp__sc_ensure_owner(p, ps1))
115 4 : return (USTR_FALSE);
116 :
117 125 : ustr__reverse(ustr_wstr(*ps1), 1, ustr_len(*ps1));
118 :
119 100 : return (USTR_TRUE);
120 : }
121 : USTR_CONF_I_PROTO int ustr_sc_reverse(struct Ustr **ps1)
122 56 : { return (ustrp__sc_reverse(0, ps1)); }
123 : USTR_CONF_I_PROTO int ustrp_sc_reverse(struct Ustr_pool *p, struct Ustrp **ps1)
124 48 : {
125 48 : struct Ustr *tmp = &(*ps1)->s;
126 48 : int ret = ustrp__sc_reverse(p, &tmp);
127 48 : *ps1 = USTRP(tmp);
128 48 : return (ret);
129 : }
130 :
131 : #ifdef USTR_UTF8_H
132 : USTR_CONF_i_PROTO
133 : int ustrp__sc_utf8_reverse(struct Ustr_pool *p, struct Ustr **ps1)
134 24 : { /* UTF-8 reversing is like word order reversing. The simple way is to reverse
135 : * each "character", in place, and then reverse the entire string. */
136 : char *ptr;
137 : const unsigned char *beg;
138 : const unsigned char *scan;
139 :
140 12 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
141 :
142 24 : if (!(ptr = ustrp__sc_wstr(p, ps1)))
143 4 : return (USTR_FALSE);
144 :
145 20 : scan = beg = (const unsigned char *)ptr;
146 392 : while (*scan)
147 : {
148 352 : const unsigned char *prev = scan;
149 :
150 264 : USTR_ASSERT(ustr_len(*ps1) > (size_t)(scan - beg));
151 :
152 352 : scan = ustr__utf8_next(scan);
153 352 : ustr__reverse(ptr, 1 + (prev - beg), (scan - prev));
154 : }
155 :
156 20 : ustr__reverse(ptr, 1, (scan - beg));
157 :
158 20 : return (USTR_TRUE);
159 : }
160 : USTR_CONF_I_PROTO int ustr_sc_utf8_reverse(struct Ustr **ps1)
161 12 : { return (ustrp__sc_utf8_reverse(0, ps1)); }
162 : USTR_CONF_I_PROTO
163 : int ustrp_sc_utf8_reverse(struct Ustr_pool *p, struct Ustrp **ps1)
164 12 : {
165 12 : struct Ustr *tmp = &(*ps1)->s;
166 12 : int ret = ustrp__sc_utf8_reverse(p, &tmp);
167 12 : *ps1 = USTRP(tmp);
168 12 : return (ret);
169 : }
170 : #endif
171 :
172 : USTR_CONF_i_PROTO int ustrp__sc_tolower(struct Ustr_pool *p, struct Ustr **ps1)
173 20 : {
174 : size_t clen;
175 : size_t len;
176 : char *ptr;
177 :
178 20 : if (!(ptr = ustrp__sc_wstr(p, ps1)))
179 4 : return (USTR_FALSE);
180 :
181 20 : clen = len = ustr_len(*ps1);
182 352 : while (len)
183 : {
184 320 : if ((*ptr >= 0x41) && (*ptr <= 0x5a))
185 180 : *ptr ^= 0x20;
186 320 : ++ptr;
187 320 : --len;
188 : }
189 :
190 16 : return (USTR_TRUE);
191 : }
192 : USTR_CONF_I_PROTO int ustr_sc_tolower(struct Ustr **ps1)
193 16 : { return (ustrp__sc_tolower(0, ps1)); }
194 : USTR_CONF_I_PROTO int ustrp_sc_tolower(struct Ustr_pool *p, struct Ustrp **ps1)
195 4 : {
196 4 : struct Ustr *tmp = &(*ps1)->s;
197 4 : int ret = ustrp__sc_tolower(p, &tmp);
198 4 : *ps1 = USTRP(tmp);
199 4 : return (ret);
200 : }
201 :
202 : USTR_CONF_i_PROTO int ustrp__sc_toupper(struct Ustr_pool *p, struct Ustr **ps1)
203 20 : {
204 : size_t clen;
205 : size_t len;
206 : char *ptr;
207 :
208 20 : if (!(ptr = ustrp__sc_wstr(p, ps1)))
209 4 : return (USTR_FALSE);
210 :
211 20 : clen = len = ustr_len(*ps1);
212 352 : while (len)
213 : {
214 320 : if ((*ptr >= 0x61) && (*ptr <= 0x7a))
215 180 : *ptr ^= 0x20;
216 320 : ++ptr;
217 320 : --len;
218 : }
219 :
220 16 : return (USTR_TRUE);
221 : }
222 : USTR_CONF_I_PROTO int ustr_sc_toupper(struct Ustr **ps1)
223 16 : { return (ustrp__sc_toupper(0, ps1)); }
224 : USTR_CONF_I_PROTO int ustrp_sc_toupper(struct Ustr_pool *p, struct Ustrp **ps1)
225 4 : {
226 4 : struct Ustr *tmp = &(*ps1)->s;
227 4 : int ret = ustrp__sc_toupper(p, &tmp);
228 4 : *ps1 = USTRP(tmp);
229 4 : return (ret);
230 : }
231 :
232 : USTR_CONF_i_PROTO
233 : char *ustrp__sc_export_subustr(struct Ustr_pool *p,
234 : const struct Ustr *s1, size_t pos,size_t len,
235 : void *(*my_alloc)(size_t))
236 556 : {
237 556 : char *ret = 0;
238 :
239 272 : USTR_ASSERT(my_alloc || p);
240 :
241 556 : if (!ustrp__assert_valid_subustr(!!p, s1, pos, len))
242 : {
243 12 : errno = USTR__EINVAL;
244 12 : return (ret);
245 : }
246 544 : --pos;
247 :
248 544 : if (my_alloc) /* Alloc ustrp_*() to use normal export too */
249 368 : ret = (*my_alloc)(len + 1);
250 : else
251 176 : ret = p->pool_sys_malloc(p, len + 1);
252 :
253 544 : if (!ret)
254 : {
255 16 : errno = ENOMEM;
256 16 : return (ret);
257 : }
258 :
259 528 : memcpy(ret, ustr_cstr(s1) + pos, len);
260 528 : ret[len] = 0;
261 :
262 528 : return (ret);
263 : }
264 :
265 : USTR_CONF_I_PROTO
266 : char *ustr_sc_export_subustr(const struct Ustr *s1, size_t pos, size_t len,
267 : void *(*my_alloc)(size_t))
268 188 : {
269 92 : USTR_ASSERT(my_alloc);
270 188 : return (ustrp__sc_export_subustr(0, s1, pos, len, my_alloc));
271 : }
272 : USTR_CONF_I_PROTO
273 : char *ustrp_sc_export_subustrp(struct Ustr_pool *p,
274 : const struct Ustrp *s1, size_t pos,size_t len,
275 : void *(*my_alloc)(size_t))
276 368 : { return (ustrp__sc_export_subustr(p, &s1->s, pos, len, my_alloc)); }
277 :
278 : USTR_CONF_i_PROTO
279 : int ustrp__sc_ltrim_chrs(struct Ustr_pool *p, struct Ustr **ps1,
280 : const char *chrs, size_t len)
281 40 : {
282 40 : return (ustrp__del_subustr(p, ps1, 1, ustr_spn_chrs_fwd(*ps1, 0, chrs, len)));
283 : }
284 : USTR_CONF_I_PROTO
285 : int ustr_sc_ltrim_chrs(struct Ustr **ps1, const char *chrs, size_t len)
286 20 : { return (ustrp__sc_ltrim_chrs(0, ps1, chrs, len)); }
287 : USTR_CONF_I_PROTO
288 : int ustrp_sc_ltrim_chrs(struct Ustr_pool *p, struct Ustrp **ps1,
289 : const char *chrs, size_t len)
290 20 : {
291 20 : struct Ustr *tmp = &(*ps1)->s;
292 20 : int ret = ustrp__sc_ltrim_chrs(p, &tmp, chrs, len);
293 20 : *ps1 = USTRP(tmp);
294 20 : return (ret);
295 : }
296 :
297 : USTR_CONF_i_PROTO
298 : int ustrp__sc_rtrim_chrs(struct Ustr_pool *p, struct Ustr **ps1,
299 : const char *chrs, size_t len)
300 40 : {
301 40 : return (ustrp__del(p, ps1, ustr_spn_chrs_rev(*ps1, 0, chrs, len)));
302 : }
303 : USTR_CONF_I_PROTO
304 : int ustr_sc_rtrim_chrs(struct Ustr **ps1, const char *chrs, size_t len)
305 20 : { return (ustrp__sc_rtrim_chrs(0, ps1, chrs, len)); }
306 : USTR_CONF_I_PROTO
307 : int ustrp_sc_rtrim_chrs(struct Ustr_pool *p, struct Ustrp **ps1,
308 : const char *chrs, size_t len)
309 20 : {
310 20 : struct Ustr *tmp = &(*ps1)->s;
311 20 : int ret = ustrp__sc_rtrim_chrs(p, &tmp, chrs, len);
312 20 : *ps1 = USTRP(tmp);
313 20 : return (ret);
314 : }
315 :
316 : USTR_CONF_i_PROTO
317 : int ustrp__sc_trim_chrs(struct Ustr_pool *p, struct Ustr **ps1,
318 : const char *chrs, size_t len)
319 48 : {
320 48 : size_t ltrim = ustr_spn_chrs_fwd(*ps1, 0, chrs, len);
321 48 : size_t rtrim = 0;
322 48 : size_t clen = ustr_len(*ps1);
323 48 : size_t nlen = 0;
324 : char *ptr;
325 :
326 24 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
327 :
328 48 : if (ltrim == clen)
329 12 : return (ustrp__del(p, ps1, ltrim));
330 :
331 36 : rtrim = ustr_spn_chrs_rev(*ps1, 0, chrs, len);
332 :
333 36 : if (!ltrim && !rtrim)
334 8 : return (USTR_TRUE); /* minor speed hack */
335 :
336 28 : nlen = clen - (ltrim + rtrim);
337 28 : if (!ustr_owner(*ps1))
338 : {
339 12 : struct Ustr *ret = ustrp__dup_subustr(p, *ps1, 1 + ltrim, nlen);
340 :
341 12 : if (ret)
342 12 : ustrp__sc_free2(p, ps1, ret);
343 :
344 12 : return (!!ret);
345 : }
346 :
347 16 : ptr = ustr_wstr(*ps1);
348 16 : memmove(ptr, ptr + ltrim, nlen);
349 :
350 16 : return (ustrp__del(p, ps1, ltrim + rtrim));
351 : }
352 : USTR_CONF_I_PROTO
353 : int ustr_sc_trim_chrs(struct Ustr **ps1, const char *chrs, size_t len)
354 20 : { return (ustrp__sc_trim_chrs(0, ps1, chrs, len)); }
355 : USTR_CONF_I_PROTO
356 : int ustrp_sc_trim_chrs(struct Ustr_pool *p, struct Ustrp **ps1,
357 : const char *chrs, size_t len)
358 28 : {
359 28 : struct Ustr *tmp = &(*ps1)->s;
360 28 : int ret = ustrp__sc_trim_chrs(p, &tmp, chrs, len);
361 28 : *ps1 = USTRP(tmp);
362 28 : return (ret);
363 : }
364 :
365 : USTR_CONF_i_PROTO
366 : struct Ustr *ustrp__sc_vjoinx(struct Ustr_pool *p,
367 : size_t sz, size_t rbytes, int exact, int emem,
368 : const struct Ustr *sep,
369 : const struct Ustr *s2, const struct Ustr *s3,
370 : va_list ap)
371 88 : {
372 88 : struct Ustr *s1 = USTR_NULL;
373 88 : const char *sptr = ustr_cstr(sep);
374 88 : size_t slen = ustr_len(sep);
375 :
376 : #if USTR_CONF_HAVE_VA_COPY /* do a single allocation */
377 88 : size_t olen = 0;
378 88 : size_t len = 0;
379 88 : struct Ustr *tmp = USTR_NULL;
380 88 : int sz_bad = USTR_FALSE;
381 : va_list nap;
382 :
383 44 : USTR_ASSERT(ustrp__assert_valid(0, sep));
384 :
385 88 : USTR__VA_COPY(nap, ap);
386 :
387 88 : len += ustr_len(s2);
388 88 : sz_bad |= (len < olen); olen = len;
389 :
390 88 : len += slen;
391 88 : sz_bad |= (len < olen); olen = len;
392 :
393 88 : len += ustr_len(s3);
394 88 : sz_bad |= (len < olen); olen = len;
395 352 : while ((tmp = va_arg(nap, struct Ustr *)))
396 : {
397 176 : len += slen;
398 176 : sz_bad |= (len < olen); olen = len;
399 :
400 176 : len += ustr_len(tmp);
401 176 : sz_bad |= (len < olen); olen = len;
402 : }
403 88 : va_end(nap);
404 :
405 88 : if (sz_bad || !(s1 = ustrp__dupx_undef(p, sz, rbytes, exact, emem, len)))
406 : {
407 8 : errno = USTR__ENOMEM;
408 8 : return (USTR_NULL);
409 : }
410 :
411 80 : len = 0;
412 80 : ustr__memcpy(s1, len, ustr_cstr(s2), ustr_len(s2)); len += ustr_len(s2);
413 : do
414 : {
415 240 : ustr__memcpy(s1, len, sptr, slen); len += slen;
416 240 : ustr__memcpy(s1, len, ustr_cstr(s3), ustr_len(s3)); len += ustr_len(s3);
417 240 : } while ((s3 = va_arg(ap, struct Ustr *)));
418 40 : USTR_ASSERT(olen == len);
419 : #else
420 :
421 : USTR_ASSERT(ustrp__assert_valid(0, sep));
422 :
423 : if (!(s1 = ustrp__dupx(p, sz, rbytes, exact, USTR_FALSE, s2)))
424 : return (USTR_NULL);
425 :
426 : do {
427 : ustrp__add_buf(p, &s1, sptr, slen);
428 : ustrp__add(p, &s1, s3);
429 : } while ((s3 = va_arg(ap, struct Ustr *)));
430 :
431 : if (ustr_enomem(s1))
432 : {
433 : ustrp__sc_free(p, &s1);
434 : errno = USTR__ENOMEM;
435 : return (USTR_NULL);
436 : }
437 :
438 : if (emem)
439 : ustr_setf_enomem_err(s1);
440 : #endif
441 40 : USTR_ASSERT(ustrp__assert_valid(!!p, s1));
442 80 : return (s1);
443 : }
444 : USTR_CONF_I_PROTO
445 : struct Ustr *ustr_sc_vjoinx(size_t sz, size_t rbytes, int exact, int emem,
446 : const struct Ustr *sep, const struct Ustr *s2,
447 : const struct Ustr *s3, va_list ap)
448 4 : { return (ustrp__sc_vjoinx(0, sz, rbytes, exact, emem, sep, s2, s3, ap)); }
449 : USTR_CONF_I_PROTO
450 : struct Ustrp *ustrp_sc_vjoinx(struct Ustr_pool *p,
451 : size_t sz, size_t rbytes,
452 : int exact, int emem,
453 : const struct Ustrp *sp,const struct Ustrp *s2,
454 : const struct Ustrp *s3, va_list ap)
455 8 : { return (USTRP(ustrp__sc_vjoinx(p, sz, rbytes, exact, emem,
456 : &sp->s, &s2->s, &s3->s, ap))); }
457 : USTR_CONF_I_PROTO
458 : struct Ustr *ustr_sc_joinx(size_t sz, size_t rbytes,
459 : int exact, int emem,
460 : const struct Ustr *sep, const struct Ustr *s2,
461 : const struct Ustr *s3, ...)
462 4 : {
463 4 : struct Ustr *ret = USTR_NULL;
464 : va_list ap;
465 :
466 4 : va_start(ap, s3);
467 4 : ret = ustr_sc_vjoinx(sz, rbytes, exact, emem, sep, s2, s3, ap);
468 4 : va_end(ap);
469 :
470 4 : return (ret);
471 : }
472 : USTR_CONF_I_PROTO
473 : struct Ustrp *ustrp_sc_joinx(struct Ustr_pool *p,
474 : size_t sz, size_t rbytes,
475 : int exact, int emem,
476 : const struct Ustrp *sep,const struct Ustrp *s2,
477 : const struct Ustrp *s3, ...)
478 8 : {
479 8 : struct Ustrp *ret = USTRP_NULL;
480 : va_list ap;
481 :
482 8 : va_start(ap, s3);
483 8 : ret = ustrp_sc_vjoinx(p, sz, rbytes, exact, emem, sep, s2, s3, ap);
484 8 : va_end(ap);
485 :
486 8 : return (ret);
487 : }
488 :
489 : USTR_CONF_I_PROTO
490 : struct Ustr *ustr_sc_vjoin(const struct Ustr *sep, const struct Ustr *s2,
491 : const struct Ustr *s3, va_list ap)
492 20 : { return (ustrp__sc_vjoinx(0, USTR__DUPX_DEF, sep, s2, s3, ap)); }
493 : USTR_CONF_I_PROTO
494 : struct Ustrp *ustrp_sc_vjoin(struct Ustr_pool *p, const struct Ustrp *sep,
495 : const struct Ustrp *s2,const struct Ustrp *s3,
496 : va_list ap)
497 12 : { return (USTRP(ustrp__sc_vjoinx(p,USTR__DUPX_DEF,&sep->s,&s2->s,&s3->s,ap))); }
498 : USTR_CONF_I_PROTO
499 : struct Ustr *ustr_sc_join(const struct Ustr *sep, const struct Ustr *s2,
500 : const struct Ustr *s3, ...)
501 20 : {
502 20 : struct Ustr *ret = USTR_NULL;
503 : va_list ap;
504 :
505 20 : va_start(ap, s3);
506 20 : ret = ustr_sc_vjoin(sep, s2, s3, ap);
507 20 : va_end(ap);
508 :
509 20 : return (ret);
510 : }
511 : USTR_CONF_I_PROTO
512 : struct Ustrp *
513 : ustrp_sc_join(struct Ustr_pool *p, const struct Ustrp *sep,
514 : const struct Ustrp *s2, const struct Ustrp *s3, ...)
515 12 : {
516 12 : struct Ustrp *ret = USTRP_NULL;
517 : va_list ap;
518 :
519 12 : va_start(ap, s3);
520 12 : ret = ustrp_sc_vjoin(p, sep, s2, s3, ap);
521 12 : va_end(ap);
522 :
523 12 : return (ret);
524 : }
525 :
526 : /* ---- concat ---- */
527 :
528 : USTR_CONF_i_PROTO
529 : struct Ustr *ustrp__sc_vconcatx(struct Ustr_pool *p,
530 : size_t sz, size_t rbytes, int exact, int emem,
531 : const struct Ustr *s2, va_list ap)
532 44 : { return (ustrp__sc_vjoinx(p, sz,rbytes,exact,emem, USTR(""),USTR(""),s2,ap)); }
533 : USTR_CONF_I_PROTO
534 : struct Ustr *ustr_sc_vconcatx(size_t sz, size_t rbytes, int exact, int emem,
535 : const struct Ustr *s2, va_list ap)
536 4 : { return (ustrp__sc_vconcatx(0, sz, rbytes, exact, emem, s2, ap)); }
537 : USTR_CONF_I_PROTO
538 : struct Ustrp *ustrp_sc_vconcatx(struct Ustr_pool *p,
539 : size_t sz, size_t rbytes, int exact, int emem,
540 : const struct Ustrp *s2, va_list ap)
541 8 : { return (USTRP(ustrp__sc_vconcatx(p, sz,rbytes,exact,emem, &s2->s, ap))); }
542 : USTR_CONF_I_PROTO
543 : struct Ustr *ustr_sc_concatx(size_t sz, size_t rbytes, int exact, int emem,
544 : const struct Ustr *s2, ...)
545 4 : {
546 4 : struct Ustr *ret = USTR_NULL;
547 : va_list ap;
548 :
549 4 : va_start(ap, s2);
550 4 : ret = ustr_sc_vconcatx(sz, rbytes, exact, emem, s2, ap);
551 4 : va_end(ap);
552 :
553 4 : return (ret);
554 : }
555 : USTR_CONF_I_PROTO
556 : struct Ustrp *ustrp_sc_concatx(struct Ustr_pool *p,
557 : size_t sz, size_t rbytes, int exact, int emem,
558 : const struct Ustrp *s2, ...)
559 8 : {
560 8 : struct Ustrp *ret = USTRP_NULL;
561 : va_list ap;
562 :
563 8 : va_start(ap, s2);
564 8 : ret = ustrp_sc_vconcatx(p, sz, rbytes, exact, emem, s2, ap);
565 8 : va_end(ap);
566 :
567 8 : return (ret);
568 : }
569 :
570 : USTR_CONF_I_PROTO
571 : struct Ustr *ustr_sc_vconcat(const struct Ustr *s2, va_list ap)
572 20 : { return (ustrp__sc_vconcatx(0, USTR__DUPX_DEF, s2, ap)); }
573 : USTR_CONF_I_PROTO
574 : struct Ustrp *ustrp_sc_vconcat(struct Ustr_pool *p,
575 : const struct Ustrp *s2, va_list ap)
576 12 : { return (USTRP(ustrp__sc_vconcatx(p, USTR__DUPX_DEF, &s2->s, ap))); }
577 : USTR_CONF_I_PROTO
578 : struct Ustr *ustr_sc_concat(const struct Ustr *s2, ...)
579 20 : {
580 20 : struct Ustr *ret = USTR_NULL;
581 : va_list ap;
582 :
583 20 : va_start(ap, s2);
584 20 : ret = ustr_sc_vconcat(s2, ap);
585 20 : va_end(ap);
586 :
587 20 : return (ret);
588 : }
589 : USTR_CONF_I_PROTO
590 : struct Ustrp *ustrp_sc_concat(struct Ustr_pool *p,
591 : const struct Ustrp *s2, ...)
592 12 : {
593 12 : struct Ustrp *ret = USTRP_NULL;
594 : va_list ap;
595 :
596 12 : va_start(ap, s2);
597 12 : ret = ustrp_sc_vconcat(p, s2, ap);
598 12 : va_end(ap);
599 :
600 12 : return (ret);
601 : }
602 :
|