1 : /* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */
2 :
3 : #ifndef USTR_MAIN_H
4 : #error " You should have already included ustr-main.h, or just include ustr.h."
5 : #endif
6 :
7 : USTR_CONF_i_PROTO
8 : int ustr__dupx_cmp_eq(size_t sz1, size_t rb1, int x1, int emem1,
9 : size_t sz2, size_t rb2, int x2, int emem2)
10 262938 : {
11 262938 : if ((!x1 != !x2) || (!emem1 != !emem2))
12 166 : return (USTR_FALSE);
13 :
14 262772 : if (sz1)
15 : {
16 262182 : if (rb1 < 2)
17 262152 : rb1 = 2;
18 : }
19 590 : else if (rb1 > 4)
20 2 : sz1 = 1;
21 :
22 262772 : if (sz2)
23 : {
24 262164 : if (rb2 < 2)
25 2 : rb2 = 2;
26 : }
27 608 : else if (rb2 > 4)
28 4 : sz2 = 1;
29 :
30 262772 : return ((!sz1 == !sz2) && (rb1 == rb2));
31 : }
32 :
33 : USTR_CONF_i_PROTO size_t ustr__sz_get(const struct Ustr *s1)
34 1445490 : {
35 1445490 : size_t lenn = 0;
36 :
37 1314164 : USTR_ASSERT(!ustr_ro(s1));
38 1314164 : USTR_ASSERT( ustr_sized(s1));
39 :
40 1445490 : lenn = USTR__LEN_LEN(s1);
41 :
42 2759654 : return (ustr_xi__embed_val_get(s1->data + 1 + USTR__REF_LEN(s1) + lenn,lenn));
43 : }
44 :
45 : USTR_CONF_i_PROTO size_t ustr__nb(size_t num)
46 598775 : {
47 : USTR_ASSERT((num <= 0xFFFFFFFF) || USTR_CONF_HAVE_64bit_SIZE_MAX);
48 :
49 1522573 : if (num > 0xFFFFFFFF) return (8);
50 1521845 : if (num > 0xFFFF) return (4);
51 1521729 : if (num > 0xFF) return (2);
52 1520717 : else return (1);
53 : }
54 :
55 : USTR_CONF_i_PROTO
56 : int ustrp__assert_valid(int p, const struct Ustr *s1)
57 4473973 : {
58 4473973 : const char *eos_ptr = 0;
59 4473973 : size_t eos_len = sizeof(USTR_END_ALOCDx);
60 4473973 : size_t rbytes = 0;
61 4473973 : size_t lbytes = 0;
62 4473973 : size_t sbytes = 0;
63 4473973 : size_t sz = 0;
64 4473973 : size_t oh = 0;
65 :
66 4473973 : USTR_ASSERT_RET(s1, USTR_FALSE);
67 2537925 : ustr_assert_ret(USTR__ASSERT_MALLOC_CHECK_MEM(p, s1), USTR_FALSE);
68 :
69 4473973 : if (!s1->data[0])
70 985942 : return (USTR_TRUE);
71 :
72 : /* just make sure for compound "bits" tests */
73 6981743 : USTR_ASSERT(( ustr_alloc(s1) || ustr_sized(s1)) != ustr_ro(s1));
74 6981743 : USTR_ASSERT((!ustr_alloc(s1) && ustr_sized(s1)) == ustr_fixed(s1));
75 6976688 : USTR_ASSERT(( ustr_fixed(s1) && ustr_exact(s1)) == ustr_limited(s1));
76 :
77 3488031 : rbytes = USTR__REF_LEN(s1);
78 3488031 : lbytes = USTR__LEN_LEN(s1);
79 3488031 : ustr_assert_ret(lbytes, USTR_FALSE);
80 :
81 3488031 : if (ustr_sized(s1))
82 : {
83 1051555 : sbytes = lbytes;
84 1051555 : sz = ustr__sz_get(s1);
85 : }
86 3488031 : oh = 1 + rbytes + lbytes + sbytes + eos_len;
87 :
88 3488031 : USTR_ASSERT_RET(!ustr_sized(s1) || (ustr_len(s1) <= sz), USTR_FALSE);
89 :
90 4408304 : USTR_ASSERT(!sz || (ustr__nb(sz) == lbytes) ||
91 : ((ustr__nb(sz) == 1) && (lbytes == 2))); /* 2 is the minimum */
92 :
93 3488031 : USTR_ASSERT_RET(!sz || (oh <= sz), USTR_FALSE);
94 3488031 : USTR_ASSERT_RET(!sz || ((ustr_len(s1) + oh) <= sz), USTR_FALSE);
95 :
96 5920440 : USTR_ASSERT_RET( ustr_exact(s1) || !ustr_ro(s1), USTR_FALSE);
97 4539979 : USTR_ASSERT_RET(!ustr_enomem(s1) || !ustr_ro(s1), USTR_FALSE);
98 :
99 : if (!USTR_CONF_USE_EOS_MARK)
100 : {
101 5461 : USTR_ASSERT_RET(!ustr_cstr(s1)[ustr_len(s1)], USTR_FALSE);
102 5461 : return (USTR_TRUE);
103 : }
104 :
105 3482570 : if (ustr_ro(s1))
106 4083 : eos_ptr = USTR_END_CONSTx;
107 3478487 : else if (ustr_fixed(s1))
108 316 : eos_ptr = USTR_END_FIXEDx;
109 : else
110 3478171 : eos_ptr = USTR_END_ALOCDx;
111 :
112 3482570 : USTR_ASSERT_RET(!memcmp(ustr_cstr(s1) + ustr_len(s1), eos_ptr, eos_len),
113 : USTR_FALSE);
114 :
115 3482570 : return (USTR_TRUE);
116 : }
117 : /* Due to ustrp_assert_valid() being inline we can't pass 0 for
118 : * ustr_assert_valid() until we've made two ustr_assert_valid() versions.
119 : * Maybe I'll do that for 1.0.3 ... NOTE: We'd need to change the other
120 : * internal ustr_assert_valid() calls. */
121 : USTR_CONF_I_PROTO int ustr_assert_valid(const struct Ustr *s1)
122 3581787 : { return (ustrp__assert_valid(1, s1)); }
123 : /* We can't change the API of this function until 2.0.x time, even if we want
124 : * to. But it's no big deal, as we might not want to. */
125 : USTR_CONF_I_PROTO int ustrp_assert_valid(const struct Ustrp *s1)
126 14 : { return (ustrp__assert_valid(1, &s1->s)); }
127 :
128 : USTR_CONF_i_PROTO
129 : size_t ustrp__assert_valid_subustr(int p, const struct Ustr *s1,
130 : size_t pos, size_t len)
131 2852 : {
132 2852 : size_t clen = 0;
133 :
134 : (void) p;
135 1430 : USTR_ASSERT(ustrp__assert_valid(p, s1));
136 2852 : USTR_ASSERT_RET(pos, 0);
137 :
138 2852 : clen = ustr_len(s1);
139 2852 : if (((pos == 1) || !len) && (len == clen))
140 228 : return (clen);
141 :
142 2624 : USTR_ASSERT_RET((clen >= pos), 0);
143 2590 : USTR_ASSERT_RET((clen >= (len + --pos)), 0);
144 :
145 2530 : return (clen);
146 : }
147 : /* see comments for ustr_assert_valid() etc. */
148 : USTR_CONF_I_PROTO
149 : size_t ustr_assert_valid_subustr(const struct Ustr *s1, size_t pos, size_t len)
150 618 : { return (ustrp__assert_valid_subustr(1, s1, pos, len)); }
151 : USTR_CONF_I_PROTO
152 : int ustrp_assert_valid_subustrp(const struct Ustrp *s1, size_t pos, size_t len)
153 12 : { return (ustrp__assert_valid_subustr(1, &s1->s, pos, len)); }
154 :
155 : USTR_CONF_I_PROTO char *ustr_wstr(struct Ustr *s1)
156 4202 : { /* NOTE: Not EI/II so we can call ustr_assert_valid() here. */
157 4202 : unsigned char *data = s1->data;
158 4202 : size_t lenn = 0;
159 :
160 2101 : USTR_ASSERT(ustr_assert_valid(s1));
161 :
162 4202 : USTR_ASSERT_RET(!ustr_ro(s1), 0);
163 :
164 4202 : lenn = USTR__LEN_LEN(s1);
165 4202 : if (ustr_sized(s1))
166 391 : lenn *= 2;
167 :
168 6303 : return ((char *)(data + 1 + USTR__REF_LEN(s1) + lenn));
169 : }
170 :
171 : USTR_CONF_I_PROTO int ustr_owner(const struct Ustr *s1)
172 6683 : {
173 3952 : USTR_ASSERT(ustr_assert_valid(s1));
174 :
175 6683 : if (ustr_ro(s1)) return (USTR_FALSE);
176 5629 : if (ustr_fixed(s1)) return (USTR_TRUE);
177 :
178 8754 : switch (USTR__REF_LEN(s1))
179 : {
180 : #if USTR_CONF_HAVE_64bit_SIZE_MAX
181 6 : case 8: if (s1->data[8]) return (USTR_FALSE);
182 6 : if (s1->data[7]) return (USTR_FALSE);
183 6 : if (s1->data[6]) return (USTR_FALSE);
184 6 : if (s1->data[5]) return (USTR_FALSE);
185 : #endif
186 811 : case 4: if (s1->data[4]) return (USTR_FALSE);
187 811 : if (s1->data[3]) return (USTR_FALSE);
188 1675 : case 2: if (s1->data[2]) return (USTR_FALSE);
189 :
190 3939 : case 1: return (s1->data[1] == 1);
191 :
192 : case 0:
193 :
194 0 : USTR_ASSERT_NO_SWITCH_DEF("Ref. length bad for ustr__ref_owner()");
195 : }
196 :
197 1521 : return (USTR_TRUE); /* Ustr with no ref. count */
198 : }
199 :
200 : USTR_CONF_I_PROTO int ustr_setf_enomem_err(struct Ustr *s1)
201 569 : {
202 338 : USTR_ASSERT(ustr_assert_valid(s1));
203 :
204 569 : errno = USTR__ENOMEM;
205 569 : if (!ustr_owner(s1))
206 230 : return (USTR_FALSE);
207 :
208 339 : s1->data[0] |= USTR__BIT_ENOMEM;
209 339 : return (USTR_TRUE);
210 : }
211 : USTR_CONF_I_PROTO int ustr_setf_enomem_clr(struct Ustr *s1)
212 141 : {
213 70 : USTR_ASSERT(ustr_assert_valid(s1));
214 :
215 141 : errno = 0;
216 141 : if (!ustr_owner(s1))
217 8 : return (USTR_FALSE);
218 :
219 133 : s1->data[0] &= ~USTR__BIT_ENOMEM;
220 133 : return (USTR_TRUE);
221 : }
222 :
223 : USTR_CONF_i_PROTO void ustr__embed_val_set(unsigned char *data,
224 : size_t len, size_t val)
225 1317608 : {
226 1317608 : switch (len)
227 : {
228 : #if USTR_CONF_HAVE_64bit_SIZE_MAX
229 : case 8:
230 25 : data[7] = (val >> 56) & 0xFF;
231 25 : data[6] = (val >> 48) & 0xFF;
232 25 : data[5] = (val >> 40) & 0xFF;
233 25 : data[4] = (val >> 32) & 0xFF;
234 : #endif
235 : case 4:
236 262597 : data[3] = (val >> 24) & 0xFF;
237 262597 : data[2] = (val >> 16) & 0xFF;
238 : case 2:
239 1312463 : data[1] = (val >> 8) & 0xFF;
240 : case 1:
241 1317608 : data[0] = (val >> 0) & 0xFF;
242 :
243 0 : USTR_ASSERT_NO_SWITCH_DEF("Val. length bad for ustr__embed_val_set()");
244 : }
245 1317608 : }
246 :
247 : /* no warn here, because most callers already know it's not going to fail */
248 : USTR_CONF_i_PROTO int ustr__ref_set(struct Ustr *s1, size_t ref)
249 1313904 : {
250 1313904 : size_t len = 0;
251 :
252 656950 : USTR_ASSERT(ustr_assert_valid(s1));
253 656950 : USTR_ASSERT(ustr_alloc(s1));
254 :
255 1970854 : if (!(len = USTR__REF_LEN(s1)))
256 312 : return (USTR_FALSE);
257 :
258 1313592 : ustr__embed_val_set(s1->data + 1, len, ref);
259 :
260 656794 : USTR_ASSERT(ustr_assert_valid(s1));
261 :
262 1313592 : return (USTR_TRUE);
263 : }
264 :
265 : USTR_CONF_I_PROTO int ustr_setf_share(struct Ustr *s1)
266 58 : {
267 29 : USTR_ASSERT(ustr_assert_valid(s1));
268 :
269 58 : if (!ustr_alloc(s1))
270 4 : return (USTR_TRUE);
271 :
272 54 : if (!ustr__ref_set(s1, 0))
273 12 : return (USTR_FALSE);
274 :
275 21 : USTR_ASSERT(ustr_assert_valid(s1));
276 42 : return (USTR_TRUE);
277 : }
278 : USTR_CONF_I_PROTO int ustr_setf_owner(struct Ustr *s1)
279 24 : {
280 12 : USTR_ASSERT(ustr_assert_valid(s1));
281 :
282 24 : if (!ustr_alloc(s1))
283 4 : return (USTR_FALSE);
284 :
285 20 : ustr__ref_set(s1, 1); /* 0 means it's unsharable and so they are the owner */
286 :
287 10 : USTR_ASSERT(ustr_assert_valid(s1));
288 20 : return (USTR_TRUE);
289 : }
290 :
291 : USTR_CONF_i_PROTO void ustr__len_set(struct Ustr *s1, size_t len)
292 3745 : { /* can only validate after the right len is in place */
293 3745 : unsigned char *data = s1->data;
294 :
295 1872 : USTR_ASSERT(!ustr_ro(s1));
296 7489 : ustr__embed_val_set(data + 1 + USTR__REF_LEN(s1), USTR__LEN_LEN(s1), len);
297 1872 : USTR_ASSERT(ustr_assert_valid(s1));
298 3745 : }
299 :
300 : USTR_CONF_i_PROTO void ustr__sz_set(struct Ustr *s1, size_t sz)
301 240 : { /* can't validate as this is called before anything is setup */
302 240 : size_t lenn = 0;
303 :
304 119 : USTR_ASSERT(!ustr_ro(s1));
305 119 : USTR_ASSERT(ustr_sized(s1));
306 :
307 240 : lenn = USTR__LEN_LEN(s1);
308 :
309 359 : ustr__embed_val_set(s1->data + 1 + USTR__REF_LEN(s1) + lenn, lenn, sz);
310 240 : }
311 :
312 : USTR_CONF_i_PROTO int ustr__ref_add(struct Ustr *s1)
313 1329921 : {
314 1329921 : size_t ref = 0;
315 1329921 : size_t lim = 0;
316 :
317 664960 : USTR_ASSERT(ustr_assert_valid(s1));
318 :
319 1329921 : if (ustr_ro(s1))
320 393930 : return (USTR_TRUE);
321 935991 : if (ustr_fixed(s1))
322 8 : return (USTR_FALSE);
323 :
324 1403974 : switch (USTR__REF_LEN(s1))
325 : {
326 : #if USTR_CONF_HAVE_64bit_SIZE_MAX
327 5 : case 8: if (!lim) lim = 0xFFFFFFFFFFFFFFFFULL;
328 : #endif
329 131087 : case 4: if (!lim) lim = 0xFFFFFFFFUL;
330 935387 : case 2: if (!lim) lim = 0xFFFF;
331 935955 : case 1: if (!lim) lim = 0xFF;
332 :
333 935955 : ref = ustr_xi__ref_get(s1);
334 935955 : if (ref == 0)
335 280000 : return (USTR_TRUE);
336 655955 : if (ref == lim)
337 10 : return (USTR_FALSE);
338 655945 : ustr__ref_set(s1, ref + 1);
339 655945 : return (USTR_TRUE);
340 :
341 : case 0: /* Ustr with no reference count */
342 :
343 0 : USTR_ASSERT_NO_SWITCH_DEF("Ref. length bad for ustr__ref_add()");
344 : }
345 :
346 28 : return (USTR_FALSE);
347 : }
348 :
349 : USTR_CONF_i_PROTO size_t ustr__ref_del(struct Ustr *s1)
350 1765675 : {
351 882838 : USTR_ASSERT(ustr_assert_valid(s1));
352 :
353 1765675 : if (!ustr_alloc(s1))
354 788252 : return (-1);
355 :
356 1466135 : switch (USTR__REF_LEN(s1))
357 : {
358 : case 8:
359 : case 4:
360 : case 2:
361 : case 1:
362 : {
363 977191 : size_t ref = ustr_xi__ref_get(s1);
364 :
365 977191 : if (ref == 0)
366 320030 : return (-1);
367 657161 : if (ref == 1) /* Special case this so it doesn't "go shared"
368 : * plus this is a common case and doing this is
369 : * marginally faster */
370 1216 : return (0);
371 :
372 655945 : ustr__ref_set(s1, ref - 1);
373 655945 : return (ref - 1);
374 : }
375 :
376 : case 0: /* Ustr with no reference count */
377 :
378 0 : USTR_ASSERT_NO_SWITCH_DEF("Ref. length bad for ustr__ref_del()");
379 : }
380 :
381 232 : return (0);
382 : }
383 :
384 : USTR_CONF_I_PROTO size_t ustr_size_overhead(const struct Ustr *s1)
385 287337 : {
386 287337 : size_t lenn = 0;
387 :
388 286004 : USTR_ASSERT(ustr_assert_valid(s1));
389 :
390 287337 : if (!s1->data[0])
391 4 : return (1);
392 :
393 287333 : lenn = USTR__LEN_LEN(s1);
394 287333 : if (ustr_sized(s1))
395 200 : lenn *= 2;
396 :
397 573335 : return (1 + USTR__REF_LEN(s1) + lenn + sizeof(USTR_END_ALOCDx));
398 : }
399 :
400 : USTR_CONF_I_PROTO size_t ustr_size_alloc(const struct Ustr *s1)
401 418331 : { /* copy and paste so that ustr_ro() does the right thing */
402 418331 : size_t oh = 0;
403 :
404 417151 : USTR_ASSERT(ustr_assert_valid(s1));
405 :
406 418331 : if (ustr_sized(s1))
407 131353 : return (ustr__sz_get(s1));
408 :
409 286978 : oh = ustr_size_overhead(s1);
410 285838 : USTR_ASSERT((oh + ustr_len(s1)) >= oh);
411 :
412 286978 : if (ustr_exact(s1))
413 175 : return (ustr_len(s1) + oh);
414 :
415 286803 : return (ustr__ns(ustr_len(s1) + oh));
416 : }
417 :
418 : USTR_CONF_i_PROTO void ustrp__free(struct Ustr_pool *p, struct Ustr *s1)
419 1765816 : {
420 1765816 : if (!s1) return;
421 :
422 882838 : USTR_ASSERT(ustrp__assert_valid(!!p, s1));
423 :
424 1765675 : if (!ustr__ref_del(s1))
425 : {
426 1448 : if (p)
427 116 : p->pool_sys_free(p, s1);
428 : else
429 1332 : USTR_CONF_FREE(s1);
430 : }
431 : }
432 :
433 : USTR_CONF_I_PROTO void ustr_free(struct Ustr *s1)
434 1763588 : { return (ustrp__free(0, s1)); }
435 : USTR_CONF_I_PROTO void ustrp_free(struct Ustr_pool *p, struct Ustrp *s1)
436 4 : { return (ustrp__free(p, &s1->s)); }
437 :
438 : /* shortcut -- needs to be here, as lots of things calls this */
439 : USTR_CONF_i_PROTO
440 : void ustrp__sc_free2(struct Ustr_pool *p, struct Ustr **ps1, struct Ustr *s2)
441 1308 : {
442 654 : USTR_ASSERT(ps1);
443 654 : USTR_ASSERT(ustrp__assert_valid(!!p, s2)); /* don't pass NULL */
444 :
445 1308 : ustrp__free(p, *ps1);
446 1308 : *ps1 = s2;
447 1308 : }
448 :
449 : USTR_CONF_i_PROTO size_t ustr__ns(size_t num)
450 291273 : {
451 291273 : size_t min_sz = 4;
452 :
453 291273 : if (num > ((USTR__SIZE_MAX / 4) * 3))
454 2 : return (USTR__SIZE_MAX);
455 :
456 : /* *2 is too much, we end up wasting a lot of RAM. So we do *1.5. */
457 1172466 : while (min_sz < num)
458 : {
459 883217 : size_t adder = min_sz / 2;
460 :
461 883217 : min_sz += adder;
462 883217 : if (min_sz >= num) break;
463 877864 : min_sz += adder;
464 : }
465 :
466 291271 : return (min_sz);
467 : }
468 :
469 : /* ---------------- init - helpers so others can make Ustr's ---------------- */
470 : USTR_CONF_I_PROTO size_t ustr_init_size(size_t sz, size_t rbytes, int exact,
471 : size_t len)
472 2578 : {
473 2578 : size_t oh = 0;
474 2578 : size_t rsz = sz ? sz : len;
475 2578 : size_t lbytes = 0;
476 :
477 2578 : USTR_ASSERT_RET((rbytes == 0) ||
478 : (rbytes == 1) || (rbytes == 2) || (rbytes == 4) ||
479 : (USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)), 0);
480 :
481 : do
482 : {
483 2584 : size_t sbytes = 0;
484 :
485 1907 : lbytes = ustr__nb(rsz);
486 2584 : if (!sz && ((lbytes == 8) || (rbytes == 8)))
487 488 : sz = 1;
488 :
489 1365 : USTR_ASSERT( (lbytes == 1) || (lbytes == 2) || (lbytes == 4) ||
490 : (USTR_CONF_HAVE_64bit_SIZE_MAX && (lbytes == 8)));
491 :
492 2584 : if (sz)
493 : {
494 670 : if (rbytes <= 1)
495 608 : rbytes = 2;
496 670 : if (lbytes <= 1)
497 184 : lbytes = 2;
498 670 : sbytes = lbytes;
499 : }
500 :
501 2584 : oh = 1 + rbytes + lbytes + sbytes + sizeof(USTR_END_ALOCDx);
502 2584 : rsz = oh + len;
503 :
504 2584 : if (rsz < len)
505 : {
506 484 : errno = USTR__EINVAL;
507 484 : return (0);
508 : }
509 :
510 1093 : USTR_ASSERT((lbytes <= ustr__nb(rsz)) ||
511 : ((lbytes == 2) && sz && (ustr__nb(rsz) == 1)));
512 2100 : } while (lbytes < ustr__nb(rsz));
513 :
514 2094 : if (exact)
515 132 : return (rsz);
516 :
517 1962 : return (ustr__ns(rsz));
518 : }
519 :
520 : /* NIL terminate -- with possible end marker */
521 : USTR_CONF_i_PROTO void ustr__terminate(unsigned char *ptr, int alloc,size_t len)
522 3601 : {
523 : if (sizeof(USTR_END_ALOCDx) == 1)
524 2062 : ptr[len] = 0;
525 1713 : else if (alloc)
526 1695 : memcpy(ptr + len, USTR_END_ALOCDx, sizeof(USTR_END_ALOCDx));
527 : else
528 18 : memcpy(ptr + len, USTR_END_FIXEDx, sizeof(USTR_END_FIXEDx));
529 3601 : }
530 :
531 : USTR_CONF_I_PROTO
532 : struct Ustr *ustr_init_alloc(void *data, size_t rsz, size_t sz,
533 : size_t rbytes, int exact, int emem, size_t len)
534 1955 : {
535 : static const unsigned char map_big_pow2[9] = {-1, -1, 0, -1, 1, -1, -1, -1,2};
536 : static const unsigned char map_pow2[5] = {0, 1, 2, -1, 3};
537 1955 : struct Ustr *ret = data;
538 1955 : int nexact = !exact;
539 1955 : int sized = 0;
540 1955 : size_t lbytes = 0;
541 1955 : size_t sbytes = 0;
542 1955 : size_t oh = 0;
543 1955 : const size_t eos_len = sizeof(USTR_END_ALOCDx);
544 :
545 1955 : USTR_ASSERT_RET((rbytes == 0) ||
546 : (rbytes == 1) || (rbytes == 2) || (rbytes == 4) ||
547 : (USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)), USTR_NULL);
548 977 : USTR_ASSERT(data);
549 977 : USTR_ASSERT(exact == !!exact);
550 977 : USTR_ASSERT(emem == !!emem);
551 977 : USTR_ASSERT(!sz || (sz == rsz));
552 1955 : USTR_ASSERT_RET(!sz || (sz > len), USTR_NULL);
553 :
554 1955 : if (!sz && (rbytes == 8))
555 4 : sz = rsz; /* whee... */
556 :
557 1955 : lbytes = ustr__nb(sz ? sz : len);
558 1955 : if (!sz && (lbytes == 8))
559 4 : sz = rsz; /* whee... */
560 1465 : USTR_ASSERT(lbytes == ustr__nb(sz ? sz : len));
561 :
562 977 : USTR_ASSERT( (lbytes == 1) || (lbytes == 2) || (lbytes == 4) ||
563 : (USTR_CONF_HAVE_64bit_SIZE_MAX && (lbytes == 8)));
564 :
565 1955 : if (sz)
566 : {
567 227 : if (sz < (1 + 2 + 2 + 1))
568 12 : goto val_inval;
569 :
570 215 : if (rbytes <= 1)
571 167 : rbytes = 2;
572 215 : if (lbytes <= 1)
573 175 : lbytes = 2;
574 215 : sbytes = lbytes;
575 : }
576 1943 : oh = 1 + rbytes + lbytes + sbytes + eos_len;
577 :
578 1943 : if (rsz < (oh + len))
579 4 : goto val_inval;
580 :
581 1939 : if (sz) sized = USTR__BIT_HAS_SZ;
582 1939 : if (nexact) nexact = USTR__BIT_NEXACT;
583 1939 : if (emem) emem = USTR__BIT_ENOMEM;
584 :
585 1939 : ret->data[0] = USTR__BIT_ALLOCD | sized | nexact | emem;
586 1939 : if (sz)
587 211 : ret->data[0] |= (map_big_pow2[rbytes] << 2) | map_big_pow2[lbytes];
588 : else
589 1728 : ret->data[0] |= (map_pow2[rbytes] << 2) | map_pow2[lbytes];
590 :
591 1939 : ustr__terminate(ret->data, USTR_TRUE, (oh - eos_len) + len);
592 :
593 1939 : if (sz)
594 211 : ustr__sz_set(ret, sz);
595 1939 : ustr__len_set(ret, len);
596 1939 : ustr__ref_set(ret, 1);
597 :
598 969 : USTR_ASSERT(ustr_assert_valid(ret));
599 969 : USTR_ASSERT( ustr_alloc(ret));
600 969 : USTR_ASSERT(!ustr_fixed(ret));
601 969 : USTR_ASSERT(!ustr_ro(ret));
602 969 : USTR_ASSERT( ustr_enomem(ret) == !!emem);
603 969 : USTR_ASSERT( ustr_exact(ret) == exact);
604 969 : USTR_ASSERT(!ustr_shared(ret));
605 969 : USTR_ASSERT( ustr_owner(ret));
606 :
607 1939 : return (ret);
608 :
609 16 : val_inval:
610 16 : errno = USTR__EINVAL;
611 16 : return (USTR_NULL);
612 : }
613 : USTR_CONF_I_PROTO
614 : struct Ustrp *ustrp_init_alloc(void *data, size_t rsz, size_t sz,
615 : size_t rbytes, int exact, int emem, size_t len)
616 4 : { return (USTRP(ustr_init_alloc(data, rsz, sz, rbytes, exact, emem, len))); }
617 :
618 : USTR_CONF_I_PROTO
619 : struct Ustr *ustr_init_fixed(void *data, size_t sz, int exact, size_t len)
620 47 : {
621 47 : struct Ustr *ret = data;
622 47 : void *tmp = 0; /* move type between char and unsigned char */
623 47 : size_t rbytes = 0;
624 47 : const int emem = USTR_FALSE;
625 :
626 23 : USTR_ASSERT(sz);
627 :
628 47 : if (!ustr_init_alloc(data, sz, sz, rbytes, exact, emem, len))
629 16 : return (USTR_NULL);
630 :
631 31 : tmp = ustr_wstr(ret); /* done here,
632 : as it might not be valid until we terminate */
633 :
634 31 : ret->data[0] &= ~USTR__BIT_ALLOCD;
635 31 : ustr__terminate(tmp, USTR_FALSE, len);
636 46 : if ((rbytes = USTR__REF_LEN(ret))) /* _large_ */
637 31 : ustr__embed_val_set(ret->data + 1, rbytes, 0);
638 :
639 15 : USTR_ASSERT(ustr_assert_valid(ret));
640 15 : USTR_ASSERT( ustr_fixed(ret));
641 15 : USTR_ASSERT(!ustr_alloc(ret));
642 15 : USTR_ASSERT(!ustr_ro(ret));
643 15 : USTR_ASSERT( ustr_enomem(ret) == emem);
644 15 : USTR_ASSERT(!ustr_shared(ret));
645 15 : USTR_ASSERT( ustr_owner(ret));
646 :
647 31 : return (ret);
648 : }
649 : USTR_CONF_I_PROTO
650 : struct Ustrp *ustrp_init_fixed(void *data, size_t sz, int exact, size_t len)
651 8 : { return (USTRP(ustr_init_fixed(data, sz, exact, len))); }
652 :
653 : USTR_CONF_I_PROTO size_t ustr_size(const struct Ustr *s1)
654 491 : { /* size of available space in the string */
655 491 : size_t oh = 0;
656 :
657 234 : USTR_ASSERT(ustr_assert_valid(s1));
658 :
659 491 : if (ustr_sized(s1))
660 104 : return (ustr__sz_get(s1) - ustr_size_overhead(s1));
661 387 : if (ustr_exact(s1))
662 242 : return (ustr_len(s1));
663 :
664 145 : oh = ustr_size_overhead(s1);
665 145 : return (ustr__ns(ustr_len(s1) + oh) - oh);
666 : }
667 :
668 : /* ---------------- allocations ---------------- */
669 : /* NOTE: This is one of the two main "allocation" functions --
670 : * this is the only thing that calls MALLOC. */
671 : USTR_CONF_i_PROTO
672 : struct Ustr *ustrp__dupx_undef(struct Ustr_pool *p, size_t sz, size_t rbytes,
673 : int exact, int emem, size_t len)
674 2656 : {
675 2656 : struct Ustr *ret = USTR_NULL;
676 2656 : struct Ustr *chk = USTR_NULL;
677 2656 : size_t rsz = 0;
678 :
679 1400 : USTR_ASSERT((rbytes == 0) || (rbytes == 1) || (rbytes == 2) || (rbytes == 4)||
680 : (USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)));
681 1400 : USTR_ASSERT(exact == !!exact);
682 1400 : USTR_ASSERT(emem == !!emem);
683 :
684 2656 : if (!len && ustr__dupx_cmp_eq(sz, rbytes, exact, emem, USTR__DUPX_DEF))
685 86 : return (USTR("")); /* We don't go to all the trouble ustr_del() does.
686 : * Which is probably better overall. */
687 :
688 2570 : if (!(rsz = ustr_init_size(sz, rbytes, exact, len)))
689 480 : return (USTR_NULL);
690 :
691 2090 : if (p)
692 656 : ret = p->pool_sys_malloc(p, rsz);
693 : else
694 1434 : ret = USTR_CONF_MALLOC(rsz);
695 :
696 2090 : if (!ret)
697 : {
698 190 : errno = USTR__ENOMEM;
699 190 : return (USTR_NULL);
700 : }
701 :
702 1900 : chk = ustr_init_alloc(ret, rsz, sz ? rsz : 0, rbytes, exact, emem, len);
703 950 : USTR_ASSERT(chk);
704 :
705 950 : USTR_ASSERT(ustrp__assert_valid(!!p, ret));
706 1900 : return (ret);
707 : }
708 :
709 : USTR_CONF_i_PROTO
710 : int ustrp__rw_realloc(struct Ustr_pool *p, struct Ustr **ps1,
711 : int sized, size_t osz, size_t nsz)
712 1037 : {
713 1037 : struct Ustr *ret = USTR_NULL;
714 :
715 968 : USTR_ASSERT(ustr_alloc(*ps1));
716 484 : USTR_ASSERT(osz == ustr_size_alloc(*ps1));
717 484 : USTR_ASSERT(sized == !!sized);
718 968 : USTR_ASSERT(sized == ustr_sized(*ps1));
719 437 : ustr_assert(USTR__ASSERT_MALLOC_CHECK_MEM(p, *ps1));
720 :
721 : /* printf("1. p=%p, osz=%zu, nsz=%zu\n", p, osz, nsz); */
722 1037 : if (p)
723 242 : ret = p->pool_sys_realloc(p, *ps1, osz, nsz);
724 : else
725 795 : ret = USTR_CONF_REALLOC(*ps1, nsz);
726 :
727 1037 : if (!ret)
728 : {
729 71 : ustr_setf_enomem_err(*ps1);
730 71 : return (USTR_FALSE);
731 : }
732 966 : if (sized)
733 28 : ustr__sz_set(ret, nsz);
734 :
735 966 : *ps1 = ret;
736 :
737 966 : return (USTR_TRUE);
738 : }
739 :
740 : USTR_CONF_i_PROTO void ustr__memcpy(struct Ustr *s1, size_t off,
741 : const void *ptr, size_t len)
742 3828 : { /* can't call ustr_wstr() if len == 0, as it might be RO */
743 3828 : if (!len)
744 880 : return;
745 2948 : memcpy(ustr_wstr(s1) + off, ptr, len);
746 : }
747 :
748 : USTR_CONF_i_PROTO void ustr__memset(struct Ustr *s1, size_t off,
749 : int chr, size_t len)
750 280 : { /* can't call ustr_wstr() if len == 0, as it might be RO */
751 280 : if (!len)
752 17 : return;
753 263 : memset(ustr_wstr(s1) + off, chr, len);
754 : }
755 :
756 : /* ---------------- del ---------------- */
757 :
758 : /* Fine grained management of the space allocated to a sized Ustr */
759 : USTR_CONF_i_PROTO
760 : int ustrp__realloc(struct Ustr_pool *p, struct Ustr **ps1, size_t nsz)
761 64 : {
762 64 : struct Ustr *s1 = USTR_NULL;
763 64 : size_t oh = 0;
764 64 : size_t len = 0;
765 64 : size_t msz = 0; /* min size */
766 64 : size_t osz = 0; /* old size */
767 64 : int ret = USTR_TRUE;
768 :
769 32 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
770 :
771 64 : s1 = *ps1;
772 96 : if (!ustr_sized(s1) || !ustr_alloc(s1) || !ustr_owner(s1))
773 4 : return (USTR_FALSE);
774 :
775 60 : oh = ustr_size_overhead(s1);
776 60 : len = ustr_len(s1);
777 60 : msz = oh + len;
778 :
779 60 : if (!nsz)
780 16 : nsz = len;
781 60 : nsz += oh; /* if this overflows, we'll get it at the msz test */
782 :
783 60 : osz = ustr__sz_get(s1);
784 60 : if (nsz == osz) /* if there's nothing to do... */
785 8 : return (USTR_TRUE);
786 :
787 52 : if (nsz < msz) /* we can't go less than the minimum */
788 16 : return (USTR_FALSE);
789 :
790 : /* Don't let the length num. bytes go up, as we might as well just dupx()
791 : */
792 54 : if (ustr__nb(nsz) > USTR__LEN_LEN(s1))
793 12 : return (USTR_FALSE);
794 :
795 24 : ret = ustrp__rw_realloc(p, ps1, USTR_TRUE, osz, nsz);
796 12 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
797 :
798 24 : return (ret);
799 : }
800 : USTR_CONF_I_PROTO int ustr_realloc(struct Ustr **ps1, size_t sz)
801 8 : { return (ustrp__realloc(0, ps1, sz)); }
802 : USTR_CONF_I_PROTO int ustrp_realloc(struct Ustr_pool *p,
803 : struct Ustrp **ps1, size_t sz)
804 56 : {
805 56 : struct Ustr *tmp = &(*ps1)->s;
806 56 : int ret = ustrp__realloc(p, &tmp, sz);
807 56 : *ps1 = USTRP(tmp);
808 56 : return (ret);
809 : }
810 :
811 : /* Can we actually RW to this Ustr, at _this_ moment, _this_ len */
812 : USTR_CONF_i_PROTO
813 : int ustr__rw_mod(struct Ustr *s1, size_t nlen, size_t *sz, size_t *oh,
814 : size_t *osz, size_t *nsz, int *alloc)
815 3213 : {
816 3213 : size_t lbytes = 0;
817 3213 : size_t sbytes = 0;
818 :
819 3213 : if (!ustr_owner(s1))
820 596 : return (USTR_FALSE);
821 :
822 2617 : *sz = 0;
823 2617 : if (ustr_sized(s1))
824 204 : *sz = ustr__sz_get(s1);
825 2617 : *osz = *sz;
826 :
827 2617 : lbytes = USTR__LEN_LEN(s1);
828 2617 : if (*sz)
829 204 : sbytes = lbytes;
830 1448 : USTR_ASSERT(!*sz || (ustr__nb(*sz) == lbytes) ||
831 : ((ustr__nb(*sz) == 1) && (lbytes == 2))); /* 2 is the minimum */
832 :
833 2617 : if (ustr__nb(nlen) > lbytes)
834 256 : return (USTR_FALSE); /* in theory we could do better, but it's _hard_ */
835 :
836 3542 : *oh = 1 + USTR__REF_LEN(s1) + lbytes + sbytes + sizeof(USTR_END_ALOCDx);
837 2361 : *nsz = *oh + nlen;
838 :
839 2361 : if (*nsz < nlen)
840 0 : return (USTR_FALSE);
841 : if (*nsz > USTR__SIZE_MAX) /* 32bit overflow on 64bit size_t */
842 : return (USTR_FALSE);
843 :
844 2361 : *alloc = USTR_FALSE; /* don't need to allocate/deallocate anything */
845 2361 : if (*nsz <= *sz)
846 172 : return (USTR_TRUE); /* ustr_sized() */
847 :
848 2189 : if (!ustr_exact(s1))
849 2113 : *nsz = ustr__ns(*nsz);
850 :
851 2189 : *osz = ustr_size_alloc(s1);
852 :
853 2189 : if (!*sz && (*nsz == *osz))
854 923 : return (USTR_TRUE);
855 :
856 1266 : *alloc = ustr_alloc(s1); /* _do_ need to deallocate */
857 1266 : if (!*sz && (*nsz <= *osz))
858 520 : return (USTR_TRUE);
859 :
860 746 : if (!*alloc)
861 12 : return (USTR_FALSE);
862 :
863 734 : return (USTR_TRUE);
864 : }
865 :
866 : /* NOTE: This is the main "deallocation" function (apart from plain free) --
867 : * this is one of only three things that removes data via. REALLOC.
868 : * Others are in ustr-set.h */
869 : USTR_CONF_i_PROTO
870 : int ustrp__del(struct Ustr_pool *p, struct Ustr **ps1, size_t len)
871 1026 : {
872 1026 : struct Ustr *s1 = USTR_NULL;
873 1026 : struct Ustr *ret = USTR_NULL;
874 1026 : size_t sz = 0;
875 1026 : size_t oh = 0;
876 1026 : size_t osz = 0;
877 1026 : size_t nsz = 0;
878 1026 : size_t clen = 0;
879 1026 : size_t nlen = 0;
880 1026 : int alloc = USTR_FALSE;
881 :
882 513 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
883 :
884 1026 : if (!len)
885 64 : return (USTR_TRUE);
886 :
887 962 : s1 = *ps1;
888 962 : clen = ustr_len(s1);
889 : /* under certain conditions, we can just return "" as it's much more efficient
890 : * and we don't get anything with not doing it. */
891 1746 : if (!(nlen = clen - len) && /* we are deleting everything */
892 : !(ustr_fixed(*ps1) || /* NOT in "free" space, or */
893 : (ustr_sized(*ps1) && ustr_owner(*ps1))) && /* sized with one ref. */
894 : ustr__dupx_cmp_eq(USTR__DUPX_DEF, USTR__DUPX_FROM(s1))) /* def. config. */
895 : {
896 244 : ustrp__sc_free2(p, ps1, USTR(""));
897 244 : return (USTR_TRUE);
898 : }
899 :
900 718 : if (nlen > clen) /* underflow */
901 4 : return (USTR_FALSE);
902 :
903 714 : if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc))
904 : {
905 690 : size_t eos_len = sizeof(USTR_END_ALOCDx);
906 :
907 690 : if (alloc)
908 : { /* ignore errors? -- can they happen on truncate? */
909 427 : int emem = ustr_enomem(*ps1);
910 :
911 201 : USTR_ASSERT(nsz < osz);
912 201 : USTR_ASSERT(!sz);
913 :
914 427 : if (!ustrp__rw_realloc(p, ps1, USTR_FALSE, osz, nsz))
915 : {
916 10 : if (!p)
917 : {
918 2 : ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(*ps1, osz));
919 4 : USTR__CNTL_MALLOC_CHECK_FIXUP_REALLOC(*ps1, nsz);
920 2 : ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(*ps1, nsz));
921 : }
922 :
923 21 : if (!emem)
924 21 : ustr_setf_enomem_clr(*ps1);
925 : }
926 : }
927 :
928 1035 : ustr__terminate((*ps1)->data, ustr_alloc(*ps1), (oh - eos_len) + nlen);
929 690 : ustr__len_set(*ps1, nlen);
930 :
931 345 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
932 690 : return (USTR_TRUE);
933 : }
934 :
935 12 : USTR_ASSERT(!ustr_limited(s1));
936 :
937 64 : if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen)))
938 : {
939 10 : ustr_setf_enomem_err(s1);
940 10 : return (USTR_FALSE);
941 : }
942 :
943 14 : ustr__memcpy(ret, 0, ustr_cstr(s1), nlen);
944 14 : ustrp__sc_free2(p, ps1, ret);
945 :
946 7 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
947 14 : return (USTR_TRUE);
948 : }
949 : USTR_CONF_I_PROTO int ustr_del(struct Ustr **ps1, size_t len)
950 80 : { return (ustrp__del(0, ps1, len)); }
951 : USTR_CONF_I_PROTO
952 : int ustrp_del(struct Ustr_pool *p, struct Ustrp **ps1, size_t len)
953 64 : {
954 64 : struct Ustr *tmp = &(*ps1)->s;
955 64 : int ret = ustrp__del(p, &tmp, len);
956 64 : *ps1 = USTRP(tmp);
957 64 : return (ret);
958 : }
959 :
960 : USTR_CONF_i_PROTO
961 : int ustrp__del_subustr(struct Ustr_pool *p,
962 : struct Ustr **ps1, size_t pos, size_t len)
963 212 : {
964 212 : struct Ustr *s1 = USTR_NULL;
965 212 : struct Ustr *ret = USTR_NULL;
966 212 : size_t sz = 0;
967 212 : size_t oh = 0;
968 212 : size_t osz = 0;
969 212 : size_t nsz = 0;
970 212 : size_t clen = 0;
971 212 : size_t nlen = 0;
972 212 : int alloc = USTR_FALSE;
973 212 : const char *ocstr = 0;
974 :
975 105 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
976 :
977 212 : if (!len)
978 48 : return (USTR_TRUE);
979 :
980 164 : s1 = *ps1;
981 164 : clen = ustrp__assert_valid_subustr(!!p, s1, pos, len);
982 164 : if (!clen)
983 2 : return (USTR_FALSE);
984 162 : if (--pos == (clen - len)) /* deleting from the end */
985 22 : return (ustrp__del(p, ps1, len));
986 :
987 140 : nlen = clen - len;
988 70 : USTR_ASSERT(nlen < clen);
989 :
990 140 : if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc))
991 : { /* Move everything to the begining and call ustr_del() */
992 128 : char *ptr = ustr_wstr(s1);
993 :
994 64 : USTR_ASSERT(nlen - pos);
995 :
996 128 : memmove(ptr + pos, ptr + pos + len, (nlen - pos));
997 :
998 128 : return (ustrp__del(p, ps1, len));
999 : }
1000 :
1001 6 : USTR_ASSERT(!ustr_limited(s1));
1002 :
1003 : /* Can't do anything sane, give up and build a new string from scratch */
1004 34 : if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen)))
1005 : {
1006 4 : ustr_setf_enomem_err(s1);
1007 4 : return (USTR_FALSE);
1008 : }
1009 :
1010 8 : ocstr = ustr_cstr(s1);
1011 :
1012 4 : USTR_ASSERT(pos || (nlen - pos)); /* can be both */
1013 :
1014 8 : ustr__memcpy(ret, 0, ocstr, pos);
1015 8 : ustr__memcpy(ret, pos, ocstr + pos + len, nlen - pos);
1016 :
1017 8 : ustrp__sc_free2(p, ps1, ret);
1018 :
1019 4 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
1020 8 : return (USTR_TRUE);
1021 : }
1022 : USTR_CONF_I_PROTO int ustr_del_subustr(struct Ustr **ps1, size_t pos,size_t len)
1023 56 : { return (ustrp__del_subustr(0, ps1, pos, len)); }
1024 : USTR_CONF_I_PROTO
1025 : int ustrp_del_subustrp(struct Ustr_pool *p,
1026 : struct Ustrp **ps1, size_t pos, size_t len)
1027 16 : {
1028 16 : struct Ustr *tmp = &(*ps1)->s;
1029 16 : int ret = ustrp__del_subustr(p, &tmp, pos, len);
1030 16 : *ps1 = USTRP(tmp);
1031 16 : return (ret);
1032 : }
1033 :
1034 : /* ---------------- dupx/dup ---------------- */
1035 :
1036 : USTR_CONF_I_PROTO struct Ustr *ustr_dupx_undef(size_t sz, size_t rbytes,
1037 : int exact, int emem, size_t len)
1038 130 : { return (ustrp__dupx_undef(0, sz, rbytes, exact, emem, len)); }
1039 : USTR_CONF_I_PROTO
1040 : struct Ustrp *ustrp_dupx_undef(struct Ustr_pool *p, size_t sz, size_t rbytes,
1041 : int exact, int emem, size_t len)
1042 196 : { return (USTRP(ustrp__dupx_undef(p, sz, rbytes, exact, emem, len))); }
1043 :
1044 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_undef(size_t len)
1045 124 : { return (ustr_dupx_undef(USTR__DUPX_DEF, len)); }
1046 :
1047 : USTR_CONF_I_PROTO struct Ustrp *ustrp_dup_undef(struct Ustr_pool *p, size_t len)
1048 225 : { return (ustrp_dupx_undef(p, USTR__DUPX_DEF, len)); }
1049 :
1050 : USTR_CONF_i_PROTO
1051 : struct Ustr *ustrp__dupx_empty(struct Ustr_pool *p, size_t sz, size_t rbytes,
1052 : int exact, int emem)
1053 102 : { /* set the error bit, so we always get malloc()'d data, then clear it */
1054 102 : struct Ustr *s1 = ustrp__dupx_undef(p, sz, rbytes, exact, USTR_TRUE, 0);
1055 102 : int eret = USTR_FALSE;
1056 :
1057 102 : if (!s1 || emem)
1058 10 : return (s1);
1059 :
1060 92 : eret = ustr_setf_enomem_clr(s1);
1061 46 : USTR_ASSERT(eret);
1062 :
1063 92 : return (s1);
1064 : }
1065 : USTR_CONF_I_PROTO struct Ustr *ustr_dupx_empty(size_t sz, size_t rbytes,
1066 : int exact, int emem)
1067 28 : { return (ustrp__dupx_empty(0, sz, rbytes, exact, emem)); }
1068 : USTR_CONF_I_PROTO
1069 : struct Ustrp *ustrp_dupx_empty(struct Ustr_pool *p, size_t sz, size_t rbytes,
1070 : int exact, int emem)
1071 30 : { return (USTRP(ustrp__dupx_empty(p, sz, rbytes, exact, emem))); }
1072 :
1073 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_empty(void)
1074 8 : { return (ustr_dupx_empty(USTR__DUPX_DEF)); }
1075 :
1076 : USTR_CONF_I_PROTO struct Ustrp *ustrp_dup_empty(struct Ustr_pool *p)
1077 17 : { return (ustrp_dupx_empty(p, USTR__DUPX_DEF)); }
1078 :
1079 : USTR_CONF_i_PROTO
1080 : struct Ustr *ustrp__dupx_buf(struct Ustr_pool *p, size_t sz, size_t rbytes,
1081 : int exact, int emem, const void *data, size_t len)
1082 1130 : {
1083 1130 : struct Ustr *s1 = ustrp__dupx_undef(p, sz, rbytes, exact, emem, len);
1084 :
1085 1130 : if (!s1)
1086 76 : return (USTR_NULL);
1087 :
1088 1054 : ustr__memcpy(s1, 0, data, len);
1089 :
1090 527 : USTR_ASSERT(ustrp__assert_valid(!!p, s1));
1091 1054 : return (s1);
1092 : }
1093 : USTR_CONF_I_PROTO
1094 : struct Ustr *ustr_dupx_buf(size_t sz, size_t rb, int exact,
1095 : int emem, const void *data, size_t len)
1096 152 : { return (ustrp__dupx_buf(0, sz, rb, exact, emem, data, len)); }
1097 : USTR_CONF_I_PROTO
1098 : struct Ustrp *ustrp_dupx_buf(struct Ustr_pool *p, size_t sz, size_t rb,
1099 : int exact, int emem, const void *data, size_t len)
1100 36 : { return (USTRP(ustrp__dupx_buf(p, sz, rb, exact, emem, data, len))); }
1101 :
1102 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_buf(const void *data, size_t len)
1103 140 : { return (ustr_dupx_buf(USTR__DUPX_DEF, data, len)); }
1104 : USTR_CONF_I_PROTO
1105 : struct Ustrp *ustrp_dup_buf(struct Ustr_pool *p, const void *data, size_t len)
1106 25 : { return (USTRP(ustrp_dupx_buf(p, USTR__DUPX_DEF, data, len))); }
1107 :
1108 : USTR_CONF_i_PROTO
1109 : struct Ustr *ustrp__dup(struct Ustr_pool *p, const struct Ustr *s1)
1110 1329921 : { /* This ignores the const argument, because it doesn't alter the data, or at
1111 : * all when ustr_ro(). */
1112 533347 : ustr_assert(USTR__ASSERT_MALLOC_CHECK_MEM(p, s1));
1113 :
1114 1329921 : if (ustr__ref_add((struct Ustr *)s1))
1115 1329875 : return ((struct Ustr *)s1);
1116 :
1117 142 : return (ustrp__dupx_buf(p, USTR__DUPX_FROM(s1), ustr_cstr(s1), ustr_len(s1)));
1118 : }
1119 : USTR_CONF_I_PROTO struct Ustr *ustr_dup(const struct Ustr *s1)
1120 1067684 : { return (ustrp__dup(0, s1)); }
1121 : USTR_CONF_I_PROTO
1122 : struct Ustrp *ustrp_dup(struct Ustr_pool *p, const struct Ustrp *s1)
1123 24 : { return (USTRP(ustrp__dup(p, &s1->s))); }
1124 :
1125 : USTR_CONF_i_PROTO
1126 : struct Ustr *ustrp__dupx(struct Ustr_pool *p, size_t sz, size_t rbytes,
1127 : int exact, int emem, const struct Ustr *s1)
1128 262260 : { /* the exactneustr of the options is more important than the reference */
1129 131130 : USTR_ASSERT((rbytes == 0) || (rbytes == 1) || (rbytes == 2) || (rbytes == 4)||
1130 : (USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)));
1131 131130 : USTR_ASSERT(exact == !!exact);
1132 131130 : USTR_ASSERT(emem == !!emem);
1133 :
1134 655682 : if (ustr__dupx_cmp_eq(sz, rbytes, exact, emem, USTR__DUPX_FROM(s1)))
1135 262196 : return (ustrp__dup(p, s1));
1136 :
1137 64 : return (ustrp__dupx_buf(p, sz,rbytes,exact,emem, ustr_cstr(s1),ustr_len(s1)));
1138 : }
1139 : USTR_CONF_I_PROTO struct Ustr *ustr_dupx(size_t sz, size_t rbytes, int exact,
1140 : int emem, const struct Ustr *s1)
1141 262156 : { return (ustrp__dupx(0, sz, rbytes, exact, emem, s1)); }
1142 : USTR_CONF_I_PROTO
1143 : struct Ustrp *ustrp_dupx(struct Ustr_pool *p, size_t sz, size_t rbytes,
1144 : int exact, int emem, const struct Ustrp *s1)
1145 8 : { return (USTRP(ustrp__dupx(p, sz, rbytes, exact, emem, &s1->s))); }
1146 :
1147 : USTR_CONF_i_PROTO
1148 : struct Ustr *ustrp__dupx_subustr(struct Ustr_pool *p,
1149 : size_t sz, size_t rbytes, int exact, int emem,
1150 : const struct Ustr *s2, size_t pos, size_t len)
1151 184 : {
1152 184 : size_t clen = 0;
1153 :
1154 86 : USTR_ASSERT(ustrp__assert_valid(!!p, s2));
1155 86 : USTR_ASSERT(pos);
1156 :
1157 184 : if (!len)
1158 12 : return (ustrp__dupx_undef(p, sz, rbytes, exact, emem, len));
1159 :
1160 172 : clen = ustrp__assert_valid_subustr(!!p, s2, pos, len);
1161 172 : if (!clen)
1162 12 : return (USTR_NULL);
1163 160 : if (len == clen)
1164 20 : return (ustrp__dupx(p, sz, rbytes, exact, emem, s2));
1165 :
1166 140 : return (ustrp__dupx_buf(p,sz,rbytes,exact,emem, ustr_cstr(s2) + --pos, len));
1167 : }
1168 : USTR_CONF_I_PROTO
1169 : struct Ustr *ustr_dupx_subustr(size_t sz, size_t rbytes, int exact, int emem,
1170 : const struct Ustr *s2, size_t pos, size_t len)
1171 8 : { return (ustrp__dupx_subustr(0, sz, rbytes, exact, emem, s2, pos, len)); }
1172 : USTR_CONF_I_PROTO
1173 : struct Ustrp *ustrp_dupx_subustrp(struct Ustr_pool *p,
1174 : size_t sz, size_t rbytes, int exact, int emem,
1175 : const struct Ustrp *s2, size_t pos,size_t len)
1176 40 : { return (USTRP(ustrp__dupx_subustr(p, sz, rbytes, exact, emem,
1177 : &s2->s, pos, len))); }
1178 :
1179 : USTR_CONF_i_PROTO
1180 : struct Ustr *ustrp__dup_subustr(struct Ustr_pool *p, const struct Ustr *s2,
1181 : size_t pos, size_t len)
1182 418 : { return (ustrp__dupx_subustr(p, USTR__DUPX_FROM(s2), s2, pos, len)); }
1183 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_subustr(const struct Ustr *s2,
1184 : size_t pos, size_t len)
1185 4 : { return (ustrp__dup_subustr(0, s2, pos, len)); }
1186 : USTR_CONF_I_PROTO
1187 : struct Ustrp *ustrp_dup_subustrp(struct Ustr_pool *p, const struct Ustrp *s2,
1188 : size_t pos, size_t len)
1189 8 : { return (USTRP(ustrp__dup_subustr(p, &s2->s, pos, len))); }
1190 :
1191 : USTR_CONF_i_PROTO
1192 : struct Ustr *ustrp__dupx_rep_chr(struct Ustr_pool *p,
1193 : size_t sz, size_t rbytes, int exact, int emem,
1194 : char chr, size_t len)
1195 24 : {
1196 24 : struct Ustr *s1 = ustrp__dupx_undef(p, sz, rbytes, exact, emem, len);
1197 :
1198 24 : if (!s1)
1199 8 : return (USTR_NULL);
1200 :
1201 16 : if (len)
1202 16 : ustr__memset(s1, 0, chr, len);
1203 :
1204 8 : USTR_ASSERT(ustrp__assert_valid(!!p, s1));
1205 16 : return (s1);
1206 : }
1207 : USTR_CONF_I_PROTO
1208 : struct Ustr *ustr_dupx_rep_chr(size_t sz, size_t rbytes, int exact, int emem,
1209 : char chr, size_t len)
1210 4 : { return (ustrp__dupx_rep_chr(0, sz, rbytes, exact, emem, chr, len)); }
1211 : USTR_CONF_I_PROTO
1212 : struct Ustrp *ustrp_dupx_rep_chr(struct Ustr_pool *p,
1213 : size_t sz, size_t rbytes, int exact, int emem,
1214 : char chr, size_t len)
1215 20 : { return (USTRP(ustrp__dupx_rep_chr(p, sz, rbytes, exact, emem, chr, len))); }
1216 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_rep_chr(char chr, size_t len)
1217 4 : { return (ustr_dupx_rep_chr(USTR__DUPX_DEF, chr, len)); }
1218 : USTR_CONF_I_PROTO
1219 : struct Ustrp *ustrp_dup_rep_chr(struct Ustr_pool *p, char chr, size_t len)
1220 15 : { return (ustrp_dupx_rep_chr(p, USTR__DUPX_DEF, chr, len)); }
1221 :
1222 : /* ---------------- add ---------------- */
1223 :
1224 : /* NOTE: This is one of the two main "allocation" functions --
1225 : * this is one of three things funcs that gets more data via. REALLOC.
1226 : * Others are in ustr-set.h */
1227 : USTR_CONF_i_PROTO
1228 : int ustrp__add_undef(struct Ustr_pool *p, struct Ustr **ps1, size_t len)
1229 1602 : {
1230 1602 : struct Ustr *s1 = USTR_NULL;
1231 1602 : struct Ustr *ret = USTR_NULL;
1232 1602 : size_t clen = 0;
1233 1602 : size_t nlen = 0;
1234 1602 : size_t sz = 0;
1235 1602 : size_t oh = 0;
1236 1602 : size_t osz = 0;
1237 1602 : size_t nsz = 0;
1238 1602 : int alloc = USTR_FALSE;
1239 :
1240 819 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
1241 :
1242 1602 : if (!len)
1243 1 : return (USTR_TRUE);
1244 :
1245 1601 : s1 = *ps1;
1246 1601 : clen = ustr_len(s1);
1247 1601 : if ((nlen = clen + len) < clen) /* overflow */
1248 4 : goto fail_enomem;
1249 :
1250 1597 : if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc))
1251 : {
1252 1157 : size_t eos_len = sizeof(USTR_END_ALOCDx);
1253 :
1254 1157 : if (alloc && !ustrp__rw_realloc(p, ps1, !!sz, osz, nsz))
1255 42 : return (USTR_FALSE);
1256 1673 : ustr__terminate((*ps1)->data, ustr_alloc(*ps1), (oh - eos_len) + nlen);
1257 1115 : ustr__len_set(*ps1, nlen);
1258 :
1259 558 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
1260 1115 : return (USTR_TRUE);
1261 : }
1262 :
1263 440 : if (ustr_limited(s1))
1264 : {
1265 4 : ustr_setf_enomem_err(s1);
1266 4 : return (USTR_FALSE);
1267 : }
1268 :
1269 1282 : if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen)))
1270 138 : goto fail_enomem;
1271 :
1272 298 : ustr__memcpy(ret, 0, ustr_cstr(s1), ustr_len(s1));
1273 298 : ustrp__sc_free2(p, ps1, ret);
1274 :
1275 149 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
1276 298 : return (USTR_TRUE);
1277 :
1278 142 : fail_enomem:
1279 142 : ustr_setf_enomem_err(s1);
1280 142 : return (USTR_FALSE);
1281 : }
1282 : USTR_CONF_I_PROTO int ustr_add_undef(struct Ustr **ps1, size_t len)
1283 120 : { return (ustrp__add_undef(0, ps1, len)); }
1284 : USTR_CONF_I_PROTO
1285 : int ustrp_add_undef(struct Ustr_pool *p, struct Ustrp **ps1, size_t len)
1286 4 : {
1287 4 : struct Ustr *tmp = &(*ps1)->s;
1288 4 : int ret = ustrp__add_undef(p, &tmp, len);
1289 4 : *ps1 = USTRP(tmp);
1290 4 : return (ret);
1291 : }
1292 :
1293 : USTR_CONF_i_PROTO int ustrp__add_buf(struct Ustr_pool *p, struct Ustr **ps1,
1294 : const void *s2, size_t len)
1295 564 : {
1296 564 : if (!ustrp__add_undef(p, ps1, len))
1297 14 : return (USTR_FALSE);
1298 :
1299 550 : ustr__memcpy(*ps1, ustr_len(*ps1) - len, s2, len);
1300 :
1301 550 : return (USTR_TRUE);
1302 : }
1303 : USTR_CONF_I_PROTO int ustr_add_buf(struct Ustr **ps1, const void *s2,size_t len)
1304 228 : { return (ustrp__add_buf(0, ps1, s2, len)); }
1305 : USTR_CONF_I_PROTO int ustrp_add_buf(struct Ustr_pool *p, struct Ustrp **ps1,
1306 : const void *s2, size_t len)
1307 224 : {
1308 224 : struct Ustr *tmp = &(*ps1)->s;
1309 224 : int ret = ustrp__add_buf(p, &tmp, s2, len);
1310 224 : *ps1 = USTRP(tmp);
1311 224 : return (ret);
1312 : }
1313 :
1314 : /* If we can use _dup(), otherwise just pretend it's a buf+len */
1315 : USTR_CONF_i_PROTO
1316 : int ustr__treat_as_buf(const struct Ustr *s1, size_t len1, size_t len2)
1317 144 : {
1318 72 : USTR_ASSERT(!len1 || (len1 == ustr_len(s1))); /* set() uses 0 */
1319 72 : USTR_ASSERT((len1 < (len1 + len2)) || !len2); /* no overflow allowed */
1320 :
1321 144 : if (len1)
1322 60 : return (USTR_TRUE);
1323 :
1324 84 : if (ustr_limited(s1))
1325 4 : return (USTR_TRUE);
1326 :
1327 80 : if (ustr_owner(s1) && (ustr_size(s1) >= len2))
1328 20 : return (USTR_TRUE);
1329 :
1330 60 : return (USTR_FALSE);
1331 : }
1332 :
1333 : USTR_CONF_i_PROTO
1334 : int ustrp__add(struct Ustr_pool *p, struct Ustr **ps1, const struct Ustr *s2)
1335 161 : {
1336 161 : struct Ustr *ret = USTR_NULL;
1337 161 : size_t len1 = 0;
1338 161 : size_t len2 = 0;
1339 :
1340 80 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
1341 80 : USTR_ASSERT(ustrp__assert_valid(!!p, s2));
1342 :
1343 161 : len1 = ustr_len(*ps1);
1344 161 : len2 = ustr_len(s2);
1345 :
1346 161 : if (len1 > (len1 + len2))
1347 : {
1348 1 : errno = USTR__ENOMEM;
1349 1 : return (USTR_FALSE);
1350 : }
1351 :
1352 160 : if (!len2)
1353 12 : return (USTR_TRUE);
1354 :
1355 176 : if ((*ps1 == s2) && ustr_owner(s2) && ustr_alloc(s2))
1356 : { /* only one reference, so we can't take _cstr() before we realloc */
1357 56 : if (!ustrp__add_undef(p, ps1, len1))
1358 6 : return (USTR_FALSE);
1359 :
1360 50 : ustr__memcpy(*ps1, len1, ustr_cstr(*ps1), len1);
1361 :
1362 25 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
1363 50 : return (USTR_TRUE);
1364 : }
1365 :
1366 92 : if (ustr__treat_as_buf(*ps1, len1, len2))
1367 68 : return (ustrp__add_buf(p, ps1, ustr_cstr(s2), len2));
1368 :
1369 12 : USTR_ASSERT(!len1);
1370 :
1371 94 : if (!(ret = ustrp__dupx(p, USTR__DUPX_FROM(*ps1), s2)))
1372 : {
1373 4 : ustr_setf_enomem_err(*ps1);
1374 4 : return (USTR_FALSE);
1375 : }
1376 :
1377 20 : ustrp__sc_free2(p, ps1, ret);
1378 20 : return (USTR_TRUE);
1379 : }
1380 : USTR_CONF_I_PROTO int ustr_add(struct Ustr **ps1, const struct Ustr *s2)
1381 53 : { return (ustrp__add(0, ps1, s2)); }
1382 : USTR_CONF_I_PROTO
1383 : int ustrp_add(struct Ustr_pool *p, struct Ustrp **ps1, const struct Ustrp *s2)
1384 80 : {
1385 80 : struct Ustr *tmp = &(*ps1)->s;
1386 80 : int ret = ustrp__add(p, &tmp, &s2->s);
1387 80 : *ps1 = USTRP(tmp);
1388 80 : return (ret);
1389 : }
1390 :
1391 : USTR_CONF_i_PROTO
1392 : int ustrp__add_subustr(struct Ustr_pool *p, struct Ustr **ps1,
1393 : const struct Ustr *s2, size_t pos, size_t len)
1394 70 : {
1395 70 : size_t clen = 0;
1396 :
1397 30 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
1398 30 : USTR_ASSERT(ustrp__assert_valid(!!p, s2));
1399 30 : USTR_ASSERT(pos);
1400 :
1401 70 : if (!len)
1402 0 : return (USTR_TRUE);
1403 :
1404 70 : clen = ustrp__assert_valid_subustr(!!p, s2, pos, len);
1405 70 : if (!clen)
1406 10 : return (USTR_FALSE);
1407 60 : if (len == clen)
1408 8 : return (ustrp__add(p, ps1, s2));
1409 :
1410 52 : if (*ps1 != s2)
1411 28 : return (ustrp__add_buf(p, ps1, ustr_cstr(s2) + pos - 1, len));
1412 :
1413 : /* maybe only one reference, so we can't take _cstr() before we realloc */
1414 24 : if (!ustrp__add_undef(p, ps1, len))
1415 4 : return (USTR_FALSE);
1416 :
1417 20 : ustr__memcpy(*ps1, clen, ustr_cstr(*ps1) + pos - 1, len);
1418 :
1419 20 : return (USTR_TRUE);
1420 : }
1421 : USTR_CONF_I_PROTO int ustr_add_subustr(struct Ustr **ps1, const struct Ustr *s2,
1422 : size_t pos, size_t len)
1423 8 : { return (ustrp__add_subustr(0, ps1, s2, pos, len)); }
1424 : USTR_CONF_I_PROTO
1425 : int ustrp_add_subustrp(struct Ustr_pool *p, struct Ustrp **ps1,
1426 : const struct Ustrp *s2, size_t pos, size_t len)
1427 50 : {
1428 50 : struct Ustr *tmp = &(*ps1)->s;
1429 50 : int ret = ustrp__add_subustr(p, &tmp, &s2->s, pos, len);
1430 50 : *ps1 = USTRP(tmp);
1431 50 : return (ret);
1432 : }
1433 :
1434 : USTR_CONF_i_PROTO int ustrp__add_rep_chr(struct Ustr_pool *p, struct Ustr **ps1,
1435 : char chr, size_t len)
1436 44 : {
1437 44 : if (!ustrp__add_undef(p, ps1, len))
1438 8 : return (USTR_FALSE);
1439 :
1440 36 : ustr__memset(*ps1, ustr_len(*ps1) - len, chr, len);
1441 :
1442 36 : return (USTR_TRUE);
1443 : }
1444 : USTR_CONF_I_PROTO int ustr_add_rep_chr(struct Ustr **ps1, char chr, size_t len)
1445 24 : { return (ustrp__add_rep_chr(0, ps1, chr, len)); }
1446 : USTR_CONF_I_PROTO int ustrp_add_rep_chr(struct Ustr_pool *p, struct Ustrp **ps1,
1447 : char chr, size_t len)
1448 20 : {
1449 20 : struct Ustr *tmp = &(*ps1)->s;
1450 20 : int ret = ustrp__add_rep_chr(p, &tmp, chr, len);
1451 20 : *ps1 = USTRP(tmp);
1452 20 : return (ret);
1453 : }
1454 :
1455 : /* ---------------- shortcut ---------------- */
1456 :
1457 : USTR_CONF_I_PROTO void ustr_sc_free2(struct Ustr **ps1, struct Ustr *s2)
1458 250 : { ustrp__sc_free2(0, ps1, s2); }
1459 : USTR_CONF_I_PROTO void ustrp_sc_free2(struct Ustr_pool *p,
1460 : struct Ustrp **ps1, struct Ustrp *s2)
1461 52 : {
1462 52 : struct Ustr *tmp = &(*ps1)->s;
1463 52 : ustrp__sc_free2(p, &tmp, &s2->s);
1464 52 : *ps1 = USTRP(tmp);
1465 52 : }
1466 :
1467 : USTR_CONF_i_PROTO void ustrp__sc_free(struct Ustr_pool *p, struct Ustr **ps1)
1468 702 : {
1469 351 : USTR_ASSERT(ps1);
1470 :
1471 702 : ustrp__free(p, *ps1);
1472 702 : *ps1 = USTR_NULL;
1473 702 : }
1474 : USTR_CONF_I_PROTO void ustr_sc_free(struct Ustr **ps1)
1475 682 : { ustrp__sc_free(0, ps1); }
1476 : USTR_CONF_I_PROTO void ustrp_sc_free(struct Ustr_pool *p, struct Ustrp **ps1)
1477 16 : {
1478 16 : struct Ustr *tmp = &(*ps1)->s;
1479 16 : ustrp__sc_free(p, &tmp);
1480 16 : *ps1 = USTRP(tmp);
1481 16 : }
1482 :
1483 : USTR_CONF_i_PROTO void ustrp__sc_del(struct Ustr_pool *p, struct Ustr **ps1)
1484 224 : {
1485 224 : if (!ustrp__del(p, ps1, ustr_len(*ps1)))
1486 : /* Very unlikely, but in this case ignore saving the options/data.
1487 : * We can be a little less efficient etc., but no error handling is nice.
1488 : * Only thing you have to watch for is ustr_enomem() might not "work"
1489 : * after a call to here. */
1490 4 : ustrp__sc_free2(p, ps1, USTR(""));
1491 :
1492 112 : USTR_ASSERT(!ustr_len(*ps1));
1493 224 : }
1494 : USTR_CONF_I_PROTO void ustr_sc_del(struct Ustr **ps1)
1495 160 : { ustrp__sc_del(0, ps1); }
1496 : USTR_CONF_I_PROTO void ustrp_sc_del(struct Ustr_pool *p, struct Ustrp **ps1)
1497 36 : {
1498 36 : struct Ustr *tmp = &(*ps1)->s;
1499 36 : ustrp__sc_del(p, &tmp);
1500 36 : *ps1 = USTRP(tmp);
1501 36 : }
1502 :
1503 : USTR_CONF_I_PROTO
1504 : void ustr_conf(const struct Ustr *s1, size_t *ret_esz, size_t *ret_ref,
1505 : int *ret_exact, size_t *ret_lenn, size_t *ret_refc)
1506 396 : {
1507 396 : size_t esz = 0;
1508 396 : size_t ref = 0;
1509 396 : int exact = 0;
1510 396 : size_t refc = 0;
1511 :
1512 198 : USTR_ASSERT(ustr_assert_valid(s1));
1513 :
1514 396 : if (!ustr_alloc(s1))
1515 : {
1516 176 : esz = USTR_CONF_HAS_SIZE;
1517 176 : ref = USTR_CONF_REF_BYTES;
1518 176 : exact = USTR_CONF_EXACT_BYTES;
1519 : }
1520 : else
1521 : {
1522 220 : if (ustr_sized(s1))
1523 12 : esz = ustr__sz_get(s1);
1524 : else
1525 208 : esz = 0;
1526 :
1527 220 : ref = USTR__REF_LEN(s1);
1528 110 : exact = ustr_exact(s1);
1529 220 : refc = !!ref;
1530 : }
1531 :
1532 880 : USTR_ASSERT(ustr__dupx_cmp_eq(USTR__DUPX_FROM(s1),
1533 : esz, ref, exact, ustr_enomem(s1)));
1534 :
1535 396 : if (ret_esz) *ret_esz = esz;
1536 396 : if (ret_ref) *ret_ref = ref;
1537 396 : if (ret_exact) *ret_exact = exact;
1538 :
1539 495 : if (ret_lenn) *ret_lenn = USTR__LEN_LEN(s1);
1540 396 : if (ret_refc) *ret_refc = refc ? ustr_xi__ref_get(s1) : 0;
1541 396 : }
1542 :
1543 : USTR_CONF_i_PROTO
1544 : int ustrp__sc_ensure_owner(struct Ustr_pool *p, struct Ustr **ps1)
1545 1024 : {
1546 1024 : struct Ustr *ret = USTR_NULL;
1547 1024 : size_t clen = 0;
1548 :
1549 512 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
1550 :
1551 1024 : if (ustr_owner(*ps1))
1552 824 : return (USTR_TRUE);
1553 :
1554 200 : if (!(clen = ustr_len(*ps1))) /* so ustr_enomem() and ustr_wstr() work */
1555 76 : ret = ustrp__dupx_empty(p, USTR__DUPX_FROM(*ps1));
1556 : else
1557 713 : ret = ustrp__dupx_buf(p, USTR__DUPX_FROM(*ps1), ustr_cstr(*ps1), clen);
1558 :
1559 200 : if (!ret)
1560 34 : return (USTR_FALSE);
1561 :
1562 166 : ustrp__sc_free2(p, ps1, ret);
1563 :
1564 166 : return (USTR_TRUE);
1565 : }
1566 : USTR_CONF_I_PROTO int ustr_sc_ensure_owner(struct Ustr **ps1)
1567 96 : { return (ustrp__sc_ensure_owner(0, ps1)); }
1568 : USTR_CONF_I_PROTO
1569 : int ustrp_sc_ensure_owner(struct Ustr_pool *p, struct Ustrp **ps1)
1570 20 : {
1571 20 : struct Ustr *tmp = &(*ps1)->s;
1572 20 : int ret = ustrp__sc_ensure_owner(p, &tmp);
1573 20 : *ps1 = USTRP(tmp);
1574 20 : return (ret);
1575 : }
1576 :
1577 : USTR_CONF_i_PROTO char *ustrp__sc_wstr(struct Ustr_pool *p, struct Ustr **ps1)
1578 82 : {
1579 82 : if (!ustrp__sc_ensure_owner(p, ps1))
1580 14 : return (USTR_FALSE);
1581 :
1582 68 : return (ustr_wstr(*ps1));
1583 : }
1584 : USTR_CONF_I_PROTO char *ustr_sc_wstr(struct Ustr **ps1)
1585 8 : { return (ustrp__sc_wstr(0, ps1)); }
1586 : USTR_CONF_I_PROTO char *ustrp_sc_wstr(struct Ustr_pool *p, struct Ustrp **ps1)
1587 10 : {
1588 10 : struct Ustr *tmp = &(*ps1)->s;
1589 10 : char *ret = ustrp__sc_wstr(p, &tmp);
1590 10 : *ps1 = USTRP(tmp);
1591 10 : return (ret);
1592 : }
|