1 : /* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */
2 : #ifndef USTR_MAIN_H
3 : #define USTR_MAIN_H 1
4 :
5 : /* This header file is a few functions for a "simple string" ADT. The idea is
6 : * that it's so simple you can just copy this header into your project and go.
7 : * There are extra functions in various ustr-*.h files
8 : * If you require more, see Vstr etc. */
9 :
10 : /* ---- BEG: always static config. ---- */
11 :
12 : #ifndef USTR_CONF_HAVE_STDINT_H
13 : #define USTR_CONF_HAVE_STDINT_H 0
14 : #endif
15 :
16 : #include <stdlib.h> /* size_t */
17 : #include <string.h> /* strlen() / etc. */
18 : #if USTR_CONF_HAVE_STDINT_H
19 : # include <stdint.h> /* SIZE_MAX */
20 : # define USTR__SIZE_MAX SIZE_MAX
21 : #else
22 : # define USTR__SIZE_MAX ((size_t)-1)
23 : #endif
24 : #include <limits.h> /* CHAR_BIT */
25 :
26 : #include <stdarg.h> /* va_list for *printf like functionality,
27 : * needed globally now due to cntl and concat */
28 : #include <stdio.h> /* vsnprintf */
29 :
30 : #define USTR_FALSE 0
31 : #define USTR_TRUE 1
32 : #define USTR_NULL ((struct Ustr *) 0)
33 : #define USTRP_NULL ((struct Ustrp *)0)
34 : #define USTR_POOL_NULL ((struct Ustr_pool *)0)
35 :
36 : #ifndef USTR_CONF_USE_ASSERT /* Really defined in ustr-conf.h */
37 : #define USTR_CONF_USE_ASSERT 0
38 : #endif
39 :
40 : #if !defined(ustr_assert) || !defined(USTR_ASSERT) || \
41 : !defined(ustr_assert_ret) || !defined(USTR_ASSERT_RET)
42 :
43 : # undef ustr_assert
44 : # undef USTR_ASSERT
45 : # undef ustr_assert_ret
46 : # undef USTR_ASSERT_RET
47 :
48 : # if USTR_CONF_USE_ASSERT
49 : # include <assert.h>
50 :
51 : # define ustr_assert(x) assert(x)
52 : # define USTR_ASSERT(x) assert(x)
53 : # define ustr_assert_ret(x, y) assert(x)
54 : # define USTR_ASSERT_RET(x, y) assert(x)
55 : # else
56 : # define ustr_assert(x) /* nothing */
57 : # define USTR_ASSERT(x) /* nothing */
58 : # define ustr_assert_ret(x, y) \
59 : do { if (x){} else return (y); } while (USTR_FALSE)
60 : # define USTR_ASSERT_RET(x, y) \
61 : do { if (x){} else return (y); } while (USTR_FALSE)
62 : # endif
63 : #endif
64 :
65 : #undef USTR_ASSERT_NO_SWITCH_DEF
66 : #if USTR_CONF_USE_ASSERT
67 : #define USTR_ASSERT_NO_SWITCH_DEF(x) break; default: USTR_ASSERT(! "" x)
68 : #else
69 : #define USTR_ASSERT_NO_SWITCH_DEF(x) break
70 : #endif
71 :
72 : #ifndef USTR_CONF_USE_EOS_MARK /* include an "end of string" mark */
73 : #define USTR_CONF_USE_EOS_MARK 0
74 : #endif
75 :
76 : #ifndef USTR_CONF_COMPILE_TYPEDEF /* include a typedef for Ustr */
77 : #define USTR_CONF_COMPILE_TYPEDEF 1
78 : #endif
79 :
80 : #ifndef USTR_CONF_INCLUDE_CODEONLY_HEADERS /* include headers which are .c's */
81 : #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1
82 : #endif
83 :
84 : #ifndef USTR_CONF_INCLUDE_INTERNAL_HEADERS /* internal functions */
85 : # if USTR_CONF_INCLUDE_CODEONLY_HEADERS
86 : #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1
87 : #else
88 : #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 0
89 : #endif
90 : #endif
91 :
92 : #ifndef USTR_CONF_COMPILE_USE_ATTRIBUTES /* GCC attributes, for speed/warns */
93 : #define USTR_CONF_COMPILE_USE_ATTRIBUTES 1
94 : #endif
95 :
96 : #ifndef USTR_CONF_COMPILE_USE_INLINE /* have very small functions inline? */
97 : #define USTR_CONF_COMPILE_USE_INLINE 1
98 : #endif
99 :
100 : #include "ustr-compiler.h"
101 :
102 : #ifndef USTR_CONF_USE_DYNAMIC_CONF /* make some _CONF settings into variables */
103 : # if ! USTR_CONF_INCLUDE_CODEONLY_HEADERS && USTR_CONF_HAVE_DYNAMIC_CONF
104 : #define USTR_CONF_USE_DYNAMIC_CONF 1
105 : # else
106 : #define USTR_CONF_USE_DYNAMIC_CONF 0
107 : # endif
108 : #endif
109 : /* ---- END: always static config. ---- */
110 :
111 : #if USTR_CONF_USE_DYNAMIC_CONF
112 : # if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
113 : (defined(__GNUC__) && (__GNUC__ > 3) && !defined(__STRICT_ANSI__))
114 : # define USTR_CNTL_MALLOC_CHECK_BEG(x) ((x) ? \
115 : ustr_cntl_opt(666, 0x0FF0, __FILE__, (unsigned int)__LINE__, __func__) : \
116 : USTR_FALSE)
117 : # else
118 : # define USTR_CNTL_MALLOC_CHECK_BEG(x) ((x) ? \
119 : ustr_cntl_opt(666, 0x0FF0, __FILE__, (unsigned int)__LINE__, "") : \
120 : USTR_FALSE)
121 : # endif
122 : # define USTR_CNTL_MALLOC_CHECK_LVL() ustr_cntl_opt(666, 0x0FFE)
123 : # define USTR_CNTL_MALLOC_CHECK_MEM(x) ustr_cntl_opt(666, 0x0FF1, x)
124 : # define USTR_CNTL_MALLOC_CHECK_MEM_SZ(x, y) ustr_cntl_opt(666, 0x0FF2, x, y)
125 : # define USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(x, y) ustr_cntl_opt(666, 0x0FF3, x, y)
126 : # define USTR_CNTL_MALLOC_CHECK_MEM_USTR(s1) (!ustr_alloc(s1) || \
127 : USTR_CNTL_MALLOC_CHECK_MEM_SZ(s1, ustr_size_alloc(s1)))
128 : # define USTR_CNTL_MALLOC_CHECK_MEM_USTRP(sp1) (!ustrp_alloc(sp1) || \
129 : USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(sp1, ustrp_size_alloc(sp1)))
130 :
131 : # if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
132 : (defined(__GNUC__) && (__GNUC__ > 3) && !defined(__STRICT_ANSI__))
133 : # define USTR_CNTL_MALLOC_CHECK_END() \
134 : ustr_cntl_opt(666, 0x0FFF, __FILE__, (unsigned int)__LINE__, __func__)
135 : # else
136 : # define USTR_CNTL_MALLOC_CHECK_END() \
137 : ustr_cntl_opt(666, 0x0FFF, __FILE__, (unsigned int)__LINE__, "")
138 : # endif
139 :
140 : # define USTR_CNTL_MALLOC_CHECK_ADD(x) \
141 : (((x) && USTR_CNTL_MALLOC_CHECK_LVL()) ? \
142 : USTR_CNTL_MALLOC_CHECK_BEG(USTR_TRUE) : USTR_FALSE)
143 : # define USTR_CNTL_MALLOC_CHECK_DEL(x) \
144 : (((x) && USTR_CNTL_MALLOC_CHECK_LVL() > 1) ? \
145 : USTR_CNTL_MALLOC_CHECK_END() : USTR_FALSE)
146 :
147 : # define USTR__CNTL_MALLOC_CHECK_FIXUP_REALLOC(x, y) \
148 : (void) ustr_cntl_opt(666, 0x0FF4, x, y)
149 :
150 : # include "ustr-cntl.h"
151 : #else
152 : # define USTR_CNTL_MALLOC_CHECK_BEG(USTR_TRUE) (USTR_FALSE)
153 : # define USTR_CNTL_MALLOC_CHECK_LVL() (0)
154 : # define USTR_CNTL_MALLOC_CHECK_MEM(x) (USTR_TRUE) /* pretend */
155 : # define USTR_CNTL_MALLOC_CHECK_MEM_SZ(x, y) (USTR_TRUE) /* pretend */
156 : # define USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(x, y) (USTR_TRUE) /* pretend */
157 : # define USTR_CNTL_MALLOC_CHECK_MEM_USTR(s1) (USTR_TRUE) /* pretend */
158 : # define USTR_CNTL_MALLOC_CHECK_MEM_USTRP(s1) (USTR_TRUE) /* pretend */
159 : # define USTR_CNTL_MALLOC_CHECK_END(x) (USTR_TRUE)
160 : # define USTR_CNTL_MALLOC_CHECK_ADD(x) (USTR_FALSE)
161 : # define USTR_CNTL_MALLOC_CHECK_DEL(x) (USTR_TRUE)
162 :
163 : # define USTR__CNTL_MALLOC_CHECK_FIXUP_REALLOC(x, y) /* do nothing */
164 : #endif
165 :
166 : /* ---- BEG: static/dynamic config. ---- */
167 : /* NOTE: If you alter this it's copied into ustr-cntl-code.c */
168 : #ifndef USTR_CONF_REF_BYTES /* how many bytes to use for reference count */
169 : #define USTR_CONF_REF_BYTES 1
170 : #endif
171 :
172 : #ifndef USTR_CONF_HAS_SIZE /* Include a size value */
173 : #define USTR_CONF_HAS_SIZE USTR_FALSE
174 : #endif
175 :
176 : #ifndef USTR_CONF_EXACT_BYTES /* don't get a little extra space from malloc() */
177 : #define USTR_CONF_EXACT_BYTES USTR_FALSE
178 : #endif
179 :
180 : /* so you can use something else, if you want */
181 : #ifndef USTR_CONF_MALLOC
182 : #define USTR_CONF_MALLOC(x) malloc(x)
183 : #endif
184 : #ifndef USTR_CONF_REALLOC
185 : #define USTR_CONF_REALLOC(x, y) realloc((x), (y))
186 : #endif
187 : #ifndef USTR_CONF_FREE
188 : #define USTR_CONF_FREE(x) free(x)
189 : #endif
190 : #ifndef USTR_CONF_VSNPRINTF_BEG
191 : #define USTR_CONF_VSNPRINTF_BEG vsnprintf
192 : #endif
193 : #ifndef USTR_CONF_VSNPRINTF_END
194 : #define USTR_CONF_VSNPRINTF_END vsnprintf
195 : #endif
196 : /* ---- END: static/dynamic config. ---- */
197 :
198 :
199 : #define USTR__COMPILE_ASSERT(x, y) \
200 : extern char ustr__compiler_assert_ ## y[1 - 2*!(x)]
201 :
202 : USTR__COMPILE_ASSERT(CHAR_BIT == 8, num_char_bits);
203 :
204 : #if USTR_CONF_HAVE_64bit_SIZE_MAX
205 : USTR__COMPILE_ASSERT(USTR__SIZE_MAX >= 0xFFFFFFFFFFFFFFFFULL,
206 : small_size_t_limit64);
207 : #else
208 : USTR__COMPILE_ASSERT(USTR__SIZE_MAX >= 0xFFFFFFFFUL, small_size_t_limit32);
209 : #endif
210 :
211 : #if ! USTR_CONF_USE_DYNAMIC_CONF
212 : # if !((USTR_CONF_REF_BYTES == 0) || (USTR_CONF_REF_BYTES == 1) || \
213 : (USTR_CONF_REF_BYTES == 2) || (USTR_CONF_REF_BYTES == 4) || \
214 : (USTR_CONF_HAVE_64bit_SIZE_MAX && (USTR_CONF_REF_BYTES == 8)))
215 : # error "Bad size for USTR_CONF_REF_BYTES"
216 : # endif
217 : #endif
218 :
219 :
220 : /* As the saying goes:
221 : * "you can tell a lot about the code from the data structure".
222 : *
223 : * So this is the non-magic version of the struct Ustr:
224 : *
225 : * struct Ustr
226 : * {
227 : * const char *ptr;
228 : * size_t reference_count;
229 : * size_t length;
230 : * size_t size;
231 : *
232 : * unsigned char flag_is_readonly : 1;
233 : * unsigned char flag_is_fixed : 1;
234 : * unsigned char flag_exact_byte_allocations : 1;
235 : * unsigned char flag_has_enomem_error : 1;
236 : * unsigned char flag_fail_on_alloc : 1;
237 : * };
238 : *
239 : * ...however this "eats" memory for "small" strings, which is one reason given
240 : * why people don't use a real string ADT.
241 : *
242 : */
243 : struct Ustr
244 : {
245 : unsigned char data[1];
246 : /* 0b_wxyz_nnoo =>
247 : *
248 : * w = allocated
249 : * x = has size
250 : * y = round up allocations (off == exact allocations)
251 : * z = memory error
252 : * nn = refn
253 : * oo = lenn
254 : *
255 : * Eg.
256 : *
257 : * 0b_0000_0000 ==
258 : * "" ==
259 : * not allocated, [no size], [no round up allocs], no mem err, refn=0, lenn=0
260 : *
261 : * 0b1000_0001 ==
262 : * 0xA5 ==
263 : * allocated, no size, no round up allocs, no mem err, refn=0, lenn=1
264 : *
265 : * 0b1010_0101 ==
266 : * 0xA5 ==
267 : * allocated, no size, round up allocs, no mem err, refn=1, lenn=1
268 : */
269 : };
270 : struct Ustrp
271 : { /* This is a type for the "pool" allocated Ustr it is a seperate type as a
272 : * way to catch errors at compile time with static typing. You might think
273 : * we'd define Ustrp to be identical to Ustr, and just cast ... however
274 : * I'm 99% sure that aliasing rules screw us over if we do that. */
275 : struct Ustr s;
276 : };
277 : USTR__COMPILE_ASSERT(sizeof("") == sizeof(struct Ustr), bad_sizeof_ustr);
278 : USTR__COMPILE_ASSERT(sizeof(struct Ustrp) == sizeof(struct Ustr),
279 : bad_sizeof_ustrp);
280 : /* Unused bit patterns for data[0]:
281 : *
282 : * 0bx0xx_x100 == lenn = 0
283 : * 0bx0xx_1x00
284 : * 0bx0x1_xx00
285 : * 0bx01x_xx00
286 : * 0bx1xx_xx00 => is used in sized
287 : * 0b10xx_xx00
288 : *
289 : * 0bx1xx_xx11 == 128bit size_t, yeh!
290 : * 0bx1xx_11xx
291 : *
292 : * 0b0xxx_x1xx == refn values for const/fixed
293 : * 0b0xxx_1xxx
294 : *
295 : * 0b00x1_xxxx == mem error for const
296 : * 0b001x_xxxx == not exact for const
297 : *
298 : */
299 : #define USTR__BIT_ALLOCD (1<<7)
300 : #define USTR__BIT_HAS_SZ (1<<6)
301 : #define USTR__BIT_NEXACT (1<<5)
302 : #define USTR__BIT_ENOMEM (1<<4)
303 :
304 : #define USTR__BITS_RW (USTR__BIT_ALLOCD | USTR__BIT_HAS_SZ)
305 : #define USTR__BITS_FIXED USTR__BIT_HAS_SZ
306 : #define USTR__BITS_RWLIM (USTR__BIT_ALLOCD | USTR__BIT_HAS_SZ | \
307 : USTR__BIT_NEXACT)
308 : #define USTR__BITS_LIMITED USTR__BIT_HAS_SZ
309 :
310 : /* constant string macros */
311 : #define USTR_BEG_CONST1 "\x01"
312 : #define USTR_BEG_CONST2 "\x02"
313 : #define USTR_BEG_CONST4 "\x03"
314 : #define USTR_BEG_RO1 "\x01" /* compat. only */
315 : #define USTR_BEG_RO2 "\x02" /* compat. only */
316 : #define USTR_BEG_RO4 "\x03" /* compat. only */
317 : #define USTR_BEG_FIXED2 "x112233"
318 : #define USTR_BEG_FIXED4 "x1122223333" /* Likely? */
319 : #if USTR_CONF_HAVE_64bit_SIZE_MAX
320 : # define USTR_BEG_FIXED8 "x112222222233333333" /* Not, so much. */
321 : #endif
322 : #if USTR_CONF_USE_EOS_MARK /* i == 0b_0110_1001 */
323 : # define USTR_END_CONSTx "\0<ii-CONST_EOS-ii>"
324 : # define USTR_END_ALOCDx "\0<ii-ALOCD_EOS-ii>"
325 : # define USTR_END_FIXEDx "\0<ii-FIXED_EOS-ii>"
326 : #else
327 : # define USTR_END_CONSTx ""
328 : # define USTR_END_ALOCDx ""
329 : # define USTR_END_FIXEDx ""
330 : #endif
331 : USTR__COMPILE_ASSERT((sizeof(USTR_END_CONSTx) == sizeof(USTR_END_ALOCDx)),
332 : eos_alloced_bad_size);
333 : USTR__COMPILE_ASSERT((sizeof(USTR_END_CONSTx) == sizeof(USTR_END_FIXEDx)),
334 : eos_fixed_bad_size);
335 :
336 :
337 : #define USTR(x) ((struct Ustr *) x)
338 : #define USTRP(x) ((struct Ustrp *) x)
339 :
340 : #define USTR1(x1, y) \
341 : USTR(USTR_BEG_CONST1 #x1 y USTR_END_CONSTx)
342 : #define USTR2(x1, x2, y) \
343 : USTR(USTR_BEG_CONST2 #x2 #x1 y USTR_END_CONSTx)
344 : #define USTR4(x1, x2, x3, x4, y) \
345 : USTR(USTR_BEG_CONST4 #x4 #x3 #x2 #x1 y USTR_END_CONSTx)
346 :
347 : #define USTRP1(x1, y) \
348 : USTRP(USTR_BEG_CONST1 #x1 y USTR_END_CONSTx)
349 : #define USTRP2(x1, x2, y) \
350 : USTRP(USTR_BEG_CONST2 #x2 #x1 y USTR_END_CONSTx)
351 : #define USTRP4(x1, x2, x3, x4, y) \
352 : USTRP(USTR_BEG_CONST4 #x4 #x3 #x2 #x1 y USTR_END_CONSTx)
353 :
354 : #define USTR1_CHK(x1, y) ((*( #x1 ) == (sizeof(y) - 1)) ? \
355 : USTR(USTR_BEG_CONST1 #x1 y USTR_END_CONSTx) : \
356 : USTR(""))
357 : #define USTR2_CHK(x1, x2, y) \
358 : ((((size_t)*( #x1 ) * 256 + *( #x2 )) == (sizeof(y) - 1)) ? \
359 : USTR(USTR_BEG_CONST2 #x2 #x1 y USTR_END_CONSTx) : \
360 : USTR(""))
361 : #define USTR4_CHK(x1, x2, x3, x4, y) \
362 : ((((size_t)*( #x1 ) * 16777216 + (size_t)*( #x2 ) * 65536 + \
363 : (size_t)*( #x3 ) * 256 + *( #x4 )) == (sizeof(y) - 1)) ? \
364 : USTR(USTR_BEG_CONST4 #x4 #x3 #x2 #x1 y USTR_END_CONSTx) : \
365 : USTR(""))
366 :
367 : #define USTRP1_CHK(x1, y) ((*( #x1 ) == (sizeof(y) - 1)) ? \
368 : USTRP(USTR_BEG_CONST1 #x1 y USTR_END_CONSTx) : \
369 : USTRP(""))
370 : #define USTRP2_CHK(x1, x2, y) \
371 : ((((size_t)*( #x1 ) * 256 + *( #x2 )) == (sizeof(y) - 1)) ? \
372 : USTRP(USTR_BEG_CONST2 #x2 #x1 y USTR_END_CONSTx) : \
373 : USTRP(""))
374 : #define USTRP4_CHK(x1, x2, x3, x4, y) \
375 : ((((size_t)*( #x1 ) * 16777216 + (size_t)*( #x2 ) * 65536 + \
376 : (size_t)*( #x3 ) * 256 + *( #x4 )) == (sizeof(y) - 1)) ? \
377 : USTRP(USTR_BEG_CONST4 #x4 #x3 #x2 #x1 y USTR_END_CONSTx) : \
378 : USTRP(""))
379 :
380 :
381 : /*
382 : * ================ English description of struct Ustr ================
383 : *
384 : * This strucure is very magic, as an optimization "" is a valid "structure"
385 : * for an empty string, ustr_len("") == 0, ustr_size("") == 0,
386 : * ustr_cstr("") == "".
387 : * This also works for other "static data strings" if they start with the first
388 : * four bits as 0 ... although for C const strings using this, the length has
389 : * to be manually defined correctly at compile time.
390 : *
391 : * However it is also a "space efficient" String ADT, with a managed length,
392 : * _either_ with or without reference counts (so that ustr_dup() doesn't copy)
393 : * and with or without a stored size (so growing/shrinking a lot doesn't
394 : * cause lots of malloc/realloc usage). Note that for lengths of strings, or
395 : * reference counts that need >= 8 bytes of storage the Ustr _MUST_ contain
396 : * a stored size.
397 : *
398 : * It can also track memory allocation errors over multiple function calls.
399 : *
400 : * If the first byte == 0, then it's "" as above.
401 : * Otherwise the first byte contains four flags, and 2 numbers (2 bits each).
402 : *
403 : * The 1st flag says if the string is allocated. The 2nd flag says if it has a
404 : * stored size. The 3rd flag says if it isn't using "exact allocations", if it
405 : * is ustr_len() + ustr_overhead() == ustr_size_alloc(), otherwise there might
406 : * be room to grow without doing a memory allocation call[1]. The 4th flag says
407 : * if this Ustr has had a memory allocation error.
408 : * The two numbers are the mappings for the length of the reference count, and
409 : * the length of the length. Note that this mapping changes if the 2nd flag is
410 : * set.
411 : *
412 : * [1] There is an implied "size" of the string, based an how big it is. This
413 : * is a concession for speed efficiency, although it only grows at 1.5x
414 : * not 2x which is the norm. (again, to reduce memory waste). Again if this is
415 : * too much overhead, just use exact sized allocations.
416 : *
417 : * Also NOTE if the 1st and 2nd flags are set, this means that the Ustr is in
418 : * fixed storge (like an auto array). Also if the 1st, 2nd and 3rd flags are
419 : * set, this means that the Ustr is limited, Ie. it's in fixed storge and
420 : * _CANNOT_ grow (all allocation attempts will fail).
421 : *
422 : * == If there is any more data after the above declared one they have
423 : * been allocated via. the "struct hack" method (search for more info). ==
424 : *
425 : * Next, possibly, comes the reference count (of the given length[2]).
426 : * Next, if not "", comes the length of the data (of the given length[2]).
427 : * Next, if non-zero length, comes the data, which can include NIL bytes.
428 : * And finally, if not "", a NIL byte, to make sure it's always a valid C-Style
429 : * string (although obviously any embeded NIL bytes will make it look shorter
430 : * if something else just uses strlen(ustr_cstr())).
431 : *
432 : * [2] The sizes can currently be 1, 2, 4 or 8 bytes. Depending on the mapping
433 : * of the value in the first byte (length changes dynamically, as you add data).
434 : *
435 : * Examples:
436 : *
437 : * The allocated string "a", using exact allocations and no reference
438 : * counting, is the 4 bytes:
439 : *
440 : * {0x81, 0x01, 'a', 0x00}
441 : *
442 : *
443 : * The allocated string "ab", using non-exact allocations and 1 byte reference
444 : * counting (shared by 13 users), is the 6 bytes (there is no waste due to
445 : * non-exact allocations):
446 : *
447 : * {0xA5, 0x0D, 0x02, 'a', 'b', 0x00}
448 : *
449 : *
450 : * The allocated string "abcdefghijklmnop" (16 bytes, and a NIL), with
451 : * non-exact allocations 2 byte reference counting (shared by 1,003 users), is
452 : * the 24 bytes (with 3 bytes of "unused" space at the end):
453 : *
454 : * {0xA9, 0x03, 0xEB, 0x10, 'a', 'b', [...], 'o', 'p', 0x00, <x>, <x>, <x>}
455 : */
456 :
457 : struct Ustr_pool
458 : {
459 : void *(*pool_sys_malloc)(struct Ustr_pool *, size_t);
460 : void *(*pool_sys_realloc)(struct Ustr_pool *, void *, size_t, size_t);
461 : void (*pool_sys_free)(struct Ustr_pool *, void *);
462 :
463 : struct Ustr_pool *(*pool_make_subpool)(struct Ustr_pool *);
464 : void (*pool_clear)(struct Ustr_pool *);
465 : void (*pool_free)(struct Ustr_pool *);
466 : };
467 :
468 : #if USTR_CONF_COMPILE_TYPEDEF
469 : typedef struct Ustr Ustr;
470 : typedef struct Ustrp Ustrp;
471 : typedef struct Ustr_pool Ustr_pool;
472 : #endif
473 :
474 : #define USTR_SC_INIT_AUTO(x, y, z) \
475 : ustr_init_fixed(x, sizeof(x), y, z)
476 : #define USTR_SC_INIT_AUTO_OSTR(x, y, z) \
477 : ustr_init_fixed(x, sizeof(x), y, sizeof(z) - 1)
478 :
479 : #define USTRP_SC_INIT_AUTO(x, y, z) \
480 : ustrp_init_fixed(x, sizeof(x), y, z)
481 : #define USTRP_SC_INIT_AUTO_OSTR(x, y, z) \
482 : ustrp_init_fixed(x, sizeof(x), y, sizeof(z) - 1)
483 :
484 : /* (x) && (((x) - 1) >= 0xFFFFFFFF) should really be:
485 : (x) > 0xFFFFFFFF ... but GCC likes to warn about that if x == 4, say */
486 : #define USTR_SIZE_FIXED(x) ((x) + 1 + 2 + 4 + \
487 : (((x) > 0xFFFF) ? 4 : 0) + \
488 : ((USTR_CONF_HAVE_64bit_SIZE_MAX && (x) && \
489 : (((x) - 1) >= 0xFFFFFFFF)) ? 8 : 0) + \
490 : sizeof(USTR_END_FIXEDx))
491 :
492 : #define USTR_ADD_OBJ(x, y) ustr_add_buf(x, y, sizeof(y))
493 : #define USTR_ADD_OSTR(x, y) ustr_add_buf(x, y, sizeof(y) - 1)
494 : #define USTR_DUP_OBJ(y) ustr_dup_buf(y, sizeof(y))
495 : #define USTR_DUP_OSTR(y) ustr_dup_buf(y, sizeof(y) - 1)
496 : #define USTR_DUPX_OBJ(x1, x2, x3, x4, y) \
497 : ustr_dupx_buf(x1, x2, x3, x4, y, sizeof(y))
498 : #define USTR_DUPX_OSTR(x1, x2, x3, x4, y) \
499 : ustr_dupx_buf(x1, x2, x3, x4, y, sizeof(y) - 1)
500 :
501 : #define USTRP_ADD_OBJ(p, x, y) ustrp_add_buf(p, x, y, sizeof(y))
502 : #define USTRP_ADD_OSTR(p, x, y) ustrp_add_buf(p, x, y, sizeof(y) - 1)
503 : #define USTRP_DUP_OBJ(p, y) ustrp_dup_buf(p, y, sizeof(y))
504 : #define USTRP_DUP_OSTR(p, y) ustrp_dup_buf(p, y, sizeof(y) - 1)
505 : #define USTRP_DUPX_OBJ(p, x1, x2, x3, x4, y) \
506 : ustrp_dupx_buf(p, x1, x2, x3, x4, y, sizeof(y))
507 : #define USTRP_DUPX_OSTR(p, x1, x2, x3, x4, y) \
508 : ustrp_dupx_buf(p, x1, x2, x3, x4, y, sizeof(y) - 1)
509 :
510 : #define USTR__REF_LEN(x) ustr_xi__pow2(ustr_sized(x), (x)->data[0] >> 2)
511 : #define USTR__LEN_LEN(x) ustr_xi__pow2(ustr_sized(x), (x)->data[0])
512 :
513 : /* ---------------- Ustr "pool" because none in stdlib. ---------------- */
514 :
515 : USTR_CONF_EI_PROTO struct Ustr_pool *ustr_pool_make_subpool(struct Ustr_pool *)
516 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_MALLOC()
517 : USTR__COMPILE_ATTR_NONNULL_A();
518 : USTR_CONF_EI_PROTO void ustr_pool_clear(struct Ustr_pool *)
519 : USTR__COMPILE_ATTR_NONNULL_A();
520 : USTR_CONF_EI_PROTO void ustr_pool_free(struct Ustr_pool *);
521 :
522 : /* This converts a number n to 2**(n-1) -- for small values > 0.
523 : * Where n==0 means 0.
524 : * Oh and n==7 means 0 -- because, see above. */
525 : USTR_CONF_EI_PROTO size_t ustr_xi__pow2(int, unsigned char)
526 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_CONST();
527 :
528 : /* Check if everything looks OK, should be used in debugging only. */
529 : USTR_CONF_E_PROTO int ustr_assert_valid(const struct Ustr *)
530 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
531 : USTR__COMPILE_ATTR_NONNULL_A();
532 : USTR_CONF_E_PROTO
533 : size_t ustr_assert_valid_subustr(const struct Ustr *, size_t, size_t)
534 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
535 : USTR__COMPILE_ATTR_NONNULL_A();
536 :
537 : USTR_CONF_E_PROTO int ustrp_assert_valid(const struct Ustrp *)
538 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
539 : USTR__COMPILE_ATTR_NONNULL_A();
540 : USTR_CONF_E_PROTO
541 : int ustrp_assert_valid_subustrp(const struct Ustrp *, size_t, size_t)
542 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
543 : USTR__COMPILE_ATTR_NONNULL_A();
544 :
545 : USTR_CONF_EI_PROTO size_t ustr_xi__embed_val_get(const unsigned char *, size_t)
546 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
547 : USTR__COMPILE_ATTR_NONNULL_A();
548 :
549 : USTR_CONF_EI_PROTO size_t ustr_xi__ref_get(const struct Ustr *)
550 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
551 : USTR__COMPILE_ATTR_NONNULL_A();
552 :
553 : /* ---------------- Ustr "member" access ---------------- */
554 : USTR_CONF_EI_PROTO size_t ustr_len(const struct Ustr *)
555 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
556 : USTR__COMPILE_ATTR_NONNULL_A();
557 : USTR_CONF_EI_PROTO const char *ustr_cstr(const struct Ustr *)
558 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
559 : USTR__COMPILE_ATTR_NONNULL_A();
560 : USTR_CONF_E_PROTO char *ustr_wstr(struct Ustr *)
561 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
562 : USTR__COMPILE_ATTR_NONNULL_A();
563 :
564 : USTR_CONF_EI_PROTO int ustr_alloc(const struct Ustr *)
565 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
566 : USTR__COMPILE_ATTR_NONNULL_A();
567 : USTR_CONF_EI_PROTO int ustr_exact(const struct Ustr *)
568 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
569 : USTR__COMPILE_ATTR_NONNULL_A();
570 : USTR_CONF_EI_PROTO int ustr_sized(const struct Ustr *)
571 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
572 : USTR__COMPILE_ATTR_NONNULL_A();
573 : USTR_CONF_EI_PROTO int ustr_ro(const struct Ustr *)
574 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
575 : USTR__COMPILE_ATTR_NONNULL_A();
576 : USTR_CONF_EI_PROTO int ustr_fixed(const struct Ustr *)
577 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
578 : USTR__COMPILE_ATTR_NONNULL_A();
579 : USTR_CONF_EI_PROTO int ustr_enomem(const struct Ustr *)
580 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
581 : USTR__COMPILE_ATTR_NONNULL_A();
582 : USTR_CONF_EI_PROTO int ustr_shared(const struct Ustr *)
583 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
584 : USTR__COMPILE_ATTR_NONNULL_A();
585 : USTR_CONF_EI_PROTO int ustr_limited(const struct Ustr *)
586 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
587 : USTR__COMPILE_ATTR_NONNULL_A();
588 : USTR_CONF_E_PROTO int ustr_owner(const struct Ustr *)
589 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
590 : USTR__COMPILE_ATTR_NONNULL_A();
591 :
592 : USTR_CONF_E_PROTO
593 : void ustr_conf(const struct Ustr *, size_t *,size_t *,int *, size_t *,size_t *)
594 : USTR__COMPILE_ATTR_NONNULL_L((1));
595 :
596 : USTR_CONF_E_PROTO int ustr_setf_enomem_err(struct Ustr *)
597 : USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */
598 : USTR_CONF_E_PROTO int ustr_setf_enomem_clr(struct Ustr *)
599 : USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */
600 :
601 : USTR_CONF_E_PROTO int ustr_setf_share(struct Ustr *)
602 : USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */
603 : USTR_CONF_E_PROTO int ustr_setf_owner(struct Ustr *)
604 : USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */
605 :
606 : USTR_CONF_E_PROTO size_t ustr_size(const struct Ustr *)
607 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
608 : USTR__COMPILE_ATTR_NONNULL_A();
609 : USTR_CONF_E_PROTO size_t ustr_size_alloc(const struct Ustr *)
610 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
611 : USTR__COMPILE_ATTR_NONNULL_A();
612 : USTR_CONF_E_PROTO size_t ustr_size_overhead(const struct Ustr *)
613 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
614 : USTR__COMPILE_ATTR_NONNULL_A();
615 :
616 : /* ---------------- free Ustr's ---------------- */
617 :
618 : USTR_CONF_E_PROTO void ustrp_free(struct Ustr_pool *, struct Ustrp *);
619 :
620 : USTR_CONF_E_PROTO void ustr_free(struct Ustr *);
621 :
622 : /* ---------------- init - helpers so others can make Ustr's ---------------- */
623 : USTR_CONF_E_PROTO size_t ustr_init_size(size_t, size_t, int, size_t)
624 : USTR__COMPILE_ATTR_CONST() USTR__COMPILE_ATTR_WARN_UNUSED_RET();
625 : USTR_CONF_E_PROTO
626 : struct Ustr *ustr_init_alloc(void *, size_t, size_t, size_t, int, int, size_t)
627 : USTR__COMPILE_ATTR_NONNULL_A();
628 : USTR_CONF_E_PROTO
629 : struct Ustr *ustr_init_fixed(void *, size_t, int, size_t)
630 : USTR__COMPILE_ATTR_NONNULL_A();
631 :
632 : USTR_CONF_E_PROTO
633 : struct Ustrp *ustrp_init_alloc(void *, size_t, size_t, size_t, int, int, size_t)
634 : USTR__COMPILE_ATTR_NONNULL_A();
635 : USTR_CONF_E_PROTO
636 : struct Ustrp *ustrp_init_fixed(void *, size_t, int, size_t)
637 : USTR__COMPILE_ATTR_NONNULL_A();
638 :
639 : /* ---------------- add ---------------- */
640 :
641 : USTR_CONF_E_PROTO int ustr_add_undef(struct Ustr **, size_t)
642 : USTR__COMPILE_ATTR_NONNULL_A();
643 : USTR_CONF_E_PROTO
644 : int ustrp_add_undef(struct Ustr_pool *, struct Ustrp **, size_t)
645 : USTR__COMPILE_ATTR_NONNULL_L((2));
646 :
647 : USTR_CONF_E_PROTO int ustr_add_buf(struct Ustr **, const void *, size_t)
648 : USTR__COMPILE_ATTR_NONNULL_A();
649 : USTR_CONF_EI_PROTO int ustr_add_cstr(struct Ustr **, const char *)
650 : USTR__COMPILE_ATTR_NONNULL_A();
651 : USTR_CONF_E_PROTO int ustr_add(struct Ustr **, const struct Ustr *)
652 : USTR__COMPILE_ATTR_NONNULL_A();
653 : USTR_CONF_E_PROTO
654 : int ustr_add_subustr(struct Ustr **, const struct Ustr *, size_t, size_t)
655 : USTR__COMPILE_ATTR_NONNULL_A();
656 : USTR_CONF_E_PROTO int ustr_add_rep_chr(struct Ustr **, char, size_t)
657 : USTR__COMPILE_ATTR_NONNULL_A();
658 :
659 : USTR_CONF_E_PROTO
660 : int ustrp_add_buf(struct Ustr_pool *, struct Ustrp **, const void *, size_t)
661 : USTR__COMPILE_ATTR_NONNULL_L((2, 3));
662 : USTR_CONF_EI_PROTO
663 : int ustrp_add_cstr(struct Ustr_pool *, struct Ustrp **, const char *)
664 : USTR__COMPILE_ATTR_NONNULL_L((2, 3));
665 : USTR_CONF_E_PROTO
666 : int ustrp_add(struct Ustr_pool *, struct Ustrp **, const struct Ustrp *)
667 : USTR__COMPILE_ATTR_NONNULL_L((2, 3));
668 : USTR_CONF_E_PROTO int ustrp_add_subustrp(struct Ustr_pool *, struct Ustrp **,
669 : const struct Ustrp *, size_t, size_t)
670 : USTR__COMPILE_ATTR_NONNULL_L((2, 3));
671 : USTR_CONF_E_PROTO
672 : int ustrp_add_rep_chr(struct Ustr_pool *, struct Ustrp **, char, size_t)
673 : USTR__COMPILE_ATTR_NONNULL_L((2));
674 :
675 : /* ---------------- del ---------------- */
676 :
677 : USTR_CONF_E_PROTO int ustr_realloc(struct Ustr **, size_t)
678 : USTR__COMPILE_ATTR_NONNULL_A();
679 :
680 : USTR_CONF_E_PROTO int ustrp_realloc(struct Ustr_pool *, struct Ustrp **, size_t)
681 : USTR__COMPILE_ATTR_NONNULL_L((2));
682 :
683 : USTR_CONF_E_PROTO int ustr_del(struct Ustr **, size_t)
684 : USTR__COMPILE_ATTR_NONNULL_A();
685 : USTR_CONF_E_PROTO int ustr_del_subustr(struct Ustr **, size_t, size_t)
686 : USTR__COMPILE_ATTR_NONNULL_A();
687 :
688 : USTR_CONF_E_PROTO int ustrp_del(struct Ustr_pool *, struct Ustrp **, size_t)
689 : USTR__COMPILE_ATTR_NONNULL_L((2));
690 : USTR_CONF_E_PROTO
691 : int ustrp_del_subustrp(struct Ustr_pool *, struct Ustrp **, size_t,size_t)
692 : USTR__COMPILE_ATTR_NONNULL_L((2));
693 :
694 : /* ---------------- dup ---------------- */
695 :
696 : USTR_CONF_E_PROTO struct Ustr *ustr_dupx_undef(size_t, size_t, int, int, size_t)
697 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
698 : USTR_CONF_E_PROTO
699 : struct Ustrp *ustrp_dupx_undef(struct Ustr_pool *, size_t, size_t, int, int,
700 : size_t)
701 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
702 :
703 : USTR_CONF_E_PROTO struct Ustr *ustr_dup_undef(size_t)
704 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
705 : USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_undef(struct Ustr_pool *, size_t)
706 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
707 :
708 : USTR_CONF_E_PROTO struct Ustr *ustr_dupx_empty(size_t, size_t, int, int)
709 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
710 : USTR_CONF_E_PROTO
711 : struct Ustrp *ustrp_dupx_empty(struct Ustr_pool *, size_t, size_t, int, int)
712 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
713 :
714 : USTR_CONF_E_PROTO struct Ustr *ustr_dup_empty(void)
715 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
716 : USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_empty(struct Ustr_pool *)
717 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
718 :
719 : USTR_CONF_E_PROTO
720 : struct Ustr *ustr_dupx_buf(size_t, size_t, int, int, const void *, size_t)
721 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
722 : USTR_CONF_E_PROTO struct Ustr *ustr_dup_buf(const void *, size_t)
723 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
724 : USTR_CONF_EI_PROTO
725 : struct Ustr *ustr_dupx_cstr(size_t, size_t, int, int, const char *)
726 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
727 : USTR_CONF_EI_PROTO struct Ustr *ustr_dup_cstr(const char *)
728 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
729 : USTR_CONF_E_PROTO
730 : struct Ustr *ustr_dupx(size_t, size_t, int, int, const struct Ustr *)
731 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
732 : USTR_CONF_E_PROTO struct Ustr *ustr_dup(const struct Ustr *)
733 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
734 : USTR_CONF_E_PROTO
735 : struct Ustr *
736 : ustr_dupx_subustr(size_t, size_t, int, int, const struct Ustr *, size_t, size_t)
737 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
738 : USTR_CONF_E_PROTO
739 : struct Ustr *ustr_dup_subustr(const struct Ustr *, size_t, size_t)
740 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
741 : USTR_CONF_E_PROTO
742 : struct Ustr *ustr_dupx_rep_chr(size_t, size_t, int, int, char, size_t)
743 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
744 : USTR_CONF_E_PROTO struct Ustr *ustr_dup_rep_chr(char, size_t)
745 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
746 :
747 : USTR_CONF_E_PROTO
748 : struct Ustrp *ustrp_dupx_buf(struct Ustr_pool *, size_t, size_t, int, int,
749 : const void *, size_t)
750 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6));
751 : USTR_CONF_E_PROTO
752 : struct Ustrp *ustrp_dup_buf(struct Ustr_pool *, const void *, size_t)
753 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2));
754 : USTR_CONF_EI_PROTO
755 : struct Ustrp *ustrp_dupx_cstr(struct Ustr_pool *, size_t, size_t, int, int,
756 : const char *)
757 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6));
758 : USTR_CONF_EI_PROTO struct Ustrp *ustrp_dup_cstr(struct Ustr_pool *,const char *)
759 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2));
760 : USTR_CONF_E_PROTO
761 : struct Ustrp *ustrp_dupx(struct Ustr_pool *, size_t, size_t, int, int,
762 : const struct Ustrp *)
763 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6));
764 : USTR_CONF_E_PROTO
765 : struct Ustrp *ustrp_dup(struct Ustr_pool *, const struct Ustrp *)
766 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2));
767 : USTR_CONF_E_PROTO
768 : struct Ustrp *ustrp_dupx_subustrp(struct Ustr_pool *, size_t, size_t, int, int,
769 : const struct Ustrp *, size_t, size_t)
770 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6));
771 : USTR_CONF_E_PROTO
772 : struct Ustrp *ustrp_dup_subustrp(struct Ustr_pool *,
773 : const struct Ustrp *, size_t, size_t)
774 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2));
775 : USTR_CONF_E_PROTO
776 : struct Ustrp *ustrp_dupx_rep_chr(struct Ustr_pool *, size_t, size_t, int, int,
777 : char, size_t)
778 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
779 : USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_rep_chr(struct Ustr_pool *,
780 : char, size_t)
781 : USTR__COMPILE_ATTR_WARN_UNUSED_RET();
782 :
783 : /* ---------------- shortcut ---------------- */
784 :
785 : USTR_CONF_E_PROTO void ustr_sc_del(struct Ustr **)
786 : USTR__COMPILE_ATTR_NONNULL_A();
787 : USTR_CONF_E_PROTO void ustr_sc_free(struct Ustr **)
788 : USTR__COMPILE_ATTR_NONNULL_A();
789 : USTR_CONF_E_PROTO void ustr_sc_free2(struct Ustr **, struct Ustr *)
790 : USTR__COMPILE_ATTR_NONNULL_A();
791 :
792 : USTR_CONF_E_PROTO void ustrp_sc_del(struct Ustr_pool *, struct Ustrp **)
793 : USTR__COMPILE_ATTR_NONNULL_L((2));
794 : USTR_CONF_E_PROTO void ustrp_sc_free(struct Ustr_pool *, struct Ustrp **)
795 : USTR__COMPILE_ATTR_NONNULL_L((2));
796 : USTR_CONF_E_PROTO
797 : void ustrp_sc_free2(struct Ustr_pool *, struct Ustrp **, struct Ustrp *)
798 : USTR__COMPILE_ATTR_NONNULL_L((2, 3));
799 :
800 :
801 : USTR_CONF_E_PROTO int ustr_sc_ensure_owner(struct Ustr **)
802 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
803 : USTR_CONF_E_PROTO char *ustr_sc_wstr(struct Ustr **)
804 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
805 :
806 : USTR_CONF_E_PROTO int ustrp_sc_ensure_owner(struct Ustr_pool *, struct Ustrp **)
807 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2));
808 : USTR_CONF_E_PROTO char *ustrp_sc_wstr(struct Ustr_pool *, struct Ustrp **)
809 : USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2));
810 :
811 : /* ---------------- pre inlines ---------------- */
812 : #if USTR_CONF_COMPILE_USE_INLINE
813 : USTR_CONF_II_PROTO struct Ustr_pool *ustr_pool_make_subpool(struct Ustr_pool *p)
814 33 : {
815 22 : USTR_ASSERT(p);
816 44 : return (p->pool_make_subpool(p));
817 : }
818 : USTR_CONF_II_PROTO void ustr_pool_clear(struct Ustr_pool *p)
819 30 : {
820 20 : USTR_ASSERT(p);
821 40 : p->pool_clear(p);
822 30 : }
823 : USTR_CONF_II_PROTO void ustr_pool_free(struct Ustr_pool *p)
824 45 : {
825 60 : if (!p)
826 3 : return;
827 :
828 56 : p->pool_free(p);
829 : }
830 :
831 : USTR_CONF_II_PROTO int ustr_alloc(const struct Ustr *s1)
832 10810302 : { return (!!(s1->data[0] & USTR__BIT_ALLOCD)); }
833 : USTR_CONF_II_PROTO int ustr_exact(const struct Ustr *s1)
834 4042572 : { return ( !(s1->data[0] & USTR__BIT_NEXACT)); }
835 : USTR_CONF_II_PROTO int ustr_sized(const struct Ustr *s1)
836 48041859 : { return (!!(s1->data[0] & USTR__BIT_HAS_SZ)); }
837 : USTR_CONF_II_PROTO int ustr_enomem(const struct Ustr *s1)
838 3753742 : { return (!!(s1->data[0] & USTR__BIT_ENOMEM)); }
839 :
840 : /* these are compound bit tests */
841 : USTR_CONF_II_PROTO int ustr_ro(const struct Ustr *s1)
842 13114291 : { return (!(s1->data[0] & USTR__BITS_RW)); }
843 : USTR_CONF_II_PROTO int ustr_fixed(const struct Ustr *s1)
844 11397653 : { return (( s1->data[0] & USTR__BITS_RW) == USTR__BITS_FIXED); }
845 : USTR_CONF_II_PROTO int ustr_limited(const struct Ustr *s1)
846 3488801 : { return (( s1->data[0] & USTR__BITS_RWLIM) == USTR__BITS_LIMITED); }
847 :
848 : USTR_CONF_II_PROTO
849 : size_t ustr_xi__embed_val_get(const unsigned char *data, size_t len)
850 9544266 : {
851 9548934 : size_t ret = 0;
852 :
853 9548934 : switch (len)
854 : {
855 148 : case 0: return (-1);
856 :
857 : #if USTR_CONF_HAVE_64bit_SIZE_MAX
858 : case 8:
859 67 : ret |= (((size_t)data[7]) << 56);
860 67 : ret |= (((size_t)data[6]) << 48);
861 67 : ret |= (((size_t)data[5]) << 40);
862 67 : ret |= (((size_t)data[4]) << 32);
863 : #endif
864 : case 4:
865 263221 : ret |= (((size_t)data[3]) << 24);
866 263221 : ret |= (((size_t)data[2]) << 16);
867 : case 2:
868 7577265 : ret |= (((size_t)data[1]) << 8);
869 : case 1:
870 9548786 : ret |= (((size_t)data[0]) << 0);
871 :
872 0 : USTR_ASSERT_NO_SWITCH_DEF("Val. length bad for ustr_xi__embed_val_get()");
873 : }
874 :
875 9548786 : return (ret);
876 : }
877 :
878 : USTR_CONF_II_PROTO size_t ustr_xi__pow2(int use_big, unsigned char len)
879 3021752 : { /* FIXME: for 2.0 or whatever make this something like:
880 : static const unsigned char map_pow2[4] = {0, 1, 2, sizeof(size_t)};
881 : */
882 : static const unsigned char map_big_pow2[4] = {2, 4, 8, 16};
883 : static const unsigned char map_pow2[4] = {0, 1, 2, 4};
884 :
885 35259212 : if (use_big)
886 15250557 : return (map_big_pow2[len & 0x03]);
887 :
888 20008655 : return (map_pow2[len & 0x03]);
889 : }
890 : USTR_CONF_II_PROTO size_t ustr_xi__ref_get(const struct Ustr *s1)
891 2871841 : { return (ustr_xi__embed_val_get(s1->data + 1, USTR__REF_LEN(s1))); }
892 : USTR_CONF_II_PROTO int ustr_shared(const struct Ustr *s1)
893 3027 : { return (ustr_ro(s1) || (ustr_alloc(s1) && !ustr_xi__ref_get(s1))); }
894 :
895 : USTR_CONF_II_PROTO size_t ustr_len(const struct Ustr *s1)
896 6186971 : { /* NOTE: can't call ustr_assert_valid() here due to recursion,
897 : * also because assert_valid() is inline, and defined later on. */
898 6177351 : USTR_ASSERT(s1);
899 :
900 6191576 : if (!s1->data[0]) return (0);
901 :
902 18541693 : return (ustr_xi__embed_val_get(s1->data + 1 + USTR__REF_LEN(s1),
903 : USTR__LEN_LEN(s1)));
904 : }
905 : USTR_CONF_II_PROTO const char *ustr_cstr(const struct Ustr *s1)
906 3500879 : { /* NOTE: can't call ustr_assert_valid() here due to recursion,
907 : * also because assert_valid() is inline, and defined later on. */
908 3504367 : size_t lenn = 0;
909 :
910 3496248 : USTR_ASSERT(s1);
911 :
912 3504367 : if (!s1->data[0]) return ((const char *)s1->data);
913 :
914 3503561 : lenn = USTR__LEN_LEN(s1);
915 3503561 : if (ustr_sized(s1))
916 1052458 : lenn *= 2;
917 :
918 6999410 : return ((const char *)(s1->data + 1 + USTR__REF_LEN(s1) + lenn));
919 : }
920 : #endif
921 :
922 : #if USTR_CONF_INCLUDE_INTERNAL_HEADERS
923 : # include "ustr-main-internal.h"
924 : #endif
925 :
926 : #if USTR_CONF_INCLUDE_CODEONLY_HEADERS
927 : # include "ustr-main-code.h"
928 : #endif
929 :
930 : /* ---------------- post inlines ---------------- */
931 : #if USTR_CONF_COMPILE_USE_INLINE
932 : USTR_CONF_II_PROTO
933 : int ustrp_add_cstr(struct Ustr_pool *p, struct Ustrp **ps1, const char *cstr)
934 16 : { return (ustrp_add_buf(p, ps1, cstr, strlen(cstr))); }
935 :
936 : USTR_CONF_II_PROTO int ustr_add_cstr(struct Ustr **ps1, const char *cstr)
937 20 : { return (ustr_add_buf(ps1, cstr, strlen(cstr))); }
938 :
939 : USTR_CONF_II_PROTO
940 : struct Ustrp *ustrp_dupx_cstr(struct Ustr_pool *p, size_t sz, size_t rb,
941 : int ex, int me, const char *c)
942 20 : { return (ustrp_dupx_buf(p, sz, rb, ex, me, c, strlen(c))); }
943 : USTR_CONF_II_PROTO
944 : struct Ustrp *ustrp_dup_cstr(struct Ustr_pool *p, const char *cstr)
945 4 : { return (ustrp_dup_buf(p, cstr, strlen(cstr))); }
946 :
947 : USTR_CONF_II_PROTO
948 : struct Ustr *ustr_dupx_cstr(size_t sz, size_t rb, int ex, int me, const char *c)
949 12 : { return (ustr_dupx_buf(sz, rb, ex, me, c, strlen(c))); }
950 : USTR_CONF_II_PROTO struct Ustr *ustr_dup_cstr(const char *cstr)
951 130 : { return (ustr_dup_buf(cstr, strlen(cstr))); }
952 : #endif
953 :
954 : /* ---------------- pool wrapper APIs ---------------- */
955 : USTR_CONF_EI_PROTO size_t ustrp_len(const struct Ustrp *)
956 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
957 : USTR__COMPILE_ATTR_NONNULL_A();
958 : USTR_CONF_EI_PROTO const char *ustrp_cstr(const struct Ustrp *)
959 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
960 : USTR__COMPILE_ATTR_NONNULL_A();
961 : USTR_CONF_EI_PROTO char *ustrp_wstr(struct Ustrp *)
962 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
963 : USTR__COMPILE_ATTR_NONNULL_A();
964 :
965 : USTR_CONF_EI_PROTO int ustrp_alloc(const struct Ustrp *)
966 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
967 : USTR__COMPILE_ATTR_NONNULL_A();
968 : USTR_CONF_EI_PROTO int ustrp_exact(const struct Ustrp *)
969 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
970 : USTR__COMPILE_ATTR_NONNULL_A();
971 : USTR_CONF_EI_PROTO int ustrp_sized(const struct Ustrp *)
972 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
973 : USTR__COMPILE_ATTR_NONNULL_A();
974 : USTR_CONF_EI_PROTO int ustrp_ro(const struct Ustrp *)
975 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
976 : USTR__COMPILE_ATTR_NONNULL_A();
977 : USTR_CONF_EI_PROTO int ustrp_fixed(const struct Ustrp *)
978 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
979 : USTR__COMPILE_ATTR_NONNULL_A();
980 : USTR_CONF_EI_PROTO int ustrp_enomem(const struct Ustrp *)
981 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
982 : USTR__COMPILE_ATTR_NONNULL_A();
983 : USTR_CONF_EI_PROTO int ustrp_shared(const struct Ustrp *)
984 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
985 : USTR__COMPILE_ATTR_NONNULL_A();
986 : USTR_CONF_EI_PROTO int ustrp_limited(const struct Ustrp *)
987 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
988 : USTR__COMPILE_ATTR_NONNULL_A();
989 : USTR_CONF_EI_PROTO int ustrp_owner(const struct Ustrp *)
990 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
991 : USTR__COMPILE_ATTR_NONNULL_A();
992 : USTR_CONF_EI_PROTO
993 : void ustrp_conf(const struct Ustrp*, size_t *,size_t *,int *, size_t *,size_t *)
994 : USTR__COMPILE_ATTR_NONNULL_L((1));
995 :
996 : USTR_CONF_EI_PROTO int ustrp_setf_enomem_err(struct Ustrp *)
997 : USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */
998 : USTR_CONF_EI_PROTO int ustrp_setf_enomem_clr(struct Ustrp *)
999 : USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */
1000 :
1001 : USTR_CONF_EI_PROTO int ustrp_setf_share(struct Ustrp *)
1002 : USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */
1003 : USTR_CONF_EI_PROTO int ustrp_setf_owner(struct Ustrp *)
1004 : USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */
1005 :
1006 : USTR_CONF_EI_PROTO size_t ustrp_size(const struct Ustrp *)
1007 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
1008 : USTR__COMPILE_ATTR_NONNULL_A();
1009 : USTR_CONF_EI_PROTO size_t ustrp_size_alloc(const struct Ustrp *)
1010 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
1011 : USTR__COMPILE_ATTR_NONNULL_A();
1012 : USTR_CONF_EI_PROTO size_t ustrp_size_overhead(const struct Ustrp *)
1013 : USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET()
1014 : USTR__COMPILE_ATTR_NONNULL_A();
1015 :
1016 : #if USTR_CONF_COMPILE_USE_INLINE
1017 : USTR_CONF_II_PROTO size_t ustrp_len(const struct Ustrp *s1)
1018 888 : { return (ustr_len(&s1->s)); }
1019 : USTR_CONF_II_PROTO const char *ustrp_cstr(const struct Ustrp *s1)
1020 292 : { return (ustr_cstr(&s1->s)); }
1021 : USTR_CONF_II_PROTO char *ustrp_wstr(struct Ustrp *s1)
1022 4 : { return (ustr_wstr(&s1->s)); }
1023 :
1024 : USTR_CONF_II_PROTO int ustrp_alloc(const struct Ustrp *s1)
1025 40 : { return (ustr_alloc(&s1->s)); }
1026 : USTR_CONF_II_PROTO int ustrp_exact(const struct Ustrp *s1)
1027 20 : { return (ustr_exact(&s1->s)); }
1028 : USTR_CONF_II_PROTO int ustrp_sized(const struct Ustrp *s1)
1029 24 : { return (ustr_sized(&s1->s)); }
1030 : USTR_CONF_II_PROTO int ustrp_ro(const struct Ustrp *s1)
1031 44 : { return (ustr_ro(&s1->s)); }
1032 : USTR_CONF_II_PROTO int ustrp_fixed(const struct Ustrp *s1)
1033 12 : { return (ustr_fixed(&s1->s)); }
1034 : USTR_CONF_II_PROTO int ustrp_enomem(const struct Ustrp *s1)
1035 102 : { return (ustr_enomem(&s1->s)); }
1036 : USTR_CONF_II_PROTO int ustrp_shared(const struct Ustrp *s1)
1037 8 : { return (ustr_shared(&s1->s)); }
1038 : USTR_CONF_II_PROTO int ustrp_limited(const struct Ustrp *s1)
1039 12 : { return (ustr_limited(&s1->s)); }
1040 : USTR_CONF_II_PROTO int ustrp_owner(const struct Ustrp *s1)
1041 46 : { return (ustr_owner(&s1->s)); }
1042 : USTR_CONF_II_PROTO
1043 : void ustrp_conf(const struct Ustrp *s1, size_t *esz, size_t *ref,
1044 : int *exact, size_t *lenn, size_t *refc)
1045 32 : { ustr_conf(&s1->s, esz, ref, exact, lenn, refc); }
1046 :
1047 : USTR_CONF_II_PROTO int ustrp_setf_enomem_err(struct Ustrp *s1)
1048 4 : { return (ustr_setf_enomem_err(&s1->s)); }
1049 : USTR_CONF_II_PROTO int ustrp_setf_enomem_clr(struct Ustrp *s1)
1050 16 : { return (ustr_setf_enomem_clr(&s1->s)); }
1051 : USTR_CONF_II_PROTO int ustrp_setf_share(struct Ustrp *s1)
1052 34 : { return (ustr_setf_share(&s1->s)); }
1053 : USTR_CONF_II_PROTO int ustrp_setf_owner(struct Ustrp *s1)
1054 4 : { return (ustr_setf_owner(&s1->s)); }
1055 : USTR_CONF_II_PROTO size_t ustrp_size(const struct Ustrp *s1)
1056 36 : { return (ustr_size(&s1->s)); }
1057 : USTR_CONF_II_PROTO size_t ustrp_size_alloc(const struct Ustrp *s1)
1058 74 : { return (ustr_size_alloc(&s1->s)); }
1059 : USTR_CONF_II_PROTO size_t ustrp_size_overhead(const struct Ustrp *s1)
1060 28 : { return (ustr_size_overhead(&s1->s)); }
1061 : #endif
1062 :
1063 :
1064 : #endif
|