/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_MAIN_H #define USTR_MAIN_H 1 /* This header file is a few functions for a "simple string" ADT. The idea is * that it's so simple you can just copy this header into your project and go. * There are extra functions in various ustr-*.h files * If you require more, see Vstr etc. */ /* ---- BEG: always static config. ---- */ #ifndef USTR_CONF_HAVE_STDINT_H #define USTR_CONF_HAVE_STDINT_H 0 #endif #include /* size_t */ #include /* strlen() / etc. */ #if USTR_CONF_HAVE_STDINT_H # include /* SIZE_MAX */ # define USTR__SIZE_MAX SIZE_MAX #else # define USTR__SIZE_MAX ((size_t)-1) #endif #include /* CHAR_BIT */ #include /* va_list for *printf like functionality, * needed globally now due to cntl and concat */ #include /* vsnprintf */ #define USTR_FALSE 0 #define USTR_TRUE 1 #define USTR_NULL ((struct Ustr *) 0) #define USTRP_NULL ((struct Ustrp *)0) #define USTR_POOL_NULL ((struct Ustr_pool *)0) #ifndef USTR_CONF_USE_ASSERT /* Really defined in ustr-conf.h */ #define USTR_CONF_USE_ASSERT 0 #endif #if !defined(ustr_assert) || !defined(USTR_ASSERT) || \ !defined(ustr_assert_ret) || !defined(USTR_ASSERT_RET) # undef ustr_assert # undef USTR_ASSERT # undef ustr_assert_ret # undef USTR_ASSERT_RET # if USTR_CONF_USE_ASSERT # include # define ustr_assert(x) assert(x) # define USTR_ASSERT(x) assert(x) # define ustr_assert_ret(x, y) assert(x) # define USTR_ASSERT_RET(x, y) assert(x) # else # define ustr_assert(x) /* nothing */ # define USTR_ASSERT(x) /* nothing */ # define ustr_assert_ret(x, y) \ do { if (x){} else return (y); } while (USTR_FALSE) # define USTR_ASSERT_RET(x, y) \ do { if (x){} else return (y); } while (USTR_FALSE) # endif #endif #undef USTR_ASSERT_NO_SWITCH_DEF #if USTR_CONF_USE_ASSERT #define USTR_ASSERT_NO_SWITCH_DEF(x) break; default: USTR_ASSERT(! "" x) #else #define USTR_ASSERT_NO_SWITCH_DEF(x) break #endif #ifndef USTR_CONF_USE_EOS_MARK /* include an "end of string" mark */ #define USTR_CONF_USE_EOS_MARK 0 #endif #ifndef USTR_CONF_COMPILE_TYPEDEF /* include a typedef for Ustr */ #define USTR_CONF_COMPILE_TYPEDEF 1 #endif #ifndef USTR_CONF_INCLUDE_CODEONLY_HEADERS /* include headers which are .c's */ #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #endif #ifndef USTR_CONF_INCLUDE_INTERNAL_HEADERS /* internal functions */ # if USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #else #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 0 #endif #endif #ifndef USTR_CONF_COMPILE_USE_ATTRIBUTES /* GCC attributes, for speed/warns */ #define USTR_CONF_COMPILE_USE_ATTRIBUTES 1 #endif #ifndef USTR_CONF_COMPILE_USE_INLINE /* have very small functions inline? */ #define USTR_CONF_COMPILE_USE_INLINE 1 #endif #include "ustr-compiler.h" #ifndef USTR_CONF_USE_DYNAMIC_CONF /* make some _CONF settings into variables */ # if ! USTR_CONF_INCLUDE_CODEONLY_HEADERS && USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_USE_DYNAMIC_CONF 1 # else #define USTR_CONF_USE_DYNAMIC_CONF 0 # endif #endif /* ---- END: always static config. ---- */ #if USTR_CONF_USE_DYNAMIC_CONF # if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ (defined(__GNUC__) && (__GNUC__ > 3) && !defined(__STRICT_ANSI__)) # define USTR_CNTL_MALLOC_CHECK_BEG(x) ((x) ? \ ustr_cntl_opt(666, 0x0FF0, __FILE__, (unsigned int)__LINE__, __func__) : \ USTR_FALSE) # else # define USTR_CNTL_MALLOC_CHECK_BEG(x) ((x) ? \ ustr_cntl_opt(666, 0x0FF0, __FILE__, (unsigned int)__LINE__, "") : \ USTR_FALSE) # endif # define USTR_CNTL_MALLOC_CHECK_LVL() ustr_cntl_opt(666, 0x0FFE) # define USTR_CNTL_MALLOC_CHECK_MEM(x) ustr_cntl_opt(666, 0x0FF1, x) # define USTR_CNTL_MALLOC_CHECK_MEM_SZ(x, y) ustr_cntl_opt(666, 0x0FF2, x, y) # define USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(x, y) ustr_cntl_opt(666, 0x0FF3, x, y) # define USTR_CNTL_MALLOC_CHECK_MEM_USTR(s1) (!ustr_alloc(s1) || \ USTR_CNTL_MALLOC_CHECK_MEM_SZ(s1, ustr_size_alloc(s1))) # define USTR_CNTL_MALLOC_CHECK_MEM_USTRP(sp1) (!ustrp_alloc(sp1) || \ USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(sp1, ustrp_size_alloc(sp1))) # if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ (defined(__GNUC__) && (__GNUC__ > 3) && !defined(__STRICT_ANSI__)) # define USTR_CNTL_MALLOC_CHECK_END() \ ustr_cntl_opt(666, 0x0FFF, __FILE__, (unsigned int)__LINE__, __func__) # else # define USTR_CNTL_MALLOC_CHECK_END() \ ustr_cntl_opt(666, 0x0FFF, __FILE__, (unsigned int)__LINE__, "") # endif # define USTR_CNTL_MALLOC_CHECK_ADD(x) \ (((x) && USTR_CNTL_MALLOC_CHECK_LVL()) ? \ USTR_CNTL_MALLOC_CHECK_BEG(USTR_TRUE) : USTR_FALSE) # define USTR_CNTL_MALLOC_CHECK_DEL(x) \ (((x) && USTR_CNTL_MALLOC_CHECK_LVL() > 1) ? \ USTR_CNTL_MALLOC_CHECK_END() : USTR_FALSE) # define USTR__CNTL_MALLOC_CHECK_FIXUP_REALLOC(x, y) \ (void) ustr_cntl_opt(666, 0x0FF4, x, y) # include "ustr-cntl.h" #else # define USTR_CNTL_MALLOC_CHECK_BEG(USTR_TRUE) (USTR_FALSE) # define USTR_CNTL_MALLOC_CHECK_LVL() (0) # define USTR_CNTL_MALLOC_CHECK_MEM(x) (USTR_TRUE) /* pretend */ # define USTR_CNTL_MALLOC_CHECK_MEM_SZ(x, y) (USTR_TRUE) /* pretend */ # define USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(x, y) (USTR_TRUE) /* pretend */ # define USTR_CNTL_MALLOC_CHECK_MEM_USTR(s1) (USTR_TRUE) /* pretend */ # define USTR_CNTL_MALLOC_CHECK_MEM_USTRP(s1) (USTR_TRUE) /* pretend */ # define USTR_CNTL_MALLOC_CHECK_END(x) (USTR_TRUE) # define USTR_CNTL_MALLOC_CHECK_ADD(x) (USTR_FALSE) # define USTR_CNTL_MALLOC_CHECK_DEL(x) (USTR_TRUE) # define USTR__CNTL_MALLOC_CHECK_FIXUP_REALLOC(x, y) /* do nothing */ #endif /* ---- BEG: static/dynamic config. ---- */ /* NOTE: If you alter this it's copied into ustr-cntl-code.c */ #ifndef USTR_CONF_REF_BYTES /* how many bytes to use for reference count */ #define USTR_CONF_REF_BYTES 1 #endif #ifndef USTR_CONF_HAS_SIZE /* Include a size value */ #define USTR_CONF_HAS_SIZE USTR_FALSE #endif #ifndef USTR_CONF_EXACT_BYTES /* don't get a little extra space from malloc() */ #define USTR_CONF_EXACT_BYTES USTR_FALSE #endif /* so you can use something else, if you want */ #ifndef USTR_CONF_MALLOC #define USTR_CONF_MALLOC(x) malloc(x) #endif #ifndef USTR_CONF_REALLOC #define USTR_CONF_REALLOC(x, y) realloc((x), (y)) #endif #ifndef USTR_CONF_FREE #define USTR_CONF_FREE(x) free(x) #endif #ifndef USTR_CONF_VSNPRINTF_BEG #define USTR_CONF_VSNPRINTF_BEG vsnprintf #endif #ifndef USTR_CONF_VSNPRINTF_END #define USTR_CONF_VSNPRINTF_END vsnprintf #endif /* ---- END: static/dynamic config. ---- */ #define USTR__COMPILE_ASSERT(x, y) \ extern char ustr__compiler_assert_ ## y[1 - 2*!(x)] USTR__COMPILE_ASSERT(CHAR_BIT == 8, num_char_bits); #if USTR_CONF_HAVE_64bit_SIZE_MAX USTR__COMPILE_ASSERT(USTR__SIZE_MAX >= 0xFFFFFFFFFFFFFFFFULL, small_size_t_limit64); #else USTR__COMPILE_ASSERT(USTR__SIZE_MAX >= 0xFFFFFFFFUL, small_size_t_limit32); #endif #if ! USTR_CONF_USE_DYNAMIC_CONF # if !((USTR_CONF_REF_BYTES == 0) || (USTR_CONF_REF_BYTES == 1) || \ (USTR_CONF_REF_BYTES == 2) || (USTR_CONF_REF_BYTES == 4) || \ (USTR_CONF_HAVE_64bit_SIZE_MAX && (USTR_CONF_REF_BYTES == 8))) # error "Bad size for USTR_CONF_REF_BYTES" # endif #endif /* As the saying goes: * "you can tell a lot about the code from the data structure". * * So this is the non-magic version of the struct Ustr: * * struct Ustr * { * const char *ptr; * size_t reference_count; * size_t length; * size_t size; * * unsigned char flag_is_readonly : 1; * unsigned char flag_is_fixed : 1; * unsigned char flag_exact_byte_allocations : 1; * unsigned char flag_has_enomem_error : 1; * unsigned char flag_fail_on_alloc : 1; * }; * * ...however this "eats" memory for "small" strings, which is one reason given * why people don't use a real string ADT. * */ struct Ustr { unsigned char data[1]; /* 0b_wxyz_nnoo => * * w = allocated * x = has size * y = round up allocations (off == exact allocations) * z = memory error * nn = refn * oo = lenn * * Eg. * * 0b_0000_0000 == * "" == * not allocated, [no size], [no round up allocs], no mem err, refn=0, lenn=0 * * 0b1000_0001 == * 0xA5 == * allocated, no size, no round up allocs, no mem err, refn=0, lenn=1 * * 0b1010_0101 == * 0xA5 == * allocated, no size, round up allocs, no mem err, refn=1, lenn=1 */ }; struct Ustrp { /* This is a type for the "pool" allocated Ustr it is a seperate type as a * way to catch errors at compile time with static typing. You might think * we'd define Ustrp to be identical to Ustr, and just cast ... however * I'm 99% sure that aliasing rules screw us over if we do that. */ struct Ustr s; }; /* On ARM sizeof(struct Ustr) == 4, while sizeof("") == 1. Note that all the * unit tests pass, so it isn't accessing the padding bytes when you do: * * s1->data[0] * * ...or if it is, it isn't causing problems. Even so, it might be worth * fixing this for 2.0? */ USTR__COMPILE_ASSERT(sizeof("") <= sizeof(struct Ustr), bad_sizeof_ustr); USTR__COMPILE_ASSERT(sizeof(struct Ustrp) == sizeof(struct Ustr), bad_sizeof_ustrp); /* Unused bit patterns for data[0]: * * 0bx0xx_x100 == lenn = 0 * 0bx0xx_1x00 * 0bx0x1_xx00 * 0bx01x_xx00 * 0bx1xx_xx00 => is used in sized * 0b10xx_xx00 * * 0bx1xx_xx11 == 128bit size_t, yeh! * 0bx1xx_11xx * * 0b0xxx_x1xx == refn values for const/fixed * 0b0xxx_1xxx * * 0b00x1_xxxx == mem error for const * 0b001x_xxxx == not exact for const * */ #define USTR__BIT_ALLOCD (1<<7) #define USTR__BIT_HAS_SZ (1<<6) #define USTR__BIT_NEXACT (1<<5) #define USTR__BIT_ENOMEM (1<<4) #define USTR__BITS_RW (USTR__BIT_ALLOCD | USTR__BIT_HAS_SZ) #define USTR__BITS_FIXED USTR__BIT_HAS_SZ #define USTR__BITS_RWLIM (USTR__BIT_ALLOCD | USTR__BIT_HAS_SZ | \ USTR__BIT_NEXACT) #define USTR__BITS_LIMITED USTR__BIT_HAS_SZ /* constant string macros */ #define USTR_BEG_CONST1 "\x01" #define USTR_BEG_CONST2 "\x02" #define USTR_BEG_CONST4 "\x03" #define USTR_BEG_RO1 "\x01" /* compat. only */ #define USTR_BEG_RO2 "\x02" /* compat. only */ #define USTR_BEG_RO4 "\x03" /* compat. only */ #define USTR_BEG_FIXED2 "x112233" #define USTR_BEG_FIXED4 "x1122223333" /* Likely? */ #if USTR_CONF_HAVE_64bit_SIZE_MAX # define USTR_BEG_FIXED8 "x112222222233333333" /* Not, so much. */ #endif #if USTR_CONF_USE_EOS_MARK /* i == 0b_0110_1001 */ # define USTR_END_CONSTx "\0" # define USTR_END_ALOCDx "\0" # define USTR_END_FIXEDx "\0" #else # define USTR_END_CONSTx "" # define USTR_END_ALOCDx "" # define USTR_END_FIXEDx "" #endif USTR__COMPILE_ASSERT((sizeof(USTR_END_CONSTx) == sizeof(USTR_END_ALOCDx)), eos_alloced_bad_size); USTR__COMPILE_ASSERT((sizeof(USTR_END_CONSTx) == sizeof(USTR_END_FIXEDx)), eos_fixed_bad_size); #define USTR(x) ((struct Ustr *) x) #define USTRP(x) ((struct Ustrp *) x) #define USTR1(x1, y) \ USTR(USTR_BEG_CONST1 #x1 y USTR_END_CONSTx) #define USTR2(x1, x2, y) \ USTR(USTR_BEG_CONST2 #x2 #x1 y USTR_END_CONSTx) #define USTR4(x1, x2, x3, x4, y) \ USTR(USTR_BEG_CONST4 #x4 #x3 #x2 #x1 y USTR_END_CONSTx) #define USTRP1(x1, y) \ USTRP(USTR_BEG_CONST1 #x1 y USTR_END_CONSTx) #define USTRP2(x1, x2, y) \ USTRP(USTR_BEG_CONST2 #x2 #x1 y USTR_END_CONSTx) #define USTRP4(x1, x2, x3, x4, y) \ USTRP(USTR_BEG_CONST4 #x4 #x3 #x2 #x1 y USTR_END_CONSTx) #define USTR1_CHK(x1, y) ((*( #x1 ) == (sizeof(y) - 1)) ? \ USTR(USTR_BEG_CONST1 #x1 y USTR_END_CONSTx) : \ USTR("")) #define USTR2_CHK(x1, x2, y) \ ((((size_t)*( #x1 ) * 256 + *( #x2 )) == (sizeof(y) - 1)) ? \ USTR(USTR_BEG_CONST2 #x2 #x1 y USTR_END_CONSTx) : \ USTR("")) #define USTR4_CHK(x1, x2, x3, x4, y) \ ((((size_t)*( #x1 ) * 16777216 + (size_t)*( #x2 ) * 65536 + \ (size_t)*( #x3 ) * 256 + *( #x4 )) == (sizeof(y) - 1)) ? \ USTR(USTR_BEG_CONST4 #x4 #x3 #x2 #x1 y USTR_END_CONSTx) : \ USTR("")) #define USTRP1_CHK(x1, y) ((*( #x1 ) == (sizeof(y) - 1)) ? \ USTRP(USTR_BEG_CONST1 #x1 y USTR_END_CONSTx) : \ USTRP("")) #define USTRP2_CHK(x1, x2, y) \ ((((size_t)*( #x1 ) * 256 + *( #x2 )) == (sizeof(y) - 1)) ? \ USTRP(USTR_BEG_CONST2 #x2 #x1 y USTR_END_CONSTx) : \ USTRP("")) #define USTRP4_CHK(x1, x2, x3, x4, y) \ ((((size_t)*( #x1 ) * 16777216 + (size_t)*( #x2 ) * 65536 + \ (size_t)*( #x3 ) * 256 + *( #x4 )) == (sizeof(y) - 1)) ? \ USTRP(USTR_BEG_CONST4 #x4 #x3 #x2 #x1 y USTR_END_CONSTx) : \ USTRP("")) /* * ================ English description of struct Ustr ================ * * This strucure is very magic, as an optimization "" is a valid "structure" * for an empty string, ustr_len("") == 0, ustr_size("") == 0, * ustr_cstr("") == "". * This also works for other "static data strings" if they start with the first * four bits as 0 ... although for C const strings using this, the length has * to be manually defined correctly at compile time. * * However it is also a "space efficient" String ADT, with a managed length, * _either_ with or without reference counts (so that ustr_dup() doesn't copy) * and with or without a stored size (so growing/shrinking a lot doesn't * cause lots of malloc/realloc usage). Note that for lengths of strings, or * reference counts that need >= 8 bytes of storage the Ustr _MUST_ contain * a stored size. * * It can also track memory allocation errors over multiple function calls. * * If the first byte == 0, then it's "" as above. * Otherwise the first byte contains four flags, and 2 numbers (2 bits each). * * The 1st flag says if the string is allocated. The 2nd flag says if it has a * stored size. The 3rd flag says if it isn't using "exact allocations", if it * is ustr_len() + ustr_overhead() == ustr_size_alloc(), otherwise there might * be room to grow without doing a memory allocation call[1]. The 4th flag says * if this Ustr has had a memory allocation error. * The two numbers are the mappings for the length of the reference count, and * the length of the length. Note that this mapping changes if the 2nd flag is * set. * * [1] There is an implied "size" of the string, based an how big it is. This * is a concession for speed efficiency, although it only grows at 1.5x * not 2x which is the norm. (again, to reduce memory waste). Again if this is * too much overhead, just use exact sized allocations. * * Also NOTE if the 1st and 2nd flags are set, this means that the Ustr is in * fixed storge (like an auto array). Also if the 1st, 2nd and 3rd flags are * set, this means that the Ustr is limited, Ie. it's in fixed storge and * _CANNOT_ grow (all allocation attempts will fail). * * == If there is any more data after the above declared one they have * been allocated via. the "struct hack" method (search for more info). == * * Next, possibly, comes the reference count (of the given length[2]). * Next, if not "", comes the length of the data (of the given length[2]). * Next, if non-zero length, comes the data, which can include NIL bytes. * And finally, if not "", a NIL byte, to make sure it's always a valid C-Style * string (although obviously any embeded NIL bytes will make it look shorter * if something else just uses strlen(ustr_cstr())). * * [2] The sizes can currently be 1, 2, 4 or 8 bytes. Depending on the mapping * of the value in the first byte (length changes dynamically, as you add data). * * Examples: * * The allocated string "a", using exact allocations and no reference * counting, is the 4 bytes: * * {0x81, 0x01, 'a', 0x00} * * * The allocated string "ab", using non-exact allocations and 1 byte reference * counting (shared by 13 users), is the 6 bytes (there is no waste due to * non-exact allocations): * * {0xA5, 0x0D, 0x02, 'a', 'b', 0x00} * * * The allocated string "abcdefghijklmnop" (16 bytes, and a NIL), with * non-exact allocations 2 byte reference counting (shared by 1,003 users), is * the 24 bytes (with 3 bytes of "unused" space at the end): * * {0xA9, 0x03, 0xEB, 0x10, 'a', 'b', [...], 'o', 'p', 0x00, , , } */ struct Ustr_pool { void *(*pool_sys_malloc)(struct Ustr_pool *, size_t); void *(*pool_sys_realloc)(struct Ustr_pool *, void *, size_t, size_t); void (*pool_sys_free)(struct Ustr_pool *, void *); struct Ustr_pool *(*pool_make_subpool)(struct Ustr_pool *); void (*pool_clear)(struct Ustr_pool *); void (*pool_free)(struct Ustr_pool *); }; #if USTR_CONF_COMPILE_TYPEDEF typedef struct Ustr Ustr; typedef struct Ustrp Ustrp; typedef struct Ustr_pool Ustr_pool; #endif #define USTR_SC_INIT_AUTO(x, y, z) \ ustr_init_fixed(x, sizeof(x), y, z) #define USTR_SC_INIT_AUTO_OSTR(x, y, z) \ ustr_init_fixed(x, sizeof(x), y, sizeof(z) - 1) #define USTRP_SC_INIT_AUTO(x, y, z) \ ustrp_init_fixed(x, sizeof(x), y, z) #define USTRP_SC_INIT_AUTO_OSTR(x, y, z) \ ustrp_init_fixed(x, sizeof(x), y, sizeof(z) - 1) /* (x) && (((x) - 1) >= 0xFFFFFFFF) should really be: (x) > 0xFFFFFFFF ... but GCC likes to warn about that if x == 4, say */ #define USTR_SIZE_FIXED(x) ((x) + 1 + 2 + 4 + \ (((x) > 0xFFFF) ? 4 : 0) + \ ((USTR_CONF_HAVE_64bit_SIZE_MAX && (x) && \ (((x) - 1) >= 0xFFFFFFFF)) ? 8 : 0) + \ sizeof(USTR_END_FIXEDx)) #define USTR_ADD_OBJ(x, y) ustr_add_buf(x, y, sizeof(y)) #define USTR_ADD_OSTR(x, y) ustr_add_buf(x, y, sizeof(y) - 1) #define USTR_DUP_OBJ(y) ustr_dup_buf(y, sizeof(y)) #define USTR_DUP_OSTR(y) ustr_dup_buf(y, sizeof(y) - 1) #define USTR_DUPX_OBJ(x1, x2, x3, x4, y) \ ustr_dupx_buf(x1, x2, x3, x4, y, sizeof(y)) #define USTR_DUPX_OSTR(x1, x2, x3, x4, y) \ ustr_dupx_buf(x1, x2, x3, x4, y, sizeof(y) - 1) #define USTRP_ADD_OBJ(p, x, y) ustrp_add_buf(p, x, y, sizeof(y)) #define USTRP_ADD_OSTR(p, x, y) ustrp_add_buf(p, x, y, sizeof(y) - 1) #define USTRP_DUP_OBJ(p, y) ustrp_dup_buf(p, y, sizeof(y)) #define USTRP_DUP_OSTR(p, y) ustrp_dup_buf(p, y, sizeof(y) - 1) #define USTRP_DUPX_OBJ(p, x1, x2, x3, x4, y) \ ustrp_dupx_buf(p, x1, x2, x3, x4, y, sizeof(y)) #define USTRP_DUPX_OSTR(p, x1, x2, x3, x4, y) \ ustrp_dupx_buf(p, x1, x2, x3, x4, y, sizeof(y) - 1) #define USTR__REF_LEN(x) ustr_xi__pow2(ustr_sized(x), (x)->data[0] >> 2) #define USTR__LEN_LEN(x) ustr_xi__pow2(ustr_sized(x), (x)->data[0]) /* ---------------- Ustr "pool" because none in stdlib. ---------------- */ USTR_CONF_EI_PROTO struct Ustr_pool *ustr_pool_make_subpool(struct Ustr_pool *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_MALLOC() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO void ustr_pool_clear(struct Ustr_pool *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO void ustr_pool_free(struct Ustr_pool *); /* This converts a number n to 2**(n-1) -- for small values > 0. * Where n==0 means 0. * Oh and n==7 means 0 -- because, see above. */ USTR_CONF_EI_PROTO size_t ustr_xi__pow2(int, unsigned char) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_CONST(); /* Check if everything looks OK, should be used in debugging only. */ USTR_CONF_E_PROTO int ustr_assert_valid(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_assert_valid_subustr(const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_assert_valid(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_assert_valid_subustrp(const struct Ustrp *, size_t, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_xi__embed_val_get(const unsigned char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_xi__ref_get(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* ---------------- Ustr "member" access ---------------- */ USTR_CONF_EI_PROTO size_t ustr_len(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO const char *ustr_cstr(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO char *ustr_wstr(struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_alloc(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_exact(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_sized(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_ro(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_fixed(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_enomem(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_shared(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_limited(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_owner(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO void ustr_conf(const struct Ustr *, size_t *,size_t *,int *, size_t *,size_t *) USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO int ustr_setf_enomem_err(struct Ustr *) USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */ USTR_CONF_E_PROTO int ustr_setf_enomem_clr(struct Ustr *) USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */ USTR_CONF_E_PROTO int ustr_setf_share(struct Ustr *) USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */ USTR_CONF_E_PROTO int ustr_setf_owner(struct Ustr *) USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */ USTR_CONF_E_PROTO size_t ustr_size(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_size_alloc(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_size_overhead(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* ---------------- free Ustr's ---------------- */ USTR_CONF_E_PROTO void ustrp_free(struct Ustr_pool *, struct Ustrp *); USTR_CONF_E_PROTO void ustr_free(struct Ustr *); /* ---------------- init - helpers so others can make Ustr's ---------------- */ USTR_CONF_E_PROTO size_t ustr_init_size(size_t, size_t, int, size_t) USTR__COMPILE_ATTR_CONST() USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustr *ustr_init_alloc(void *, size_t, size_t, size_t, int, int, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustr *ustr_init_fixed(void *, size_t, int, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustrp *ustrp_init_alloc(void *, size_t, size_t, size_t, int, int, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustrp *ustrp_init_fixed(void *, size_t, int, size_t) USTR__COMPILE_ATTR_NONNULL_A(); /* ---------------- add ---------------- */ USTR_CONF_E_PROTO int ustr_add_undef(struct Ustr **, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_add_undef(struct Ustr_pool *, struct Ustrp **, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO int ustr_add_buf(struct Ustr **, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_add_cstr(struct Ustr **, const char *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_add(struct Ustr **, const struct Ustr *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_add_subustr(struct Ustr **, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_add_rep_chr(struct Ustr **, char, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_add_buf(struct Ustr_pool *, struct Ustrp **, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_EI_PROTO int ustrp_add_cstr(struct Ustr_pool *, struct Ustrp **, const char *) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_add(struct Ustr_pool *, struct Ustrp **, const struct Ustrp *) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_add_subustrp(struct Ustr_pool *, struct Ustrp **, const struct Ustrp *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_add_rep_chr(struct Ustr_pool *, struct Ustrp **, char, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); /* ---------------- del ---------------- */ USTR_CONF_E_PROTO int ustr_realloc(struct Ustr **, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_realloc(struct Ustr_pool *, struct Ustrp **, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO int ustr_del(struct Ustr **, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_del_subustr(struct Ustr **, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_del(struct Ustr_pool *, struct Ustrp **, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO int ustrp_del_subustrp(struct Ustr_pool *, struct Ustrp **, size_t,size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); /* ---------------- dup ---------------- */ USTR_CONF_E_PROTO struct Ustr *ustr_dupx_undef(size_t, size_t, int, int, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustrp *ustrp_dupx_undef(struct Ustr_pool *, size_t, size_t, int, int, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustr *ustr_dup_undef(size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_undef(struct Ustr_pool *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustr *ustr_dupx_empty(size_t, size_t, int, int) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustrp *ustrp_dupx_empty(struct Ustr_pool *, size_t, size_t, int, int) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustr *ustr_dup_empty(void) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_empty(struct Ustr_pool *) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustr *ustr_dupx_buf(size_t, size_t, int, int, const void *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustr *ustr_dup_buf(const void *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO struct Ustr *ustr_dupx_cstr(size_t, size_t, int, int, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO struct Ustr *ustr_dup_cstr(const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustr *ustr_dupx(size_t, size_t, int, int, const struct Ustr *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustr *ustr_dup(const struct Ustr *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustr * ustr_dupx_subustr(size_t, size_t, int, int, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustr *ustr_dup_subustr(const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustr *ustr_dupx_rep_chr(size_t, size_t, int, int, char, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustr *ustr_dup_rep_chr(char, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustrp *ustrp_dupx_buf(struct Ustr_pool *, size_t, size_t, int, int, const void *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_buf(struct Ustr_pool *, const void *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_EI_PROTO struct Ustrp *ustrp_dupx_cstr(struct Ustr_pool *, size_t, size_t, int, int, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); USTR_CONF_EI_PROTO struct Ustrp *ustrp_dup_cstr(struct Ustr_pool *,const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO struct Ustrp *ustrp_dupx(struct Ustr_pool *, size_t, size_t, int, int, const struct Ustrp *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); USTR_CONF_E_PROTO struct Ustrp *ustrp_dup(struct Ustr_pool *, const struct Ustrp *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO struct Ustrp *ustrp_dupx_subustrp(struct Ustr_pool *, size_t, size_t, int, int, const struct Ustrp *, size_t, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_subustrp(struct Ustr_pool *, const struct Ustrp *, size_t, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO struct Ustrp *ustrp_dupx_rep_chr(struct Ustr_pool *, size_t, size_t, int, int, char, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_rep_chr(struct Ustr_pool *, char, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); /* ---------------- shortcut ---------------- */ USTR_CONF_E_PROTO void ustr_sc_del(struct Ustr **) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO void ustr_sc_free(struct Ustr **) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO void ustr_sc_free2(struct Ustr **, struct Ustr *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO void ustrp_sc_del(struct Ustr_pool *, struct Ustrp **) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO void ustrp_sc_free(struct Ustr_pool *, struct Ustrp **) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO void ustrp_sc_free2(struct Ustr_pool *, struct Ustrp **, struct Ustrp *) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustr_sc_ensure_owner(struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO char *ustr_sc_wstr(struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_sc_ensure_owner(struct Ustr_pool *, struct Ustrp **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO char *ustrp_sc_wstr(struct Ustr_pool *, struct Ustrp **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); /* ---------------- pre inlines ---------------- */ #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO struct Ustr_pool *ustr_pool_make_subpool(struct Ustr_pool *p) { USTR_ASSERT(p); return (p->pool_make_subpool(p)); } USTR_CONF_II_PROTO void ustr_pool_clear(struct Ustr_pool *p) { USTR_ASSERT(p); p->pool_clear(p); } USTR_CONF_II_PROTO void ustr_pool_free(struct Ustr_pool *p) { if (!p) return; p->pool_free(p); } USTR_CONF_II_PROTO int ustr_alloc(const struct Ustr *s1) { return (!!(s1->data[0] & USTR__BIT_ALLOCD)); } USTR_CONF_II_PROTO int ustr_exact(const struct Ustr *s1) { return ( !(s1->data[0] & USTR__BIT_NEXACT)); } USTR_CONF_II_PROTO int ustr_sized(const struct Ustr *s1) { return (!!(s1->data[0] & USTR__BIT_HAS_SZ)); } USTR_CONF_II_PROTO int ustr_enomem(const struct Ustr *s1) { return (!!(s1->data[0] & USTR__BIT_ENOMEM)); } /* these are compound bit tests */ USTR_CONF_II_PROTO int ustr_ro(const struct Ustr *s1) { return (!(s1->data[0] & USTR__BITS_RW)); } USTR_CONF_II_PROTO int ustr_fixed(const struct Ustr *s1) { return (( s1->data[0] & USTR__BITS_RW) == USTR__BITS_FIXED); } USTR_CONF_II_PROTO int ustr_limited(const struct Ustr *s1) { return (( s1->data[0] & USTR__BITS_RWLIM) == USTR__BITS_LIMITED); } USTR_CONF_II_PROTO size_t ustr_xi__embed_val_get(const unsigned char *data, size_t len) { size_t ret = 0; switch (len) { case 0: return (-1); #if USTR_CONF_HAVE_64bit_SIZE_MAX case 8: ret |= (((size_t)data[7]) << 56); ret |= (((size_t)data[6]) << 48); ret |= (((size_t)data[5]) << 40); ret |= (((size_t)data[4]) << 32); #endif case 4: ret |= (((size_t)data[3]) << 24); ret |= (((size_t)data[2]) << 16); case 2: ret |= (((size_t)data[1]) << 8); case 1: ret |= (((size_t)data[0]) << 0); USTR_ASSERT_NO_SWITCH_DEF("Val. length bad for ustr_xi__embed_val_get()"); } return (ret); } USTR_CONF_II_PROTO size_t ustr_xi__pow2(int use_big, unsigned char len) { /* FIXME: for 2.0 or whatever make this something like: static const unsigned char map_pow2[4] = {0, 1, 2, sizeof(size_t)}; */ static const unsigned char map_big_pow2[4] = {2, 4, 8, 16}; static const unsigned char map_pow2[4] = {0, 1, 2, 4}; if (use_big) return (map_big_pow2[len & 0x03]); return (map_pow2[len & 0x03]); } USTR_CONF_II_PROTO size_t ustr_xi__ref_get(const struct Ustr *s1) { return (ustr_xi__embed_val_get(s1->data + 1, USTR__REF_LEN(s1))); } USTR_CONF_II_PROTO int ustr_shared(const struct Ustr *s1) { return (ustr_ro(s1) || (ustr_alloc(s1) && !ustr_xi__ref_get(s1))); } USTR_CONF_II_PROTO size_t ustr_len(const struct Ustr *s1) { /* NOTE: can't call ustr_assert_valid() here due to recursion, * also because assert_valid() is inline, and defined later on. */ USTR_ASSERT(s1); if (!s1->data[0]) return (0); return (ustr_xi__embed_val_get(s1->data + 1 + USTR__REF_LEN(s1), USTR__LEN_LEN(s1))); } USTR_CONF_II_PROTO const char *ustr_cstr(const struct Ustr *s1) { /* NOTE: can't call ustr_assert_valid() here due to recursion, * also because assert_valid() is inline, and defined later on. */ size_t lenn = 0; USTR_ASSERT(s1); if (!s1->data[0]) return ((const char *)s1->data); lenn = USTR__LEN_LEN(s1); if (ustr_sized(s1)) lenn *= 2; return ((const char *)(s1->data + 1 + USTR__REF_LEN(s1) + lenn)); } #endif #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-main-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-main-code.h" #endif /* ---------------- post inlines ---------------- */ #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO int ustrp_add_cstr(struct Ustr_pool *p, struct Ustrp **ps1, const char *cstr) { return (ustrp_add_buf(p, ps1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustr_add_cstr(struct Ustr **ps1, const char *cstr) { return (ustr_add_buf(ps1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO struct Ustrp *ustrp_dupx_cstr(struct Ustr_pool *p, size_t sz, size_t rb, int ex, int me, const char *c) { return (ustrp_dupx_buf(p, sz, rb, ex, me, c, strlen(c))); } USTR_CONF_II_PROTO struct Ustrp *ustrp_dup_cstr(struct Ustr_pool *p, const char *cstr) { return (ustrp_dup_buf(p, cstr, strlen(cstr))); } USTR_CONF_II_PROTO struct Ustr *ustr_dupx_cstr(size_t sz, size_t rb, int ex, int me, const char *c) { return (ustr_dupx_buf(sz, rb, ex, me, c, strlen(c))); } USTR_CONF_II_PROTO struct Ustr *ustr_dup_cstr(const char *cstr) { return (ustr_dup_buf(cstr, strlen(cstr))); } #endif /* ---------------- pool wrapper APIs ---------------- */ USTR_CONF_EI_PROTO size_t ustrp_len(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO const char *ustrp_cstr(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO char *ustrp_wstr(struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_alloc(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_exact(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_sized(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_ro(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_fixed(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_enomem(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_shared(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_limited(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_owner(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO void ustrp_conf(const struct Ustrp*, size_t *,size_t *,int *, size_t *,size_t *) USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_EI_PROTO int ustrp_setf_enomem_err(struct Ustrp *) USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */ USTR_CONF_EI_PROTO int ustrp_setf_enomem_clr(struct Ustrp *) USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */ USTR_CONF_EI_PROTO int ustrp_setf_share(struct Ustrp *) USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */ USTR_CONF_EI_PROTO int ustrp_setf_owner(struct Ustrp *) USTR__COMPILE_ATTR_NONNULL_A(); /* _can_ ignore the "error return" here */ USTR_CONF_EI_PROTO size_t ustrp_size(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_size_alloc(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_size_overhead(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO size_t ustrp_len(const struct Ustrp *s1) { return (ustr_len(&s1->s)); } USTR_CONF_II_PROTO const char *ustrp_cstr(const struct Ustrp *s1) { return (ustr_cstr(&s1->s)); } USTR_CONF_II_PROTO char *ustrp_wstr(struct Ustrp *s1) { return (ustr_wstr(&s1->s)); } USTR_CONF_II_PROTO int ustrp_alloc(const struct Ustrp *s1) { return (ustr_alloc(&s1->s)); } USTR_CONF_II_PROTO int ustrp_exact(const struct Ustrp *s1) { return (ustr_exact(&s1->s)); } USTR_CONF_II_PROTO int ustrp_sized(const struct Ustrp *s1) { return (ustr_sized(&s1->s)); } USTR_CONF_II_PROTO int ustrp_ro(const struct Ustrp *s1) { return (ustr_ro(&s1->s)); } USTR_CONF_II_PROTO int ustrp_fixed(const struct Ustrp *s1) { return (ustr_fixed(&s1->s)); } USTR_CONF_II_PROTO int ustrp_enomem(const struct Ustrp *s1) { return (ustr_enomem(&s1->s)); } USTR_CONF_II_PROTO int ustrp_shared(const struct Ustrp *s1) { return (ustr_shared(&s1->s)); } USTR_CONF_II_PROTO int ustrp_limited(const struct Ustrp *s1) { return (ustr_limited(&s1->s)); } USTR_CONF_II_PROTO int ustrp_owner(const struct Ustrp *s1) { return (ustr_owner(&s1->s)); } USTR_CONF_II_PROTO void ustrp_conf(const struct Ustrp *s1, size_t *esz, size_t *ref, int *exact, size_t *lenn, size_t *refc) { ustr_conf(&s1->s, esz, ref, exact, lenn, refc); } USTR_CONF_II_PROTO int ustrp_setf_enomem_err(struct Ustrp *s1) { return (ustr_setf_enomem_err(&s1->s)); } USTR_CONF_II_PROTO int ustrp_setf_enomem_clr(struct Ustrp *s1) { return (ustr_setf_enomem_clr(&s1->s)); } USTR_CONF_II_PROTO int ustrp_setf_share(struct Ustrp *s1) { return (ustr_setf_share(&s1->s)); } USTR_CONF_II_PROTO int ustrp_setf_owner(struct Ustrp *s1) { return (ustr_setf_owner(&s1->s)); } USTR_CONF_II_PROTO size_t ustrp_size(const struct Ustrp *s1) { return (ustr_size(&s1->s)); } USTR_CONF_II_PROTO size_t ustrp_size_alloc(const struct Ustrp *s1) { return (ustr_size_alloc(&s1->s)); } USTR_CONF_II_PROTO size_t ustrp_size_overhead(const struct Ustrp *s1) { return (ustr_size_overhead(&s1->s)); } #endif #endif