ustr-main-code.h
#ifndef USTR_MAIN_H
#error " You should have already included ustr-main.h, or just include ustr.h."
#endif
USTR_CONF_i_PROTO
int ustr__dupx_cmp_eq(size_t sz1, size_t rb1, int x1, int emem1,
size_t sz2, size_t rb2, int x2, int emem2)
{
if ((!x1 != !x2) || (!emem1 != !emem2))
return (USTR_FALSE);
if (sz1)
{
if (rb1 < 2)
rb1 = 2;
}
else if (rb1 > 4)
sz1 = 1;
if (sz2)
{
if (rb2 < 2)
rb2 = 2;
}
else if (rb2 > 4)
sz2 = 1;
return ((!sz1 == !sz2) && (rb1 == rb2));
}
USTR_CONF_i_PROTO size_t ustr__sz_get(const struct Ustr *s1)
{
size_t lenn = 0;
USTR_ASSERT(!ustr_ro(s1));
USTR_ASSERT( ustr_sized(s1));
lenn = USTR__LEN_LEN(s1);
return (ustr_xi__embed_val_get(s1->data + 1 + USTR__REF_LEN(s1) + lenn,lenn));
}
USTR_CONF_i_PROTO size_t ustr__nb(size_t num)
{
USTR_ASSERT((num <= 0xFFFFFFFF) || USTR_CONF_HAVE_64bit_SIZE_MAX);
if (num > 0xFFFFFFFF) return (8);
if (num > 0xFFFF) return (4);
if (num > 0xFF) return (2);
else return (1);
}
USTR_CONF_i_PROTO
int ustrp__assert_valid(int p, const struct Ustr *s1)
{
const char *eos_ptr = 0;
size_t eos_len = sizeof(USTR_END_ALOCDx);
size_t rbytes = 0;
size_t lbytes = 0;
size_t sbytes = 0;
size_t sz = 0;
size_t oh = 0;
USTR_ASSERT_RET(s1, USTR_FALSE);
ustr_assert_ret(USTR__ASSERT_MALLOC_CHECK_MEM(p, s1), USTR_FALSE);
if (!s1->data[0])
return (USTR_TRUE);
USTR_ASSERT(( ustr_alloc(s1) || ustr_sized(s1)) != ustr_ro(s1));
USTR_ASSERT((!ustr_alloc(s1) && ustr_sized(s1)) == ustr_fixed(s1));
USTR_ASSERT(( ustr_fixed(s1) && ustr_exact(s1)) == ustr_limited(s1));
rbytes = USTR__REF_LEN(s1);
lbytes = USTR__LEN_LEN(s1);
ustr_assert_ret(lbytes, USTR_FALSE);
if (ustr_sized(s1))
{
sbytes = lbytes;
sz = ustr__sz_get(s1);
}
oh = 1 + rbytes + lbytes + sbytes + eos_len;
USTR_ASSERT_RET(!ustr_sized(s1) || (ustr_len(s1) <= sz), USTR_FALSE);
USTR_ASSERT(!sz || (ustr__nb(sz) == lbytes) ||
((ustr__nb(sz) == 1) && (lbytes == 2)));
USTR_ASSERT_RET(!sz || (oh <= sz), USTR_FALSE);
USTR_ASSERT_RET(!sz || ((ustr_len(s1) + oh) <= sz), USTR_FALSE);
USTR_ASSERT_RET( ustr_exact(s1) || !ustr_ro(s1), USTR_FALSE);
USTR_ASSERT_RET(!ustr_enomem(s1) || !ustr_ro(s1), USTR_FALSE);
if (!USTR_CONF_USE_EOS_MARK)
{
USTR_ASSERT_RET(!ustr_cstr(s1)[ustr_len(s1)], USTR_FALSE);
return (USTR_TRUE);
}
if (ustr_ro(s1))
eos_ptr = USTR_END_CONSTx;
else if (ustr_fixed(s1))
eos_ptr = USTR_END_FIXEDx;
else
eos_ptr = USTR_END_ALOCDx;
USTR_ASSERT_RET(!memcmp(ustr_cstr(s1) + ustr_len(s1), eos_ptr, eos_len),
USTR_FALSE);
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_assert_valid(const struct Ustr *s1)
{ return (ustrp__assert_valid(1, s1)); }
USTR_CONF_I_PROTO int ustrp_assert_valid(const struct Ustrp *s1)
{ return (ustrp__assert_valid(1, &s1->s)); }
USTR_CONF_i_PROTO
size_t ustrp__assert_valid_subustr(int p, const struct Ustr *s1,
size_t pos, size_t len)
{
size_t clen = 0;
(void) p;
USTR_ASSERT(ustrp__assert_valid(p, s1));
USTR_ASSERT_RET(pos, 0);
clen = ustr_len(s1);
if (((pos == 1) || !len) && (len == clen))
return (clen);
USTR_ASSERT_RET((clen >= pos), 0);
USTR_ASSERT_RET((clen >= (len + --pos)), 0);
return (clen);
}
USTR_CONF_I_PROTO
size_t ustr_assert_valid_subustr(const struct Ustr *s1, size_t pos, size_t len)
{ return (ustrp__assert_valid_subustr(1, s1, pos, len)); }
USTR_CONF_I_PROTO
int ustrp_assert_valid_subustrp(const struct Ustrp *s1, size_t pos, size_t len)
{ return (ustrp__assert_valid_subustr(1, &s1->s, pos, len)); }
USTR_CONF_I_PROTO char *ustr_wstr(struct Ustr *s1)
{
unsigned char *data = s1->data;
size_t lenn = 0;
USTR_ASSERT(ustr_assert_valid(s1));
USTR_ASSERT_RET(!ustr_ro(s1), 0);
lenn = USTR__LEN_LEN(s1);
if (ustr_sized(s1))
lenn *= 2;
return ((char *)(data + 1 + USTR__REF_LEN(s1) + lenn));
}
USTR_CONF_I_PROTO int ustr_owner(const struct Ustr *s1)
{
USTR_ASSERT(ustr_assert_valid(s1));
if (ustr_ro(s1)) return (USTR_FALSE);
if (ustr_fixed(s1)) return (USTR_TRUE);
switch (USTR__REF_LEN(s1))
{
#if USTR_CONF_HAVE_64bit_SIZE_MAX
case 8: if (s1->data[8]) return (USTR_FALSE);
if (s1->data[7]) return (USTR_FALSE);
if (s1->data[6]) return (USTR_FALSE);
if (s1->data[5]) return (USTR_FALSE);
#endif
case 4: if (s1->data[4]) return (USTR_FALSE);
if (s1->data[3]) return (USTR_FALSE);
case 2: if (s1->data[2]) return (USTR_FALSE);
case 1: return (s1->data[1] == 1);
case 0:
USTR_ASSERT_NO_SWITCH_DEF("Ref. length bad for ustr__ref_owner()");
}
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_setf_enomem_err(struct Ustr *s1)
{
USTR_ASSERT(ustr_assert_valid(s1));
errno = USTR__ENOMEM;
if (!ustr_owner(s1))
return (USTR_FALSE);
s1->data[0] |= USTR__BIT_ENOMEM;
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_setf_enomem_clr(struct Ustr *s1)
{
USTR_ASSERT(ustr_assert_valid(s1));
errno = 0;
if (!ustr_owner(s1))
return (USTR_FALSE);
s1->data[0] &= ~USTR__BIT_ENOMEM;
return (USTR_TRUE);
}
USTR_CONF_i_PROTO void ustr__embed_val_set(unsigned char *data,
size_t len, size_t val)
{
switch (len)
{
#if USTR_CONF_HAVE_64bit_SIZE_MAX
case 8:
data[7] = (val >> 56) & 0xFF;
data[6] = (val >> 48) & 0xFF;
data[5] = (val >> 40) & 0xFF;
data[4] = (val >> 32) & 0xFF;
#endif
case 4:
data[3] = (val >> 24) & 0xFF;
data[2] = (val >> 16) & 0xFF;
case 2:
data[1] = (val >> 8) & 0xFF;
case 1:
data[0] = (val >> 0) & 0xFF;
USTR_ASSERT_NO_SWITCH_DEF("Val. length bad for ustr__embed_val_set()");
}
}
USTR_CONF_i_PROTO int ustr__ref_set(struct Ustr *s1, size_t ref)
{
size_t len = 0;
USTR_ASSERT(ustr_assert_valid(s1));
USTR_ASSERT(ustr_alloc(s1));
if (!(len = USTR__REF_LEN(s1)))
return (USTR_FALSE);
ustr__embed_val_set(s1->data + 1, len, ref);
USTR_ASSERT(ustr_assert_valid(s1));
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_setf_share(struct Ustr *s1)
{
USTR_ASSERT(ustr_assert_valid(s1));
if (!ustr_alloc(s1))
return (USTR_TRUE);
if (!ustr__ref_set(s1, 0))
return (USTR_FALSE);
USTR_ASSERT(ustr_assert_valid(s1));
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_setf_owner(struct Ustr *s1)
{
USTR_ASSERT(ustr_assert_valid(s1));
if (!ustr_alloc(s1))
return (USTR_FALSE);
ustr__ref_set(s1, 1);
USTR_ASSERT(ustr_assert_valid(s1));
return (USTR_TRUE);
}
USTR_CONF_i_PROTO void ustr__len_set(struct Ustr *s1, size_t len)
{
unsigned char *data = s1->data;
USTR_ASSERT(!ustr_ro(s1));
ustr__embed_val_set(data + 1 + USTR__REF_LEN(s1), USTR__LEN_LEN(s1), len);
USTR_ASSERT(ustr_assert_valid(s1));
}
USTR_CONF_i_PROTO void ustr__sz_set(struct Ustr *s1, size_t sz)
{
size_t lenn = 0;
USTR_ASSERT(!ustr_ro(s1));
USTR_ASSERT(ustr_sized(s1));
lenn = USTR__LEN_LEN(s1);
ustr__embed_val_set(s1->data + 1 + USTR__REF_LEN(s1) + lenn, lenn, sz);
}
USTR_CONF_i_PROTO int ustr__ref_add(struct Ustr *s1)
{
size_t ref = 0;
size_t lim = 0;
USTR_ASSERT(ustr_assert_valid(s1));
if (ustr_ro(s1))
return (USTR_TRUE);
if (ustr_fixed(s1))
return (USTR_FALSE);
switch (USTR__REF_LEN(s1))
{
#if USTR_CONF_HAVE_64bit_SIZE_MAX
case 8: if (!lim) lim = 0xFFFFFFFFFFFFFFFFULL;
#endif
case 4: if (!lim) lim = 0xFFFFFFFFUL;
case 2: if (!lim) lim = 0xFFFF;
case 1: if (!lim) lim = 0xFF;
ref = ustr_xi__ref_get(s1);
if (ref == 0)
return (USTR_TRUE);
if (ref == lim)
return (USTR_FALSE);
ustr__ref_set(s1, ref + 1);
return (USTR_TRUE);
case 0:
USTR_ASSERT_NO_SWITCH_DEF("Ref. length bad for ustr__ref_add()");
}
return (USTR_FALSE);
}
USTR_CONF_i_PROTO size_t ustr__ref_del(struct Ustr *s1)
{
USTR_ASSERT(ustr_assert_valid(s1));
if (!ustr_alloc(s1))
return (-1);
switch (USTR__REF_LEN(s1))
{
case 8:
case 4:
case 2:
case 1:
{
size_t ref = ustr_xi__ref_get(s1);
if (ref == 0)
return (-1);
if (ref == 1)
return (0);
ustr__ref_set(s1, ref - 1);
return (ref - 1);
}
case 0:
USTR_ASSERT_NO_SWITCH_DEF("Ref. length bad for ustr__ref_del()");
}
return (0);
}
USTR_CONF_I_PROTO size_t ustr_size_overhead(const struct Ustr *s1)
{
size_t lenn = 0;
USTR_ASSERT(ustr_assert_valid(s1));
if (!s1->data[0])
return (1);
lenn = USTR__LEN_LEN(s1);
if (ustr_sized(s1))
lenn *= 2;
return (1 + USTR__REF_LEN(s1) + lenn + sizeof(USTR_END_ALOCDx));
}
USTR_CONF_I_PROTO size_t ustr_size_alloc(const struct Ustr *s1)
{
size_t oh = 0;
USTR_ASSERT(ustr_assert_valid(s1));
if (ustr_sized(s1))
return (ustr__sz_get(s1));
oh = ustr_size_overhead(s1);
USTR_ASSERT((oh + ustr_len(s1)) >= oh);
if (ustr_exact(s1))
return (ustr_len(s1) + oh);
return (ustr__ns(ustr_len(s1) + oh));
}
USTR_CONF_i_PROTO void ustrp__free(struct Ustr_pool *p, struct Ustr *s1)
{
if (!s1) return;
USTR_ASSERT(ustrp__assert_valid(!!p, s1));
if (!ustr__ref_del(s1))
{
if (p)
p->pool_sys_free(p, s1);
else
USTR_CONF_FREE(s1);
}
}
USTR_CONF_I_PROTO void ustr_free(struct Ustr *s1)
{ return (ustrp__free(0, s1)); }
USTR_CONF_I_PROTO void ustrp_free(struct Ustr_pool *p, struct Ustrp *s1)
{ return (ustrp__free(p, &s1->s)); }
USTR_CONF_i_PROTO
void ustrp__sc_free2(struct Ustr_pool *p, struct Ustr **ps1, struct Ustr *s2)
{
USTR_ASSERT(ps1);
USTR_ASSERT(ustrp__assert_valid(!!p, s2));
ustrp__free(p, *ps1);
*ps1 = s2;
}
USTR_CONF_i_PROTO size_t ustr__ns(size_t num)
{
size_t min_sz = 4;
if (num > ((USTR__SIZE_MAX / 4) * 3))
return (USTR__SIZE_MAX);
while (min_sz < num)
{
size_t adder = min_sz / 2;
min_sz += adder;
if (min_sz >= num) break;
min_sz += adder;
}
return (min_sz);
}
USTR_CONF_I_PROTO size_t ustr_init_size(size_t sz, size_t rbytes, int exact,
size_t len)
{
size_t oh = 0;
size_t rsz = sz ? sz : len;
size_t lbytes = 0;
USTR_ASSERT_RET((rbytes == 0) ||
(rbytes == 1) || (rbytes == 2) || (rbytes == 4) ||
(USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)), 0);
do
{
size_t sbytes = 0;
lbytes = ustr__nb(rsz);
if (!sz && ((lbytes == 8) || (rbytes == 8)))
sz = 1;
USTR_ASSERT( (lbytes == 1) || (lbytes == 2) || (lbytes == 4) ||
(USTR_CONF_HAVE_64bit_SIZE_MAX && (lbytes == 8)));
if (sz)
{
if (rbytes <= 1)
rbytes = 2;
if (lbytes <= 1)
lbytes = 2;
sbytes = lbytes;
}
oh = 1 + rbytes + lbytes + sbytes + sizeof(USTR_END_ALOCDx);
rsz = oh + len;
if (rsz < len)
{
errno = USTR__EINVAL;
return (0);
}
USTR_ASSERT((lbytes <= ustr__nb(rsz)) ||
((lbytes == 2) && sz && (ustr__nb(rsz) == 1)));
} while (lbytes < ustr__nb(rsz));
if (exact)
return (rsz);
return (ustr__ns(rsz));
}
USTR_CONF_i_PROTO void ustr__terminate(unsigned char *ptr, int alloc,size_t len)
{
if (sizeof(USTR_END_ALOCDx) == 1)
ptr[len] = 0;
else if (alloc)
memcpy(ptr + len, USTR_END_ALOCDx, sizeof(USTR_END_ALOCDx));
else
memcpy(ptr + len, USTR_END_FIXEDx, sizeof(USTR_END_FIXEDx));
}
USTR_CONF_I_PROTO
struct Ustr *ustr_init_alloc(void *data, size_t rsz, size_t sz,
size_t rbytes, int exact, int emem, size_t len)
{
static const unsigned char map_big_pow2[9] = {-1, -1, 0, -1, 1, -1, -1, -1,2};
static const unsigned char map_pow2[5] = {0, 1, 2, -1, 3};
struct Ustr *ret = data;
int nexact = !exact;
int sized = 0;
size_t lbytes = 0;
size_t sbytes = 0;
size_t oh = 0;
const size_t eos_len = sizeof(USTR_END_ALOCDx);
USTR_ASSERT_RET((rbytes == 0) ||
(rbytes == 1) || (rbytes == 2) || (rbytes == 4) ||
(USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)), USTR_NULL);
USTR_ASSERT(data);
USTR_ASSERT(exact == !!exact);
USTR_ASSERT(emem == !!emem);
USTR_ASSERT(!sz || (sz == rsz));
USTR_ASSERT_RET(!sz || (sz > len), USTR_NULL);
if (!sz && (rbytes == 8))
sz = rsz;
lbytes = ustr__nb(sz ? sz : len);
if (!sz && (lbytes == 8))
sz = rsz;
USTR_ASSERT(lbytes == ustr__nb(sz ? sz : len));
USTR_ASSERT( (lbytes == 1) || (lbytes == 2) || (lbytes == 4) ||
(USTR_CONF_HAVE_64bit_SIZE_MAX && (lbytes == 8)));
if (sz)
{
if (sz < (1 + 2 + 2 + 1))
goto val_inval;
if (rbytes <= 1)
rbytes = 2;
if (lbytes <= 1)
lbytes = 2;
sbytes = lbytes;
}
oh = 1 + rbytes + lbytes + sbytes + eos_len;
if (rsz < (oh + len))
goto val_inval;
if (sz) sized = USTR__BIT_HAS_SZ;
if (nexact) nexact = USTR__BIT_NEXACT;
if (emem) emem = USTR__BIT_ENOMEM;
ret->data[0] = USTR__BIT_ALLOCD | sized | nexact | emem;
if (sz)
ret->data[0] |= (map_big_pow2[rbytes] << 2) | map_big_pow2[lbytes];
else
ret->data[0] |= (map_pow2[rbytes] << 2) | map_pow2[lbytes];
ustr__terminate(ret->data, USTR_TRUE, (oh - eos_len) + len);
if (sz)
ustr__sz_set(ret, sz);
ustr__len_set(ret, len);
ustr__ref_set(ret, 1);
USTR_ASSERT(ustr_assert_valid(ret));
USTR_ASSERT( ustr_alloc(ret));
USTR_ASSERT(!ustr_fixed(ret));
USTR_ASSERT(!ustr_ro(ret));
USTR_ASSERT( ustr_enomem(ret) == !!emem);
USTR_ASSERT( ustr_exact(ret) == exact);
USTR_ASSERT(!ustr_shared(ret));
USTR_ASSERT( ustr_owner(ret));
return (ret);
val_inval:
errno = USTR__EINVAL;
return (USTR_NULL);
}
USTR_CONF_I_PROTO
struct Ustrp *ustrp_init_alloc(void *data, size_t rsz, size_t sz,
size_t rbytes, int exact, int emem, size_t len)
{ return (USTRP(ustr_init_alloc(data, rsz, sz, rbytes, exact, emem, len))); }
USTR_CONF_I_PROTO
struct Ustr *ustr_init_fixed(void *data, size_t sz, int exact, size_t len)
{
struct Ustr *ret = data;
void *tmp = 0;
size_t rbytes = 0;
const int emem = USTR_FALSE;
USTR_ASSERT(sz);
if (!ustr_init_alloc(data, sz, sz, rbytes, exact, emem, len))
return (USTR_NULL);
tmp = ustr_wstr(ret);
ret->data[0] &= ~USTR__BIT_ALLOCD;
ustr__terminate(tmp, USTR_FALSE, len);
if ((rbytes = USTR__REF_LEN(ret)))
ustr__embed_val_set(ret->data + 1, rbytes, 0);
USTR_ASSERT(ustr_assert_valid(ret));
USTR_ASSERT( ustr_fixed(ret));
USTR_ASSERT(!ustr_alloc(ret));
USTR_ASSERT(!ustr_ro(ret));
USTR_ASSERT( ustr_enomem(ret) == emem);
USTR_ASSERT(!ustr_shared(ret));
USTR_ASSERT( ustr_owner(ret));
return (ret);
}
USTR_CONF_I_PROTO
struct Ustrp *ustrp_init_fixed(void *data, size_t sz, int exact, size_t len)
{ return (USTRP(ustr_init_fixed(data, sz, exact, len))); }
USTR_CONF_I_PROTO size_t ustr_size(const struct Ustr *s1)
{
size_t oh = 0;
USTR_ASSERT(ustr_assert_valid(s1));
if (ustr_sized(s1))
return (ustr__sz_get(s1) - ustr_size_overhead(s1));
if (ustr_exact(s1))
return (ustr_len(s1));
oh = ustr_size_overhead(s1);
return (ustr__ns(ustr_len(s1) + oh) - oh);
}
USTR_CONF_i_PROTO
struct Ustr *ustrp__dupx_undef(struct Ustr_pool *p, size_t sz, size_t rbytes,
int exact, int emem, size_t len)
{
struct Ustr *ret = USTR_NULL;
struct Ustr *chk = USTR_NULL;
size_t rsz = 0;
USTR_ASSERT((rbytes == 0) || (rbytes == 1) || (rbytes == 2) || (rbytes == 4)||
(USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)));
USTR_ASSERT(exact == !!exact);
USTR_ASSERT(emem == !!emem);
if (!len && ustr__dupx_cmp_eq(sz, rbytes, exact, emem, USTR__DUPX_DEF))
return (USTR(""));
if (!(rsz = ustr_init_size(sz, rbytes, exact, len)))
return (USTR_NULL);
if (p)
ret = p->pool_sys_malloc(p, rsz);
else
ret = USTR_CONF_MALLOC(rsz);
if (!ret)
{
errno = USTR__ENOMEM;
return (USTR_NULL);
}
chk = ustr_init_alloc(ret, rsz, sz ? rsz : 0, rbytes, exact, emem, len);
USTR_ASSERT(chk);
USTR_ASSERT(ustrp__assert_valid(!!p, ret));
return (ret);
}
USTR_CONF_i_PROTO
int ustrp__rw_realloc(struct Ustr_pool *p, struct Ustr **ps1,
int sized, size_t osz, size_t nsz)
{
struct Ustr *ret = USTR_NULL;
USTR_ASSERT(ustr_alloc(*ps1));
USTR_ASSERT(osz == ustr_size_alloc(*ps1));
USTR_ASSERT(sized == !!sized);
USTR_ASSERT(sized == ustr_sized(*ps1));
ustr_assert(USTR__ASSERT_MALLOC_CHECK_MEM(p, *ps1));
if (p)
ret = p->pool_sys_realloc(p, *ps1, osz, nsz);
else
ret = USTR_CONF_REALLOC(*ps1, nsz);
if (!ret)
{
ustr_setf_enomem_err(*ps1);
return (USTR_FALSE);
}
if (sized)
ustr__sz_set(ret, nsz);
*ps1 = ret;
return (USTR_TRUE);
}
USTR_CONF_i_PROTO void ustr__memcpy(struct Ustr *s1, size_t off,
const void *ptr, size_t len)
{
if (!len)
return;
memcpy(ustr_wstr(s1) + off, ptr, len);
}
USTR_CONF_i_PROTO void ustr__memset(struct Ustr *s1, size_t off,
int chr, size_t len)
{
if (!len)
return;
memset(ustr_wstr(s1) + off, chr, len);
}
USTR_CONF_i_PROTO
int ustrp__realloc(struct Ustr_pool *p, struct Ustr **ps1, size_t nsz)
{
struct Ustr *s1 = USTR_NULL;
size_t oh = 0;
size_t len = 0;
size_t msz = 0;
size_t osz = 0;
int ret = USTR_TRUE;
USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
s1 = *ps1;
if (!ustr_sized(s1) || !ustr_alloc(s1) || !ustr_owner(s1))
return (USTR_FALSE);
oh = ustr_size_overhead(s1);
len = ustr_len(s1);
msz = oh + len;
if (!nsz)
nsz = len;
nsz += oh;
osz = ustr__sz_get(s1);
if (nsz == osz)
return (USTR_TRUE);
if (nsz < msz)
return (USTR_FALSE);
if (ustr__nb(nsz) > USTR__LEN_LEN(s1))
return (USTR_FALSE);
ret = ustrp__rw_realloc(p, ps1, USTR_TRUE, osz, nsz);
USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
return (ret);
}
USTR_CONF_I_PROTO int ustr_realloc(struct Ustr **ps1, size_t sz)
{ return (ustrp__realloc(0, ps1, sz)); }
USTR_CONF_I_PROTO int ustrp_realloc(struct Ustr_pool *p,
struct Ustrp **ps1, size_t sz)
{
struct Ustr *tmp = &(*ps1)->s;
int ret = ustrp__realloc(p, &tmp, sz);
*ps1 = USTRP(tmp);
return (ret);
}
USTR_CONF_i_PROTO
int ustr__rw_mod(struct Ustr *s1, size_t nlen, size_t *sz, size_t *oh,
size_t *osz, size_t *nsz, int *alloc)
{
size_t lbytes = 0;
size_t sbytes = 0;
if (!ustr_owner(s1))
return (USTR_FALSE);
*sz = 0;
if (ustr_sized(s1))
*sz = ustr__sz_get(s1);
*osz = *sz;
lbytes = USTR__LEN_LEN(s1);
if (*sz)
sbytes = lbytes;
USTR_ASSERT(!*sz || (ustr__nb(*sz) == lbytes) ||
((ustr__nb(*sz) == 1) && (lbytes == 2)));
if (ustr__nb(nlen) > lbytes)
return (USTR_FALSE);
*oh = 1 + USTR__REF_LEN(s1) + lbytes + sbytes + sizeof(USTR_END_ALOCDx);
*nsz = *oh + nlen;
if (*nsz < nlen)
return (USTR_FALSE);
if (*nsz > USTR__SIZE_MAX)
return (USTR_FALSE);
*alloc = USTR_FALSE;
if (*nsz <= *sz)
return (USTR_TRUE);
if (!ustr_exact(s1))
*nsz = ustr__ns(*nsz);
*osz = ustr_size_alloc(s1);
if (!*sz && (*nsz == *osz))
return (USTR_TRUE);
*alloc = ustr_alloc(s1);
if (!*sz && (*nsz <= *osz))
return (USTR_TRUE);
if (!*alloc)
return (USTR_FALSE);
return (USTR_TRUE);
}
USTR_CONF_i_PROTO
int ustrp__del(struct Ustr_pool *p, struct Ustr **ps1, size_t len)
{
struct Ustr *s1 = USTR_NULL;
struct Ustr *ret = USTR_NULL;
size_t sz = 0;
size_t oh = 0;
size_t osz = 0;
size_t nsz = 0;
size_t clen = 0;
size_t nlen = 0;
int alloc = USTR_FALSE;
USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
if (!len)
return (USTR_TRUE);
s1 = *ps1;
clen = ustr_len(s1);
if (!(nlen = clen - len) &&
!(ustr_fixed(*ps1) ||
(ustr_sized(*ps1) && ustr_owner(*ps1))) &&
ustr__dupx_cmp_eq(USTR__DUPX_DEF, USTR__DUPX_FROM(s1)))
{
ustrp__sc_free2(p, ps1, USTR(""));
return (USTR_TRUE);
}
if (nlen > clen)
return (USTR_FALSE);
if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc))
{
size_t eos_len = sizeof(USTR_END_ALOCDx);
if (alloc)
{
int emem = ustr_enomem(*ps1);
USTR_ASSERT(nsz < osz);
USTR_ASSERT(!sz);
if (!ustrp__rw_realloc(p, ps1, USTR_FALSE, osz, nsz))
{
if (!p)
{
ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(*ps1, osz));
USTR__CNTL_MALLOC_CHECK_FIXUP_REALLOC(*ps1, nsz);
ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(*ps1, nsz));
}
if (!emem)
ustr_setf_enomem_clr(*ps1);
}
}
ustr__terminate((*ps1)->data, ustr_alloc(*ps1), (oh - eos_len) + nlen);
ustr__len_set(*ps1, nlen);
USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
return (USTR_TRUE);
}
USTR_ASSERT(!ustr_limited(s1));
if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen)))
{
ustr_setf_enomem_err(s1);
return (USTR_FALSE);
}
ustr__memcpy(ret, 0, ustr_cstr(s1), nlen);
ustrp__sc_free2(p, ps1, ret);
USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_del(struct Ustr **ps1, size_t len)
{ return (ustrp__del(0, ps1, len)); }
USTR_CONF_I_PROTO
int ustrp_del(struct Ustr_pool *p, struct Ustrp **ps1, size_t len)
{
struct Ustr *tmp = &(*ps1)->s;
int ret = ustrp__del(p, &tmp, len);
*ps1 = USTRP(tmp);
return (ret);
}
USTR_CONF_i_PROTO
int ustrp__del_subustr(struct Ustr_pool *p,
struct Ustr **ps1, size_t pos, size_t len)
{
struct Ustr *s1 = USTR_NULL;
struct Ustr *ret = USTR_NULL;
size_t sz = 0;
size_t oh = 0;
size_t osz = 0;
size_t nsz = 0;
size_t clen = 0;
size_t nlen = 0;
int alloc = USTR_FALSE;
const char *ocstr = 0;
USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
if (!len)
return (USTR_TRUE);
s1 = *ps1;
clen = ustrp__assert_valid_subustr(!!p, s1, pos, len);
if (!clen)
return (USTR_FALSE);
if (--pos == (clen - len))
return (ustrp__del(p, ps1, len));
nlen = clen - len;
USTR_ASSERT(nlen < clen);
if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc))
{
char *ptr = ustr_wstr(s1);
USTR_ASSERT(nlen - pos);
memmove(ptr + pos, ptr + pos + len, (nlen - pos));
return (ustrp__del(p, ps1, len));
}
USTR_ASSERT(!ustr_limited(s1));
if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen)))
{
ustr_setf_enomem_err(s1);
return (USTR_FALSE);
}
ocstr = ustr_cstr(s1);
USTR_ASSERT(pos || (nlen - pos));
ustr__memcpy(ret, 0, ocstr, pos);
ustr__memcpy(ret, pos, ocstr + pos + len, nlen - pos);
ustrp__sc_free2(p, ps1, ret);
USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_del_subustr(struct Ustr **ps1, size_t pos,size_t len)
{ return (ustrp__del_subustr(0, ps1, pos, len)); }
USTR_CONF_I_PROTO
int ustrp_del_subustrp(struct Ustr_pool *p,
struct Ustrp **ps1, size_t pos, size_t len)
{
struct Ustr *tmp = &(*ps1)->s;
int ret = ustrp__del_subustr(p, &tmp, pos, len);
*ps1 = USTRP(tmp);
return (ret);
}
USTR_CONF_I_PROTO struct Ustr *ustr_dupx_undef(size_t sz, size_t rbytes,
int exact, int emem, size_t len)
{ return (ustrp__dupx_undef(0, sz, rbytes, exact, emem, len)); }
USTR_CONF_I_PROTO
struct Ustrp *ustrp_dupx_undef(struct Ustr_pool *p, size_t sz, size_t rbytes,
int exact, int emem, size_t len)
{ return (USTRP(ustrp__dupx_undef(p, sz, rbytes, exact, emem, len))); }
USTR_CONF_I_PROTO struct Ustr *ustr_dup_undef(size_t len)
{ return (ustr_dupx_undef(USTR__DUPX_DEF, len)); }
USTR_CONF_I_PROTO struct Ustrp *ustrp_dup_undef(struct Ustr_pool *p, size_t len)
{ return (ustrp_dupx_undef(p, USTR__DUPX_DEF, len)); }
USTR_CONF_i_PROTO
struct Ustr *ustrp__dupx_empty(struct Ustr_pool *p, size_t sz, size_t rbytes,
int exact, int emem)
{
struct Ustr *s1 = ustrp__dupx_undef(p, sz, rbytes, exact, USTR_TRUE, 0);
int eret = USTR_FALSE;
if (!s1 || emem)
return (s1);
eret = ustr_setf_enomem_clr(s1);
USTR_ASSERT(eret);
return (s1);
}
USTR_CONF_I_PROTO struct Ustr *ustr_dupx_empty(size_t sz, size_t rbytes,
int exact, int emem)
{ return (ustrp__dupx_empty(0, sz, rbytes, exact, emem)); }
USTR_CONF_I_PROTO
struct Ustrp *ustrp_dupx_empty(struct Ustr_pool *p, size_t sz, size_t rbytes,
int exact, int emem)
{ return (USTRP(ustrp__dupx_empty(p, sz, rbytes, exact, emem))); }
USTR_CONF_I_PROTO struct Ustr *ustr_dup_empty(void)
{ return (ustr_dupx_empty(USTR__DUPX_DEF)); }
USTR_CONF_I_PROTO struct Ustrp *ustrp_dup_empty(struct Ustr_pool *p)
{ return (ustrp_dupx_empty(p, USTR__DUPX_DEF)); }
USTR_CONF_i_PROTO
struct Ustr *ustrp__dupx_buf(struct Ustr_pool *p, size_t sz, size_t rbytes,
int exact, int emem, const void *data, size_t len)
{
struct Ustr *s1 = ustrp__dupx_undef(p, sz, rbytes, exact, emem, len);
if (!s1)
return (USTR_NULL);
ustr__memcpy(s1, 0, data, len);
USTR_ASSERT(ustrp__assert_valid(!!p, s1));
return (s1);
}
USTR_CONF_I_PROTO
struct Ustr *ustr_dupx_buf(size_t sz, size_t rb, int exact,
int emem, const void *data, size_t len)
{ return (ustrp__dupx_buf(0, sz, rb, exact, emem, data, len)); }
USTR_CONF_I_PROTO
struct Ustrp *ustrp_dupx_buf(struct Ustr_pool *p, size_t sz, size_t rb,
int exact, int emem, const void *data, size_t len)
{ return (USTRP(ustrp__dupx_buf(p, sz, rb, exact, emem, data, len))); }
USTR_CONF_I_PROTO struct Ustr *ustr_dup_buf(const void *data, size_t len)
{ return (ustr_dupx_buf(USTR__DUPX_DEF, data, len)); }
USTR_CONF_I_PROTO
struct Ustrp *ustrp_dup_buf(struct Ustr_pool *p, const void *data, size_t len)
{ return (USTRP(ustrp_dupx_buf(p, USTR__DUPX_DEF, data, len))); }
USTR_CONF_i_PROTO
struct Ustr *ustrp__dup(struct Ustr_pool *p, const struct Ustr *s1)
{
ustr_assert(USTR__ASSERT_MALLOC_CHECK_MEM(p, s1));
if (ustr__ref_add((struct Ustr *)s1))
return ((struct Ustr *)s1);
return (ustrp__dupx_buf(p, USTR__DUPX_FROM(s1), ustr_cstr(s1), ustr_len(s1)));
}
USTR_CONF_I_PROTO struct Ustr *ustr_dup(const struct Ustr *s1)
{ return (ustrp__dup(0, s1)); }
USTR_CONF_I_PROTO
struct Ustrp *ustrp_dup(struct Ustr_pool *p, const struct Ustrp *s1)
{ return (USTRP(ustrp__dup(p, &s1->s))); }
USTR_CONF_i_PROTO
struct Ustr *ustrp__dupx(struct Ustr_pool *p, size_t sz, size_t rbytes,
int exact, int emem, const struct Ustr *s1)
{
USTR_ASSERT((rbytes == 0) || (rbytes == 1) || (rbytes == 2) || (rbytes == 4)||
(USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)));
USTR_ASSERT(exact == !!exact);
USTR_ASSERT(emem == !!emem);
if (ustr__dupx_cmp_eq(sz, rbytes, exact, emem, USTR__DUPX_FROM(s1)))
return (ustrp__dup(p, s1));
return (ustrp__dupx_buf(p, sz,rbytes,exact,emem, ustr_cstr(s1),ustr_len(s1)));
}
USTR_CONF_I_PROTO struct Ustr *ustr_dupx(size_t sz, size_t rbytes, int exact,
int emem, const struct Ustr *s1)
{ return (ustrp__dupx(0, sz, rbytes, exact, emem, s1)); }
USTR_CONF_I_PROTO
struct Ustrp *ustrp_dupx(struct Ustr_pool *p, size_t sz, size_t rbytes,
int exact, int emem, const struct Ustrp *s1)
{ return (USTRP(ustrp__dupx(p, sz, rbytes, exact, emem, &s1->s))); }
USTR_CONF_i_PROTO
struct Ustr *ustrp__dupx_subustr(struct Ustr_pool *p,
size_t sz, size_t rbytes, int exact, int emem,
const struct Ustr *s2, size_t pos, size_t len)
{
size_t clen = 0;
USTR_ASSERT(ustrp__assert_valid(!!p, s2));
USTR_ASSERT(pos);
if (!len)
return (ustrp__dupx_undef(p, sz, rbytes, exact, emem, len));
clen = ustrp__assert_valid_subustr(!!p, s2, pos, len);
if (!clen)
return (USTR_NULL);
if (len == clen)
return (ustrp__dupx(p, sz, rbytes, exact, emem, s2));
return (ustrp__dupx_buf(p,sz,rbytes,exact,emem, ustr_cstr(s2) + --pos, len));
}
USTR_CONF_I_PROTO
struct Ustr *ustr_dupx_subustr(size_t sz, size_t rbytes, int exact, int emem,
const struct Ustr *s2, size_t pos, size_t len)
{ return (ustrp__dupx_subustr(0, sz, rbytes, exact, emem, s2, pos, len)); }
USTR_CONF_I_PROTO
struct Ustrp *ustrp_dupx_subustrp(struct Ustr_pool *p,
size_t sz, size_t rbytes, int exact, int emem,
const struct Ustrp *s2, size_t pos,size_t len)
{ return (USTRP(ustrp__dupx_subustr(p, sz, rbytes, exact, emem,
&s2->s, pos, len))); }
USTR_CONF_i_PROTO
struct Ustr *ustrp__dup_subustr(struct Ustr_pool *p, const struct Ustr *s2,
size_t pos, size_t len)
{ return (ustrp__dupx_subustr(p, USTR__DUPX_FROM(s2), s2, pos, len)); }
USTR_CONF_I_PROTO struct Ustr *ustr_dup_subustr(const struct Ustr *s2,
size_t pos, size_t len)
{ return (ustrp__dup_subustr(0, s2, pos, len)); }
USTR_CONF_I_PROTO
struct Ustrp *ustrp_dup_subustrp(struct Ustr_pool *p, const struct Ustrp *s2,
size_t pos, size_t len)
{ return (USTRP(ustrp__dup_subustr(p, &s2->s, pos, len))); }
USTR_CONF_i_PROTO
struct Ustr *ustrp__dupx_rep_chr(struct Ustr_pool *p,
size_t sz, size_t rbytes, int exact, int emem,
char chr, size_t len)
{
struct Ustr *s1 = ustrp__dupx_undef(p, sz, rbytes, exact, emem, len);
if (!s1)
return (USTR_NULL);
if (len)
ustr__memset(s1, 0, chr, len);
USTR_ASSERT(ustrp__assert_valid(!!p, s1));
return (s1);
}
USTR_CONF_I_PROTO
struct Ustr *ustr_dupx_rep_chr(size_t sz, size_t rbytes, int exact, int emem,
char chr, size_t len)
{ return (ustrp__dupx_rep_chr(0, sz, rbytes, exact, emem, chr, len)); }
USTR_CONF_I_PROTO
struct Ustrp *ustrp_dupx_rep_chr(struct Ustr_pool *p,
size_t sz, size_t rbytes, int exact, int emem,
char chr, size_t len)
{ return (USTRP(ustrp__dupx_rep_chr(p, sz, rbytes, exact, emem, chr, len))); }
USTR_CONF_I_PROTO struct Ustr *ustr_dup_rep_chr(char chr, size_t len)
{ return (ustr_dupx_rep_chr(USTR__DUPX_DEF, chr, len)); }
USTR_CONF_I_PROTO
struct Ustrp *ustrp_dup_rep_chr(struct Ustr_pool *p, char chr, size_t len)
{ return (ustrp_dupx_rep_chr(p, USTR__DUPX_DEF, chr, len)); }
USTR_CONF_i_PROTO
int ustrp__add_undef(struct Ustr_pool *p, struct Ustr **ps1, size_t len)
{
struct Ustr *s1 = USTR_NULL;
struct Ustr *ret = USTR_NULL;
size_t clen = 0;
size_t nlen = 0;
size_t sz = 0;
size_t oh = 0;
size_t osz = 0;
size_t nsz = 0;
int alloc = USTR_FALSE;
USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
if (!len)
return (USTR_TRUE);
s1 = *ps1;
clen = ustr_len(s1);
if ((nlen = clen + len) < clen)
goto fail_enomem;
if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc))
{
size_t eos_len = sizeof(USTR_END_ALOCDx);
if (alloc && !ustrp__rw_realloc(p, ps1, !!sz, osz, nsz))
return (USTR_FALSE);
ustr__terminate((*ps1)->data, ustr_alloc(*ps1), (oh - eos_len) + nlen);
ustr__len_set(*ps1, nlen);
USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
return (USTR_TRUE);
}
if (ustr_limited(s1))
{
ustr_setf_enomem_err(s1);
return (USTR_FALSE);
}
if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen)))
goto fail_enomem;
ustr__memcpy(ret, 0, ustr_cstr(s1), ustr_len(s1));
ustrp__sc_free2(p, ps1, ret);
USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
return (USTR_TRUE);
fail_enomem:
ustr_setf_enomem_err(s1);
return (USTR_FALSE);
}
USTR_CONF_I_PROTO int ustr_add_undef(struct Ustr **ps1, size_t len)
{ return (ustrp__add_undef(0, ps1, len)); }
USTR_CONF_I_PROTO
int ustrp_add_undef(struct Ustr_pool *p, struct Ustrp **ps1, size_t len)
{
struct Ustr *tmp = &(*ps1)->s;
int ret = ustrp__add_undef(p, &tmp, len);
*ps1 = USTRP(tmp);
return (ret);
}
USTR_CONF_i_PROTO int ustrp__add_buf(struct Ustr_pool *p, struct Ustr **ps1,
const void *s2, size_t len)
{
if (!ustrp__add_undef(p, ps1, len))
return (USTR_FALSE);
ustr__memcpy(*ps1, ustr_len(*ps1) - len, s2, len);
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_add_buf(struct Ustr **ps1, const void *s2,size_t len)
{ return (ustrp__add_buf(0, ps1, s2, len)); }
USTR_CONF_I_PROTO int ustrp_add_buf(struct Ustr_pool *p, struct Ustrp **ps1,
const void *s2, size_t len)
{
struct Ustr *tmp = &(*ps1)->s;
int ret = ustrp__add_buf(p, &tmp, s2, len);
*ps1 = USTRP(tmp);
return (ret);
}
USTR_CONF_i_PROTO
int ustr__treat_as_buf(const struct Ustr *s1, size_t len1, size_t len2)
{
USTR_ASSERT(!len1 || (len1 == ustr_len(s1)));
USTR_ASSERT((len1 < (len1 + len2)) || !len2);
if (len1)
return (USTR_TRUE);
if (ustr_limited(s1))
return (USTR_TRUE);
if (ustr_owner(s1) && (ustr_size(s1) >= len2))
return (USTR_TRUE);
return (USTR_FALSE);
}
USTR_CONF_i_PROTO
int ustrp__add(struct Ustr_pool *p, struct Ustr **ps1, const struct Ustr *s2)
{
struct Ustr *ret = USTR_NULL;
size_t len1 = 0;
size_t len2 = 0;
USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
USTR_ASSERT(ustrp__assert_valid(!!p, s2));
len1 = ustr_len(*ps1);
len2 = ustr_len(s2);
if (len1 > (len1 + len2))
{
errno = USTR__ENOMEM;
return (USTR_FALSE);
}
if (!len2)
return (USTR_TRUE);
if ((*ps1 == s2) && ustr_owner(s2) && ustr_alloc(s2))
{
if (!ustrp__add_undef(p, ps1, len1))
return (USTR_FALSE);
ustr__memcpy(*ps1, len1, ustr_cstr(*ps1), len1);
USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
return (USTR_TRUE);
}
if (ustr__treat_as_buf(*ps1, len1, len2))
return (ustrp__add_buf(p, ps1, ustr_cstr(s2), len2));
USTR_ASSERT(!len1);
if (!(ret = ustrp__dupx(p, USTR__DUPX_FROM(*ps1), s2)))
{
ustr_setf_enomem_err(*ps1);
return (USTR_FALSE);
}
ustrp__sc_free2(p, ps1, ret);
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_add(struct Ustr **ps1, const struct Ustr *s2)
{ return (ustrp__add(0, ps1, s2)); }
USTR_CONF_I_PROTO
int ustrp_add(struct Ustr_pool *p, struct Ustrp **ps1, const struct Ustrp *s2)
{
struct Ustr *tmp = &(*ps1)->s;
int ret = ustrp__add(p, &tmp, &s2->s);
*ps1 = USTRP(tmp);
return (ret);
}
USTR_CONF_i_PROTO
int ustrp__add_subustr(struct Ustr_pool *p, struct Ustr **ps1,
const struct Ustr *s2, size_t pos, size_t len)
{
size_t clen = 0;
USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
USTR_ASSERT(ustrp__assert_valid(!!p, s2));
USTR_ASSERT(pos);
if (!len)
return (USTR_TRUE);
clen = ustrp__assert_valid_subustr(!!p, s2, pos, len);
if (!clen)
return (USTR_FALSE);
if (len == clen)
return (ustrp__add(p, ps1, s2));
if (*ps1 != s2)
return (ustrp__add_buf(p, ps1, ustr_cstr(s2) + pos - 1, len));
if (!ustrp__add_undef(p, ps1, len))
return (USTR_FALSE);
ustr__memcpy(*ps1, clen, ustr_cstr(*ps1) + pos - 1, len);
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_add_subustr(struct Ustr **ps1, const struct Ustr *s2,
size_t pos, size_t len)
{ return (ustrp__add_subustr(0, ps1, s2, pos, len)); }
USTR_CONF_I_PROTO
int ustrp_add_subustrp(struct Ustr_pool *p, struct Ustrp **ps1,
const struct Ustrp *s2, size_t pos, size_t len)
{
struct Ustr *tmp = &(*ps1)->s;
int ret = ustrp__add_subustr(p, &tmp, &s2->s, pos, len);
*ps1 = USTRP(tmp);
return (ret);
}
USTR_CONF_i_PROTO int ustrp__add_rep_chr(struct Ustr_pool *p, struct Ustr **ps1,
char chr, size_t len)
{
if (!ustrp__add_undef(p, ps1, len))
return (USTR_FALSE);
ustr__memset(*ps1, ustr_len(*ps1) - len, chr, len);
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_add_rep_chr(struct Ustr **ps1, char chr, size_t len)
{ return (ustrp__add_rep_chr(0, ps1, chr, len)); }
USTR_CONF_I_PROTO int ustrp_add_rep_chr(struct Ustr_pool *p, struct Ustrp **ps1,
char chr, size_t len)
{
struct Ustr *tmp = &(*ps1)->s;
int ret = ustrp__add_rep_chr(p, &tmp, chr, len);
*ps1 = USTRP(tmp);
return (ret);
}
USTR_CONF_I_PROTO void ustr_sc_free2(struct Ustr **ps1, struct Ustr *s2)
{ ustrp__sc_free2(0, ps1, s2); }
USTR_CONF_I_PROTO void ustrp_sc_free2(struct Ustr_pool *p,
struct Ustrp **ps1, struct Ustrp *s2)
{
struct Ustr *tmp = &(*ps1)->s;
ustrp__sc_free2(p, &tmp, &s2->s);
*ps1 = USTRP(tmp);
}
USTR_CONF_i_PROTO void ustrp__sc_free(struct Ustr_pool *p, struct Ustr **ps1)
{
USTR_ASSERT(ps1);
ustrp__free(p, *ps1);
*ps1 = USTR_NULL;
}
USTR_CONF_I_PROTO void ustr_sc_free(struct Ustr **ps1)
{ ustrp__sc_free(0, ps1); }
USTR_CONF_I_PROTO void ustrp_sc_free(struct Ustr_pool *p, struct Ustrp **ps1)
{
struct Ustr *tmp = &(*ps1)->s;
ustrp__sc_free(p, &tmp);
*ps1 = USTRP(tmp);
}
USTR_CONF_i_PROTO void ustrp__sc_del(struct Ustr_pool *p, struct Ustr **ps1)
{
if (!ustrp__del(p, ps1, ustr_len(*ps1)))
ustrp__sc_free2(p, ps1, USTR(""));
USTR_ASSERT(!ustr_len(*ps1));
}
USTR_CONF_I_PROTO void ustr_sc_del(struct Ustr **ps1)
{ ustrp__sc_del(0, ps1); }
USTR_CONF_I_PROTO void ustrp_sc_del(struct Ustr_pool *p, struct Ustrp **ps1)
{
struct Ustr *tmp = &(*ps1)->s;
ustrp__sc_del(p, &tmp);
*ps1 = USTRP(tmp);
}
USTR_CONF_I_PROTO
void ustr_conf(const struct Ustr *s1, size_t *ret_esz, size_t *ret_ref,
int *ret_exact, size_t *ret_lenn, size_t *ret_refc)
{
size_t esz = 0;
size_t ref = 0;
int exact = 0;
size_t refc = 0;
USTR_ASSERT(ustr_assert_valid(s1));
if (!ustr_alloc(s1))
{
esz = USTR_CONF_HAS_SIZE;
ref = USTR_CONF_REF_BYTES;
exact = USTR_CONF_EXACT_BYTES;
}
else
{
if (ustr_sized(s1))
esz = ustr__sz_get(s1);
else
esz = 0;
ref = USTR__REF_LEN(s1);
exact = ustr_exact(s1);
refc = !!ref;
}
USTR_ASSERT(ustr__dupx_cmp_eq(USTR__DUPX_FROM(s1),
esz, ref, exact, ustr_enomem(s1)));
if (ret_esz) *ret_esz = esz;
if (ret_ref) *ret_ref = ref;
if (ret_exact) *ret_exact = exact;
if (ret_lenn) *ret_lenn = USTR__LEN_LEN(s1);
if (ret_refc) *ret_refc = refc ? ustr_xi__ref_get(s1) : 0;
}
USTR_CONF_i_PROTO
int ustrp__sc_ensure_owner(struct Ustr_pool *p, struct Ustr **ps1)
{
struct Ustr *ret = USTR_NULL;
size_t clen = 0;
USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
if (ustr_owner(*ps1))
return (USTR_TRUE);
if (!(clen = ustr_len(*ps1)))
ret = ustrp__dupx_empty(p, USTR__DUPX_FROM(*ps1));
else
ret = ustrp__dupx_buf(p, USTR__DUPX_FROM(*ps1), ustr_cstr(*ps1), clen);
if (!ret)
return (USTR_FALSE);
ustrp__sc_free2(p, ps1, ret);
return (USTR_TRUE);
}
USTR_CONF_I_PROTO int ustr_sc_ensure_owner(struct Ustr **ps1)
{ return (ustrp__sc_ensure_owner(0, ps1)); }
USTR_CONF_I_PROTO
int ustrp_sc_ensure_owner(struct Ustr_pool *p, struct Ustrp **ps1)
{
struct Ustr *tmp = &(*ps1)->s;
int ret = ustrp__sc_ensure_owner(p, &tmp);
*ps1 = USTRP(tmp);
return (ret);
}
USTR_CONF_i_PROTO char *ustrp__sc_wstr(struct Ustr_pool *p, struct Ustr **ps1)
{
if (!ustrp__sc_ensure_owner(p, ps1))
return (USTR_FALSE);
return (ustr_wstr(*ps1));
}
USTR_CONF_I_PROTO char *ustr_sc_wstr(struct Ustr **ps1)
{ return (ustrp__sc_wstr(0, ps1)); }
USTR_CONF_I_PROTO char *ustrp_sc_wstr(struct Ustr_pool *p, struct Ustrp **ps1)
{
struct Ustr *tmp = &(*ps1)->s;
char *ret = ustrp__sc_wstr(p, &tmp);
*ps1 = USTRP(tmp);
return (ret);
}