ustr-1.0.4/0000755000076400007640000000000010763663475011522 5ustar jamesjamesustr-1.0.4/ustr-srch-dbg-code.c0000644000076400007640000000134410674563614015257 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-cmp-internal.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-srch.h" ustr-1.0.4/ustr-utf8-dbg-code.c0000644000076400007640000000130410722116137015166 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-utf8.h" ustr-1.0.4/ustr-pool.h0000644000076400007640000000233310704213526013617 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_POOL_H #define USTR_POOL_H 1 #ifndef USTR_MAIN_H #error " You should have already included ustr-main.h, or just include ustr.h." #endif /* struct Ustr_pool is in ustr-main.h, because it's an interface */ /* Dito. ustr_pool_make_subpool, ustr_pool_clear and ustr_pool_free */ #define USTR_POOL_LL_CNTL_GET_FREE_CMP (500 + 1) #define USTR_POOL_LL_CNTL_SET_FREE_CMP (500 + 2) #define USTR_POOL_LL_CNTL_GET_REALLOC (500 + 3) #define USTR_POOL_LL_CNTL_SET_REALLOC (500 + 4) USTR_CONF_E_PROTO struct Ustr_pool *ustr_pool_ll_make(void) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_MALLOC(); USTR_CONF_E_PROTO int ustr_pool_ll_cntl(struct Ustr_pool *, int, ...) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* USTR_CONF_E_PROTO struct Ustr_pool *ustr_pool_blk_make(void) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_MALLOC(); */ /* this is the "old" name for ustr_pool_ll_make() */ USTR_CONF_E_PROTO struct Ustr_pool *ustr_pool_make_pool(void) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_DEPRECATED(); #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-pool-code.h" #endif #endif ustr-1.0.4/ustr-sc-dbg-code.c0000644000076400007640000000135710722117312014711 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-spn.h" #include "ustr-utf8.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-sc.h" ustr-1.0.4/TODO0000644000076400007640000000043510722112020012156 0ustar jamesjames ADD --- DOCS! finish ref. documentation. ustr_parse_netstr() / ustr_parse_netstr2() scons build? ustr_to_uint() => like ustr_parse_uint() but no error checking etc. Ie. the aotl() of strtol() This allows attribute pure to be used, so it'll be hoisted from loops etc. ustr-1.0.4/ustr-b.h0000644000076400007640000001563110645257370013105 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_B_H #define USTR_B_H 1 #include "ustr-main.h" #if USTR_CONF_HAVE_STDINT_H /* ---------------- add ---------------- */ USTR_CONF_EI_PROTO int ustr_add_b_uint16(struct Ustr **, uint_least16_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_add_b_uint32(struct Ustr **, uint_least32_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_add_b_uint64(struct Ustr **, uint_least64_t) USTR__COMPILE_ATTR_NONNULL_A(); /* ---------------- parse ---------------- */ USTR_CONF_EI_PROTO uint_least16_t ustr_parse_b_uint16(const struct Ustr*,size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO uint_least32_t ustr_parse_b_uint32(const struct Ustr*,size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO uint_least64_t ustr_parse_b_uint64(const struct Ustr*,size_t) USTR__COMPILE_ATTR_NONNULL_A(); /* ---------------- pool APIs ---------------- */ /* ---------------- add ---------------- */ USTR_CONF_EI_PROTO int ustrp_add_b_uint16(struct Ustr_pool *, struct Ustrp **, uint_least16_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_add_b_uint32(struct Ustr_pool *, struct Ustrp **, uint_least32_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_add_b_uint64(struct Ustr_pool *, struct Ustrp **, uint_least64_t) USTR__COMPILE_ATTR_NONNULL_A(); /* ---------------- parse ---------------- */ USTR_CONF_EI_PROTO uint_least16_t ustrp_parse_b_uint16(const struct Ustrp *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO uint_least32_t ustrp_parse_b_uint32(const struct Ustrp *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO uint_least64_t ustrp_parse_b_uint64(const struct Ustrp *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO int ustr_add_b_uint16(struct Ustr **ps1, uint_least16_t data) { unsigned char buf[2]; buf[1] = data & 0xFF; data >>= 8; buf[0] = data & 0xFF; return (ustr_add_buf(ps1, buf, sizeof(buf))); } USTR_CONF_II_PROTO int ustr_add_b_uint32(struct Ustr **ps1, uint_least32_t data) { unsigned char buf[4]; buf[3] = data & 0xFF; data >>= 8; buf[2] = data & 0xFF; data >>= 8; buf[1] = data & 0xFF; data >>= 8; buf[0] = data & 0xFF; return (ustr_add_buf(ps1, buf, sizeof(buf))); } USTR_CONF_II_PROTO int ustr_add_b_uint64(struct Ustr **ps1, uint_least64_t data) { unsigned char buf[8]; buf[7] = data & 0xFF; data >>= 8; buf[6] = data & 0xFF; data >>= 8; buf[5] = data & 0xFF; data >>= 8; buf[4] = data & 0xFF; data >>= 8; buf[3] = data & 0xFF; data >>= 8; buf[2] = data & 0xFF; data >>= 8; buf[1] = data & 0xFF; data >>= 8; buf[0] = data & 0xFF; return (ustr_add_buf(ps1, buf, sizeof(buf))); } USTR_CONF_II_PROTO uint_least16_t ustr_parse_b_uint16(const struct Ustr *s1, size_t off) { uint_least16_t ret = 0; const unsigned char *ptr = 0; size_t len = ustr_len(s1); USTR_ASSERT_RET(off <= len, 0); if (len < 2) return (ret); if ((len - 2) < off) return (ret); ptr = (const unsigned char *) ustr_cstr(s1); ptr += off; ret += *ptr++; ret <<= 8; ret += *ptr++; return (ret); } USTR_CONF_II_PROTO uint_least32_t ustr_parse_b_uint32(const struct Ustr *s1, size_t off) { uint_least32_t ret = 0; const unsigned char *ptr = 0; size_t len = ustr_len(s1); USTR_ASSERT_RET(off <= len, 0); if (len < 4) return (ret); if ((len - 4) < off) return (ret); ptr = (const unsigned char *) ustr_cstr(s1); ptr += off; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; return (ret); } USTR_CONF_II_PROTO uint_least64_t ustr_parse_b_uint64(const struct Ustr *s1, size_t off) { uint_least64_t ret = 0; const unsigned char *ptr = 0; size_t len = ustr_len(s1); USTR_ASSERT_RET(off <= len, 0); if (len < 8) return (ret); if ((len - 8) < off) return (ret); ptr = (const unsigned char *) ustr_cstr(s1); ptr += off; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; return (ret); } /* ----------------------------------------------- */ /* copy and paste the above functions for pool API */ /* ----------------------------------------------- */ USTR_CONF_II_PROTO int ustrp_add_b_uint16(struct Ustr_pool *p, struct Ustrp **ps1, uint_least16_t data) { unsigned char buf[2]; buf[1] = data & 0xFF; data >>= 8; buf[0] = data & 0xFF; return (ustrp_add_buf(p, ps1, buf, sizeof(buf))); } USTR_CONF_II_PROTO int ustrp_add_b_uint32(struct Ustr_pool *p, struct Ustrp **ps1, uint_least32_t data) { unsigned char buf[4]; buf[3] = data & 0xFF; data >>= 8; buf[2] = data & 0xFF; data >>= 8; buf[1] = data & 0xFF; data >>= 8; buf[0] = data & 0xFF; return (ustrp_add_buf(p, ps1, buf, sizeof(buf))); } USTR_CONF_II_PROTO int ustrp_add_b_uint64(struct Ustr_pool *p, struct Ustrp **ps1, uint_least64_t data) { unsigned char buf[8]; buf[7] = data & 0xFF; data >>= 8; buf[6] = data & 0xFF; data >>= 8; buf[5] = data & 0xFF; data >>= 8; buf[4] = data & 0xFF; data >>= 8; buf[3] = data & 0xFF; data >>= 8; buf[2] = data & 0xFF; data >>= 8; buf[1] = data & 0xFF; data >>= 8; buf[0] = data & 0xFF; return (ustrp_add_buf(p, ps1, buf, sizeof(buf))); } USTR_CONF_II_PROTO uint_least16_t ustrp_parse_b_uint16(const struct Ustrp *s1, size_t off) { uint_least16_t ret = 0; const unsigned char *ptr = 0; size_t len = ustrp_len(s1); USTR_ASSERT_RET(off <= len, 0); if (len < 2) return (ret); if ((len - 2) < off) return (ret); ptr = (const unsigned char *) ustrp_cstr(s1); ptr += off; ret += *ptr++; ret <<= 8; ret += *ptr++; return (ret); } USTR_CONF_II_PROTO uint_least32_t ustrp_parse_b_uint32(const struct Ustrp *s1, size_t off) { uint_least32_t ret = 0; const unsigned char *ptr = 0; size_t len = ustrp_len(s1); USTR_ASSERT_RET(off <= len, 0); if (len < 4) return (ret); if ((len - 4) < off) return (ret); ptr = (const unsigned char *) ustrp_cstr(s1); ptr += off; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; return (ret); } USTR_CONF_II_PROTO uint_least64_t ustrp_parse_b_uint64(const struct Ustrp *s1, size_t off) { uint_least64_t ret = 0; const unsigned char *ptr = 0; size_t len = ustrp_len(s1); USTR_ASSERT_RET(off <= len, 0); if (len < 8) return (ret); if ((len - 8) < off) return (ret); ptr = (const unsigned char *) ustrp_cstr(s1); ptr += off; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; ret <<= 8; ret += *ptr++; return (ret); } #endif #endif #endif ustr-1.0.4/ustr-cmp-internal.h0000644000076400007640000000064610673025637015255 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_CMP_INTERNAL_H #define USTR_CMP_INTERNAL_H 1 #ifndef USTR_MAIN_H # error " You should have already included ustr-main.h, or just include ustr.h" #endif USTR_CONF_e_PROTO int ustr__memcasecmp(const void *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #endif ustr-1.0.4/ustr-main-code.h0000644000076400007640000013007410755372705014521 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #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); /* just make sure for compound "bits" tests */ 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))); /* 2 is the minimum */ 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); } /* Due to ustrp_assert_valid() being inline we can't pass 0 for * ustr_assert_valid() until we've made two ustr_assert_valid() versions. * Maybe I'll do that for 1.0.3 ... NOTE: We'd need to change the other * internal ustr_assert_valid() calls. */ USTR_CONF_I_PROTO int ustr_assert_valid(const struct Ustr *s1) { return (ustrp__assert_valid(1, s1)); } /* We can't change the API of this function until 2.0.x time, even if we want * to. But it's no big deal, as we might not want to. */ 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); } /* see comments for ustr_assert_valid() etc. */ 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) { /* NOTE: Not EI/II so we can call ustr_assert_valid() here. */ 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 with no ref. count */ } 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()"); } } /* no warn here, because most callers already know it's not going to fail */ 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); /* 0 means it's unsharable and so they are the owner */ USTR_ASSERT(ustr_assert_valid(s1)); return (USTR_TRUE); } USTR_CONF_i_PROTO void ustr__len_set(struct Ustr *s1, size_t len) { /* can only validate after the right len is in place */ 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) { /* can't validate as this is called before anything is setup */ 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 with no reference count */ 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) /* Special case this so it doesn't "go shared" * plus this is a common case and doing this is * marginally faster */ return (0); ustr__ref_set(s1, ref - 1); return (ref - 1); } case 0: /* Ustr with no reference count */ 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) { /* copy and paste so that ustr_ro() does the right thing */ 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)); } /* shortcut -- needs to be here, as lots of things calls this */ 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)); /* don't pass NULL */ 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); /* *2 is too much, we end up wasting a lot of RAM. So we do *1.5. */ while (min_sz < num) { size_t adder = min_sz / 2; min_sz += adder; if (min_sz >= num) break; min_sz += adder; } return (min_sz); } /* ---------------- init - helpers so others can make Ustr's ---------------- */ 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)); } /* NIL terminate -- with possible end marker */ 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; /* whee... */ lbytes = ustr__nb(sz ? sz : len); if (!sz && (lbytes == 8)) sz = rsz; /* whee... */ 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; /* move type between char and unsigned char */ 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); /* done here, as it might not be valid until we terminate */ ret->data[0] &= ~USTR__BIT_ALLOCD; ustr__terminate(tmp, USTR_FALSE, len); if ((rbytes = USTR__REF_LEN(ret))) /* _large_ */ 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 of available space in the string */ 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); } /* ---------------- allocations ---------------- */ /* NOTE: This is one of the two main "allocation" functions -- * this is the only thing that calls MALLOC. */ 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("")); /* We don't go to all the trouble ustr_del() does. * Which is probably better overall. */ 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)); /* printf("1. p=%p, osz=%zu, nsz=%zu\n", p, osz, nsz); */ 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) { /* can't call ustr_wstr() if len == 0, as it might be RO */ 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) { /* can't call ustr_wstr() if len == 0, as it might be RO */ if (!len) return; memset(ustr_wstr(s1) + off, chr, len); } /* ---------------- del ---------------- */ /* Fine grained management of the space allocated to a sized Ustr */ 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; /* min size */ size_t osz = 0; /* old size */ 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; /* if this overflows, we'll get it at the msz test */ osz = ustr__sz_get(s1); if (nsz == osz) /* if there's nothing to do... */ return (USTR_TRUE); if (nsz < msz) /* we can't go less than the minimum */ return (USTR_FALSE); /* Don't let the length num. bytes go up, as we might as well just dupx() */ 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); } /* Can we actually RW to this Ustr, at _this_ moment, _this_ len */ 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))); /* 2 is the minimum */ if (ustr__nb(nlen) > lbytes) return (USTR_FALSE); /* in theory we could do better, but it's _hard_ */ *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) /* 32bit overflow on 64bit size_t */ return (USTR_FALSE); *alloc = USTR_FALSE; /* don't need to allocate/deallocate anything */ if (*nsz <= *sz) return (USTR_TRUE); /* ustr_sized() */ if (!ustr_exact(s1)) *nsz = ustr__ns(*nsz); *osz = ustr_size_alloc(s1); if (!*sz && (*nsz == *osz)) return (USTR_TRUE); *alloc = ustr_alloc(s1); /* _do_ need to deallocate */ if (!*sz && (*nsz <= *osz)) return (USTR_TRUE); if (!*alloc) return (USTR_FALSE); return (USTR_TRUE); } /* NOTE: This is the main "deallocation" function (apart from plain free) -- * this is one of only three things that removes data via. REALLOC. * Others are in ustr-set.h */ 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); /* under certain conditions, we can just return "" as it's much more efficient * and we don't get anything with not doing it. */ if (!(nlen = clen - len) && /* we are deleting everything */ !(ustr_fixed(*ps1) || /* NOT in "free" space, or */ (ustr_sized(*ps1) && ustr_owner(*ps1))) && /* sized with one ref. */ ustr__dupx_cmp_eq(USTR__DUPX_DEF, USTR__DUPX_FROM(s1))) /* def. config. */ { ustrp__sc_free2(p, ps1, USTR("")); return (USTR_TRUE); } if (nlen > clen) /* underflow */ return (USTR_FALSE); if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc)) { size_t eos_len = sizeof(USTR_END_ALOCDx); if (alloc) { /* ignore errors? -- can they happen on truncate? */ 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)) /* deleting from the end */ return (ustrp__del(p, ps1, len)); nlen = clen - len; USTR_ASSERT(nlen < clen); if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc)) { /* Move everything to the begining and call ustr_del() */ 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)); /* Can't do anything sane, give up and build a new string from scratch */ 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)); /* can be both */ 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); } /* ---------------- dupx/dup ---------------- */ 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) { /* set the error bit, so we always get malloc()'d data, then clear it */ 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) { /* This ignores the const argument, because it doesn't alter the data, or at * all when ustr_ro(). */ 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) { /* the exactneustr of the options is more important than the reference */ 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)); } /* ---------------- add ---------------- */ /* NOTE: This is one of the two main "allocation" functions -- * this is one of three things funcs that gets more data via. REALLOC. * Others are in ustr-set.h */ 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) /* overflow */ 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); } /* If we can use _dup(), otherwise just pretend it's a buf+len */ 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))); /* set() uses 0 */ USTR_ASSERT((len1 < (len1 + len2)) || !len2); /* no overflow allowed */ 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)) { /* only one reference, so we can't take _cstr() before we realloc */ 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)); /* maybe only one reference, so we can't take _cstr() before we realloc */ 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); } /* ---------------- shortcut ---------------- */ 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))) /* Very unlikely, but in this case ignore saving the options/data. * We can be a little less efficient etc., but no error handling is nice. * Only thing you have to watch for is ustr_enomem() might not "work" * after a call to here. */ 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))) /* so ustr_enomem() and ustr_wstr() work */ 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); } ustr-1.0.4/ustr-main-dbg-code.c0000644000076400007640000000061310674563614015242 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO inline #include "ustr-main.h" ustr-1.0.4/.gdbinit0000644000076400007640000001127610630111754013127 0ustar jamesjames############################################################################### # gdb "user functions" to help when developing with Ustr # ############################################################################### define ustr__ret_bits set $_bit_allocd = $arg0->data[0] & 0x80 set $_bit_has_sz = $arg0->data[0] & 0x40 set $_bit_nexact = $arg0->data[0] & 0x20 set $_bit_enomem = $arg0->data[0] & 0x10 end define ustr__ret_refn ustr__ret_bits $arg0 set $__num = $arg0->data[0] & 0x0C if $_bit_has_sz && $__num == 0 set $_refn = 2 end if !$_bit_has_sz && $__num == 0 set $_refn = 0 end if $_bit_has_sz && $__num == 4 set $_refn = 4 end if !$_bit_has_sz && $__num == 4 set $_refn = 1 end if $_bit_has_sz && $__num == 8 set $_refn = 8 end if !$_bit_has_sz && $__num == 8 set $_refn = 2 end if $_bit_has_sz && $__num == 12 print "** ERROR **" end if !$_bit_has_sz && $__num == 12 set $_refn = 4 end end define pustr_refn ustr__ret_refn $arg0 printf "Ref is %u Bytes long\n", $_refn end define ustr__ret_lenn ustr__ret_bits $arg0 set $__num = $arg0->data[0] & 0x03 if $_bit_has_sz && $__num == 0 set $_lenn = 2 end if !$_bit_has_sz && $__num == 0 set $_lenn = 0 end if $_bit_has_sz && $__num == 1 set $_lenn = 4 end if !$_bit_has_sz && $__num == 1 set $_lenn = 1 end if $_bit_has_sz && $__num == 2 set $_lenn = 8 end if !$_bit_has_sz && $__num == 2 set $_lenn = 2 end if $_bit_has_sz && $__num == 3 print "** ERROR **" end if !$_bit_has_sz && $__num == 3 set $_lenn = 4 end end define pustr_lenn ustr__ret_lenn $arg0 printf "Len is %u Bytes long\n", $_lenn end define ustr__ret_num set $__ptr = $arg0->data + 1 + $arg1 set $__tmpn = $arg2 set $_num = 0 while $__tmpn > 0 set $__tmpn = $__tmpn - 1 set $_num = $_num << 8 set $_num = $_num + $__ptr[$__tmpn] end end define ustr__ret_ref ustr__ret_refn $arg0 set $_ref = 0 if $_refn ustr__ret_num $arg0 0 $_refn set $_ref = $_num end end define pustr_ref ustr__ret_ref $arg0 if $_refn printf "Ref = %u\n", $_ref else printf "Ref = \n" end end define ustr__ret_len ustr__ret_refn $arg0 ustr__ret_lenn $arg0 set $_len = 0 if $_lenn ustr__ret_num $arg0 $_refn $_lenn set $_len = $_num end end define pustr_len ustr__ret_len $arg0 printf "Len = %u\n", $_len end define ustr__ret_sz ustr__ret_refn $arg0 ustr__ret_lenn $arg0 set $_szn = 0 set $_sz = 0 if $_bit_has_sz && $_lenn set $_szn = $_lenn set $__skip = $_refn + $_lenn ustr__ret_num $arg0 $__skip $_szn set $_sz = $_num end end define pustr_szn ustr__ret_sz $arg0 printf "Sz is %u Bytes long\n", $_szn end define pustr_sz ustr__ret_sz $arg0 if $_szn printf "Sz = %u\n", $_sz else printf "Sz = \n" end end define ustr__ret_oh ustr__ret_sz $arg0 set $_oh = 0 if $_len set $_oh = 1 + $_refn + $_lenn + $_szn + 1 end end define ustr__ret_used ustr__ret_len $arg0 ustr__ret_oh $arg0 set $_used = $_len + $_oh end define pustr_used ustr__ret_used $arg0 printf "Mem used = %u\n", $_used end define pustr_cstr ustr__ret_sz $arg0 if $_lenn print (const char *)$arg0->data + 1 + $_refn + $_lenn + $_szn else print (const char *)"" end end define pustr_info if ! $arg0->data[0] printf "This Ustr is the empty string: \"\"\n" printf " Is in read-only memory.\n" else printf "This Ustr has[%x]:\n", $arg0->data[0] ustr__ret_refn $arg0 if $_bit_allocd if $_bit_has_sz printf " Does store size metadata.\n" else printf " Does not store size metadata.\n" end if !$_bit_nexact printf " Does exact byte memory allocations.\n" end else if $_bit_has_sz printf " Is in fixed memory.\n" else printf " Is in read-only memory.\n" end if !$_bit_nexact printf " Is limited to an exact byte size (all allocations fail).\n" end end if $_bit_enomem printf " Has had memory allocation errors.\n" end if $_refn printf " " pustr_refn $arg0 end printf " " pustr_lenn $arg0 printf " " pustr_szn $arg0 printf " " pustr_used $arg0 end end define pustr_all if ! $arg0 printf "This Ustr is NULL\n" else pustr_info $arg0 pustr_ref $arg0 pustr_len $arg0 pustr_sz $arg0 pustr_cstr $arg0 end end define pustr if ! $arg0 printf "This Ustr is NULL\n" else pustr_cstr $arg0 pustr_len $arg0 ustr__ret_sz $arg0 if $_szn pustr_sz $arg0 end end end ustr-1.0.4/ustr-debug.pc0000644000076400007640000000016010760727044014112 0ustar jamesjamesName: Ustr Description: String Library # FIXME: More C&P of VERSION Version: 1.0.4 Cflags: Libs: -lustr-debug ustr-1.0.4/ustr-split-dbg-code.c0000644000076400007640000000141010674563614015445 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-set.h" #include "ustr-spn.h" #include "ustr-srch.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-split.h" ustr-1.0.4/ustr-b-opt-code.c0000644000076400007640000000127310674563614014610 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-b.h" ustr-1.0.4/ustr-utf8-code.h0000644000076400007640000003755210722117045014456 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_UTF8_H #error " You should have already included ustr-utf8.h, or just include ustr.h." #endif /* import and hacked from: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c 2007-06-04 */ /* * This is an implementation of wcwidth() and wcswidth() (defined in * IEEE Std 1002.1-2001) for Unicode. * * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html * * In fixed-width output devices, Latin characters all occupy a single * "cell" position of equal width, whereas ideographic CJK characters * occupy two such cells. Interoperability between terminal-line * applications and (teletype-style) character terminals using the * UTF-8 encoding requires agreement on which character should advance * the cursor by how many cell positions. No established formal * standards exist at present on which Unicode character shall occupy * how many cell positions on character terminals. These routines are * a first attempt of defining such behavior based on simple rules * applied to data provided by the Unicode Consortium. * * For some graphical characters, the Unicode standard explicitly * defines a character-cell width via the definition of the East Asian * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes. * In all these cases, there is no ambiguity about which width a * terminal shall use. For characters in the East Asian Ambiguous (A) * class, the width choice depends purely on a preference of backward * compatibility with either historic CJK or Western practice. * Choosing single-width for these characters is easy to justify as * the appropriate long-term solution, as the CJK practice of * displaying these characters as double-width comes from historic * implementation simplicity (8-bit encoded characters were displayed * single-width and 16-bit ones double-width, even for Greek, * Cyrillic, etc.) and not any typographic considerations. * * Much less clear is the choice of width for the Not East Asian * (Neutral) class. Existing practice does not dictate a width for any * of these characters. It would nevertheless make sense * typographically to allocate two character cells to characters such * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be * represented adequately with a single-width glyph. The following * routines at present merely assign a single-cell width to all * neutral characters, in the interest of simplicity. This is not * entirely satisfactory and should be reconsidered before * establishing a formal standard in this area. At the moment, the * decision which Not East Asian (Neutral) characters should be * represented by double-width glyphs cannot yet be answered by * applying a simple rule from the Unicode database content. Setting * up a proper standard for the behavior of UTF-8 character terminals * will require a careful analysis not only of each Unicode character, * but also of each presentation form, something the author of these * routines has avoided to do so far. * * http://www.unicode.org/unicode/reports/tr11/ * * Markus Kuhn -- 2007-05-26 (Unicode 5.0) * * Permission to use, copy, modify, and distribute this software * for any purpose and without fee is hereby granted. The author * disclaims all warranties with regard to this software. * * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c */ /* auxiliary function for binary search in interval table */ USTR_CONF_i_PROTO int ustr__utf8_bisearch(USTR__UTF8_WCHAR ucs, const struct ustr__utf8_interval *table, int max) { int min = 0; int mid; if (ucs < table[0].first || ucs > table[max].last) return (USTR_FALSE); while (max >= min) { mid = (min + max) / 2; if (ucs > table[mid].last) min = mid + 1; else if (ucs < table[mid].first) max = mid - 1; else return (USTR_TRUE); } return (USTR_FALSE); } /* The following two functions define the column width of an ISO 10646 * character as follows: * * - The null character (U+0000) has a column width of 0. * * - Other C0/C1 control characters and DEL will lead to a return * value of -1. * * - Non-spacing and enclosing combining characters (general * category code Mn or Me in the Unicode database) have a * column width of 0. * * - SOFT HYPHEN (U+00AD) has a column width of 1. * * - Other format characters (general category code Cf in the Unicode * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0. * * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) * have a column width of 0. * * - Spacing characters in the East Asian Wide (W) or East Asian * Full-width (F) category as defined in Unicode Technical * Report #11 have a column width of 2. * * - All remaining characters (including all printable * ISO 8859-1 and WGL4 characters, Unicode control characters, * etc.) have a column width of 1. * * This implementation assumes that wchar_t characters are encoded * in ISO 10646. */ USTR_CONF_i_PROTO USTR__SSIZE ustr__utf8_mk_wcwidth(USTR__UTF8_WCHAR ucs) { /* sorted list of non-overlapping intervals of non-spacing characters */ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ static const struct ustr__utf8_interval combining[] = { { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 }, { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 }, { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A }, { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC }, { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F }, { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 }, { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD }, { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD }, { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 }, { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B }, { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 }, { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 }, { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF }, { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 }, { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F }, { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B }, { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F }, { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB }, { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F }, { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 }, { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD }, { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F }, { 0xE0100, 0xE01EF } }; /* test for 8-bit control characters */ if (ucs == 0) return 0; if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) return (-1); /* binary search in table of non-spacing characters */ if (ustr__utf8_bisearch(ucs, combining, sizeof(combining) / sizeof(struct ustr__utf8_interval) - 1)) return 0; /* if we arrive here, ucs is not a combining or C0/C1 control character */ return 1 + (ucs >= 0x1100 && (ucs <= 0x115f || /* Hangul Jamo init. consonants */ ucs == 0x2329 || ucs == 0x232a || (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) || /* CJK ... Yi */ (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ (ucs >= 0xffe0 && ucs <= 0xffe6) || (ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd))); } /* import and hacked from: http://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c 2007-06-04 */ /* * The utf8_check() function scans the '\0'-terminated string starting * at s. It returns a pointer to the first byte of the first malformed * or overlong UTF-8 sequence found, or NULL if the string contains * only correct UTF-8. It also spots UTF-8 sequences that could cause * trouble if converted to UTF-16, namely surrogate characters * (U+D800..U+DFFF) and non-Unicode positions (U+FFFE..U+FFFF). This * routine is very likely to find a malformed sequence if the input * uses any other encoding than UTF-8. It therefore can be used as a * very effective heuristic for distinguishing between UTF-8 and other * encodings. * * Markus Kuhn -- 2005-03-30 */ USTR_CONF_i_PROTO USTR__UTF8_WCHAR ustr__utf8_check(const unsigned char **ps) { const unsigned char *s = *ps; USTR__UTF8_WCHAR ret = 0; if (*s < 0x80) /* 0xxxxxxx */ { ret = *s; s++; } else if ((s[0] & 0xe0) == 0xc0) /* 110XXXXx 10xxxxxx */ { if (((s[1] & 0xc0) != 0x80) || ((s[0] & 0xfe) == 0xc0)) /* overlong? */ goto utf8_fail; ret = ((s[0] & 0x1f) << 6) | (s[1] & 0x3f); s += 2; } else if ((s[0] & 0xf0) == 0xe0) /* 1110XXXX 10Xxxxxx 10xxxxxx */ { if (((s[1] & 0xc0) != 0x80) || ((s[2] & 0xc0) != 0x80) || ((s[0] == 0xe0) && ((s[1] & 0xe0) == 0x80)) || /* overlong? */ ((s[0] == 0xed) && ((s[1] & 0xe0) == 0xa0)) || /* surrogate? */ ((s[0] == 0xef) && (s[1] == 0xbf) && ((s[2] & 0xfe) == 0xbe))) /* U+FFFE or U+FFFF? */ goto utf8_fail; ret = (((s[0] & 0x0f) << 12) | ((s[1] & 0x3f) << 6) | (s[2] & 0x3f)); s += 3; } else if ((s[0] & 0xf8) == 0xf0) /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */ { if (((s[1] & 0xc0) != 0x80) || ((s[2] & 0xc0) != 0x80) || ((s[3] & 0xc0) != 0x80) || ((s[0] == 0xf0) && ((s[1] & 0xf0) == 0x80)) || /* overlong? */ ((s[0] == 0xf4) && (s[1] > 0x8f)) || (s[0] > 0xf4)) /* > U+10FFFF? */ goto utf8_fail; ret = (((s[0] & 0x07) << 18) | ((s[1] & 0x3f) << 12) | ((s[2] & 0x3f) << 6) | (s[3] & 0x3f)); s += 4; } else goto utf8_fail; *ps = s; return (ret); utf8_fail: *ps = NULL; return (0); } /* See: http://en.wikipedia.org/wiki/UTF-8#Description */ USTR_CONF_e_PROTO const unsigned char *ustr__utf8_prev(const unsigned char *ptr, size_t len) { /* find the begining of the previous UTF-8 character, no checking */ while (len--) { if ((*--ptr & 0xc0) != 0x80) return (ptr); } return (0); } USTR_CONF_e_PROTO const unsigned char *ustr__utf8_next(const unsigned char *ptr) { /* find the begining of the next UTF-8 character, no checking. * -- assumes NIL termination, so no length. */ while (1) { if ((*++ptr & 0xc0) != 0x80) break; } return (ptr); } USTR_CONF_I_PROTO int ustr_utf8_valid(const struct Ustr *s1) { const unsigned char *beg = (const unsigned char *)ustr_cstr(s1); const unsigned char *scan = beg; size_t ret = 0; USTR_ASSERT(ustr_assert_valid(s1)); while (*scan) { USTR_ASSERT(ustr_len(s1) > (size_t)(scan - beg)); ustr__utf8_check(&scan); if (!scan) return (USTR_FALSE); ++ret; } USTR_ASSERT(ustr_len(s1) >= (size_t)(scan - beg)); if (ustr_len(s1) != (size_t)(scan - beg)) return (USTR_FALSE); /* string contains a NIL byte */ return (USTR_TRUE); } USTR_CONF_I_PROTO size_t ustr_utf8_len(const struct Ustr *s1) { /* this is a "fast" version */ const unsigned char *scan = (const unsigned char *)ustr_cstr(s1); size_t ret = 0; USTR_ASSERT(ustr_assert_valid(s1)); while (*scan) ret += ((*scan++ & 0xc0) != 0x80); return (ret); } USTR__SSIZE ustr_utf8_width(const struct Ustr *s1) { const unsigned char *beg = (const unsigned char *)ustr_cstr(s1); const unsigned char *scan = beg; USTR__SSIZE ret = 0; USTR_ASSERT(ustr_assert_valid(s1)); while (*scan) { USTR__UTF8_WCHAR tmp = 0; USTR_ASSERT(ustr_len(s1) > (size_t)(scan - beg)); tmp = ustr__utf8_check(&scan); if (!scan) return (0); ret += ustr__utf8_mk_wcwidth(tmp); } USTR_ASSERT(ustr_len(s1) >= (size_t)(scan - beg)); if (ustr_len(s1) != (size_t)(scan - beg)) return (0); /* string contains a NIL byte */ return (ret); } USTR_CONF_I_PROTO size_t ustr_utf8_chars2bytes(const struct Ustr *s1, size_t pos, size_t len, size_t *pret_pos) { const unsigned char *beg = (const unsigned char *)ustr_cstr(s1); const unsigned char *scan = beg; const unsigned char *ret_beg = beg; size_t ret_pos = 0; USTR_ASSERT(ustr_assert_valid_subustr(s1, pos, len) || !len); USTR_ASSERT(pret_pos || (pos == 1)); while (*scan) { const unsigned char *prev = scan; USTR_ASSERT(ustr_len(s1) > (size_t)(scan - beg)); scan = ustr__utf8_next(scan); if (!--pos) { ret_beg = prev; ret_pos = (ret_beg - beg) + 1; break; } } if (len) while (*scan && --len) { USTR_ASSERT(ustr_len(s1) > (size_t)(scan - beg)); scan = ustr__utf8_next(scan); } USTR_ASSERT(ustr_len(s1) >= (size_t)(scan - beg)); if (len > 1) return (0); /* string contains a NIL byte, or ends with a bad UTF-8 char */ if (pret_pos) *pret_pos = ret_pos; return (scan - ret_beg); } USTR_CONF_I_PROTO size_t ustr_utf8_bytes2chars(const struct Ustr *s1, size_t pos, size_t len, size_t *pret_pos) { const unsigned char *beg = (const unsigned char *)ustr_cstr(s1); const unsigned char *scan = beg; const unsigned char *ret_beg = beg; size_t clen = ustr_assert_valid_subustr(s1, pos, len); size_t unum = 0; size_t ret_pos = 0; USTR_ASSERT(pret_pos || (pos == 1)); if (!clen) /* bad position */ return (0); scan += pos; if (!(ret_beg = ustr__utf8_prev(scan, pos))) return (0); USTR_ASSERT(ustr_len(s1) >= (size_t)(scan - beg)); scan = beg; while (scan < ret_beg) unum += ((*scan++ & 0xc0) != 0x80); unum += ((*scan & 0xc0) != 0x80); ret_pos = unum; if (len) { ret_beg += len - 1; USTR_ASSERT(ustr_len(s1) >= (size_t)(ret_beg - beg)); while (scan <= ret_beg) unum += ((*scan++ & 0xc0) != 0x80); } if (pret_pos) *pret_pos = ret_pos; return (unum - ret_pos); } ustr-1.0.4/ustr-spn-dbg-code.c0000644000076400007640000000136110674563614015117 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-srch.h" #include "ustr-utf8.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-spn.h" ustr-1.0.4/ustr-set-opt-code.c0000644000076400007640000000132310674563614015156 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-fmt.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-set.h" ustr-1.0.4/ustr-split.h0000644000076400007640000001143610651531474014013 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_SPLIT_H #define USTR_SPLIT_H 1 #ifndef USTR_MAIN_H # error " You should include ustr-main.h before this file, or just ustr.h" #endif #define USTR_FLAG_SPLIT_DEF 0 #define USTR_FLAG_SPLIT_RET_SEP (1<<0) #define USTR_FLAG_SPLIT_RET_NON (1<<1) #define USTR_FLAG_SPLIT_KEEP_CONF (1<<2) USTR_CONF_E_PROTO struct Ustr *ustr_split_buf(const struct Ustr *, size_t *, const void *, size_t, struct Ustr *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 2,3)); USTR_CONF_E_PROTO struct Ustr *ustr_split(const struct Ustr *, size_t *, const struct Ustr *, struct Ustr *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 2,3)); USTR_CONF_EI_PROTO struct Ustr *ustr_split_cstr(const struct Ustr *, size_t *, const char *, struct Ustr *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 2,3)); USTR_CONF_E_PROTO struct Ustrp *ustrp_split_buf(struct Ustr_pool *, const struct Ustrp *,size_t *, const void *, size_t, struct Ustrp *,unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3,4)); USTR_CONF_E_PROTO struct Ustrp *ustrp_split(struct Ustr_pool *, const struct Ustrp *, size_t *, const struct Ustrp *, struct Ustrp *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3,4)); USTR_CONF_EI_PROTO struct Ustrp *ustrp_split_cstr(struct Ustr_pool *,const struct Ustrp *,size_t *, const char *, struct Ustrp *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3,4)); USTR_CONF_E_PROTO struct Ustr *ustr_split_spn_chrs(const struct Ustr *, size_t *, const char *, size_t, struct Ustr *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 2,3)); USTR_CONF_E_PROTO struct Ustr *ustr_split_spn(const struct Ustr *, size_t *, const struct Ustr *, struct Ustr *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 2,3)); USTR_CONF_EI_PROTO struct Ustr *ustr_split_spn_cstr(const struct Ustr *, size_t *, const char *, struct Ustr *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 2,3)); USTR_CONF_E_PROTO struct Ustrp *ustrp_split_spn_chrs(struct Ustr_pool *, const struct Ustrp *, size_t *, const char *, size_t, struct Ustrp *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3,4)); USTR_CONF_E_PROTO struct Ustrp *ustrp_split_spn(struct Ustr_pool *, const struct Ustrp *,size_t *, const struct Ustrp *, struct Ustrp *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3,4)); USTR_CONF_EI_PROTO struct Ustrp *ustrp_split_spn_cstr(struct Ustr_pool *, const struct Ustrp *, size_t *, const char *, struct Ustrp *, unsigned int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3,4)); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-split-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-split-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO struct Ustr *ustr_split_cstr(const struct Ustr *s1, size_t *off, const char *cstr, struct Ustr *ret, unsigned int flags) { return (ustr_split_buf(s1, off, cstr, strlen(cstr), ret, flags)); } USTR_CONF_II_PROTO struct Ustrp *ustrp_split_cstr(struct Ustr_pool *p, const struct Ustrp *sp1, size_t *off, const char *cstr, struct Ustrp *ret, unsigned int flgs) { return (ustrp_split_buf(p, sp1, off, cstr, strlen(cstr), ret, flgs)); } USTR_CONF_II_PROTO struct Ustr *ustr_split_spn_cstr(const struct Ustr *s1, size_t *off, const char *cstr, struct Ustr *ret, unsigned int flags) { return (ustr_split_spn_chrs(s1, off, cstr, strlen(cstr), ret, flags)); } USTR_CONF_II_PROTO struct Ustrp *ustrp_split_spn_cstr(struct Ustr_pool *p, const struct Ustrp *sp1, size_t *off, const char *cstr, struct Ustrp *ret, unsigned int flgs) { return (ustrp_split_spn_chrs(p, sp1, off, cstr, strlen(cstr), ret, flgs)); } #endif #endif ustr-1.0.4/ChangeLog0000644000076400007640000010775210763646212013276 0ustar jamesjames2008-03-05 James Antill * NEWS: Release 1.0.4 2008-02-19 James Antill * ustr-sub-code.h (ustr_sub_subustr): Speedup when subustr == ustr. (ustr_sc_sub_subustr): Speedup when subustr == ustr. * ustr-ins-code.h (ustr_ins_subustr): Speedup when subustr == ustr. 2008-02-15 James Antill * ustr-ins-code.h (ustr_ins): Make sure ustr_ins(&x, p, x) is valid. (ustr_ins_subustr): Dito. * ustr-replace-code.h (ustr_replace): Make sure ustr_replace(&x, x, x,0) is valid. * ustr-sub-code.h (ustr_sub): Make sure ustr_sub(&x, p, x) is valid. (ustr_sub_subustr): Dito. (ustr_sc_sub): Dito. (ustr_sc_sub_subustr): Dito. * ustr-spn-code.h (ustr_cspn_chr_rev): Fix for when using off > 0. 2008-02-14 James Antill * ustr-sc-code.h (ustr_sc_vconcatx): Added function. (ustr_sc_concatx): Added function. (ustr_sc_vconcat): Added function. (ustr_sc_concat): Added function. (ustr_sc_vjoinx): Added function. (ustr_sc_joinx): Added function. (ustr_sc_vjoin): Added function. (ustr_sc_join): Added function. 2008-02-13 James Antill * ustr-set-code.h (ustr_set_subustr): Minor opt. for ustr_set_subustr() in the delete everything case. * ustr-fmt-code.h (ustr__retard_vfmt_ret): Fix use of bare va_copy. 2008-01-14 James Antill * NEWS: Release 1.0.3 2007-11-30 James Antill * Makefile (install-multilib-linux): Add Linux multilib support, as that makes Fedora happy. 2007-11-24 James Antill * ustr-sc-code.h (ustr_sc_ltrim): Added function. (ustr_sc_rtrim): Added function. (ustr_sc_trim): Added function. * T-installed/tst_vstr_chk.c (main): Add test for new option. * ustr-cntl.h (struct Ustr_cntl_fmt): Add a way to use another vsnprintf() type function, for instance vstr_add_vfmt(). 2007-10-29 James Antill * NEWS: Release 1.0.2 2007-10-27 James Antill * ustr-main-code.h (ustr_conf): Add a reference count argument. * ustr-main.h (USTR_CNTL_MALLOC_CHECK_MEM_SZ): Renamed function to follow order of arguments. (USTR_CNTL_MALLOC_CHECK_MEM_MINSZ): Renamed function to follow order of arguments. (USTR_CNTL_MALLOC_CHECK_MEM_USTR): Added function to ease calls to other USTR_CNTL_MALLOC_CHECK_MEM_*() functions. (USTR_CNTL_MALLOC_CHECK_MEM_USTRP): Added function. * ustr-main-code.h (ustr_conf): Remove the refnn argument as at was the exact same thing as the ref argument. * ustr-cntl.h (USTR_CNTL_OPT_GET_MC_M_SCRUB): Added control option for malloc check scrubbing. (USTR_CNTL_OPT_SET_MC_M_SCRUB): Added control option for malloc check scrubbing. (USTR_CNTL_OPT_GET_MC_F_SCRUB): Added control option for malloc check scrubbing. (USTR_CNTL_OPT_SET_MC_F_SCRUB): Added control option for malloc check scrubbing. (USTR_CNTL_OPT_GET_MC_R_SCRUB): Added control option for malloc check scrubbing. (USTR_CNTL_OPT_SET_MC_R_SCRUB): Added control option for malloc check scrubbing. * ustr-cntl-code.h (ustr__cntl_mc_setup_malloc): Added enablement of malloc checking via. environment variables. 2007-10-25 James Antill * ustr-main.h (USTR_CNTL_MALLOC_CHECK_LVL): Added function. 2007-10-24 James Antill * ustr-main.h (USTR_CNTL_MALLOC_CHECK_BEG): Use as a general enter/exit function macro ... so we can tell much better where the problems are. * ustr-main.h (USTR_CNTL_MALLOC_CHECK_EMPTY): Remove function. * ustr-main.h (USTR1_CHK): Added macro function. (USTR2_CHK): Added macro function. (USTR4_CHK): Added macro function. 2007-10-23 James Antill * examples/custr.c (main): Add new example, creates constant ustr's from input. 2007-10-22 James Antill * ustr-import.in: Missed fixes needed for install testing. * libustr.ver: Use different versions for different minor lib. versions. 2007-10-21 James Antill * ustr-import.in: Fixes needed for bugs found by installed testing. * ustr-import.in: Fix default ref bytes to be the same as when using the library. * ustr-conf.h.in: Fix pre-computed config. to be the same as that delivered. * ustr-cntl-code.h: Changed dynamic config. to be the same as the static config. -- Oops. 2007-10-17 James Antill * ustr-main.h (USTR_SC_INIT_AUTO_OSTR): Added macro function. 2007-10-15 James Antill * ustr-io-code.h (ustrp__io_getdelim): Return the last line of a file, even if it doesn't match the delimiter. * examples/fgrep.c (fp_loop): Fixup memory allocations free's. (fp_loop): Remove dual IO strategy, going with obvious implementation. * ustr-pool-code.h (ustr__pool_ll_sys_realloc): Always call the fixup function for pool realloc, as it can be used in non-debug programs. 2007-10-13 James Antill * ustr-main-code.h (ustrp__del): Change recorded size in malloc-check for realloc() downgrade that failed. * ustr-pool-code.h (ustr__pool_ll_sys_realloc): Change the interface contract to say that the "oldsz" is a minimum. (ustr__pool_ll_sys_realloc): Change recorded size in malloc-check for realloc() downgrade. * ustr-main.h (USTR_CNTL_MALLOC_CHECK_MINSZ_MEM): Add function. * ustr-cntl-code.h (ustr_cntl_opt): Remove warn_unused_ret. * ustr-main-code.h (ustr__rw_add): Fixup alloc return value. (ustr__rw_mod): Remove ustr__rw_add() and ustr__rw_del(), use this instead. * ustr-main.h (USTR_CNTL_MALLOC_CHECK_BEG): Rename function from USTR_CNTL_MALLOC_CHECK_ENABLE. (USTR_CNTL_MALLOC_CHECK_END): Rename function from USTR_CNTL_MALLOC_CHECK_DISABLE. * ustr-pool-code.h (ustr_pool_ll_make): Choose better name for linked list pool API. (ustr_pool_ll_make): Add malloc check asserts for most of pool API. (ustr_pool_ll_cntl): Add function. 2007-10-11 James Antill * ustr-main.h (USTR_CNTL_MALLOC_CHECK_DISABLE): Add function. 2007-10-10 James Antill * ustr-main.h (USTR_CNTL_MALLOC_CHECK_ENABLE): Add function. (USTR_CNTL_MALLOC_CHECK_MEM): Add function. (USTR_CNTL_MALLOC_CHECK_SZ_MEM): Add function. (USTR_CNTL_MALLOC_CHECK_EMPTY): Add function. 2007-10-06 James Antill * ustr-sc-code.h (ustrp_sc_export): Added function, redefined ustr_sc_export() to do entire ustr. * examples/txt2html.c (main): Added another example program. 2007-10-05 James Antill * ustr-sc-code.h (ustr_sc_export): Added function. 2007-09-21 James Antill * ustr-srch-code.h (ustr_srch_buf_fwd): Change search for len=0 to return zero when the string is empty. (ustr_srch_buf_rev): Change search for len=0 to return zero when the string is empty. (ustr_srch_rep_chr_fwd): Change search for len=0 to return zero when the string is empty. (ustr_srch_rep_chr_rev): Change search for len=0 to return zero when the string is empty. 2007-09-20 James Antill * ustr-srch-code.h (ustr__memcasechr): Have the args. the same way around as memchr() 2007-09-15 James Antill * ustr-main-code.h (ustr__ref_del): Speed improvment for ustr_free(). * examples/fgrep.c (fgrep): Add some more GNU options, and give it a minor speed boost. * ustr-io-code.h (ustr_io_getdelim): Fix hanging errno problem. * libustr.ver: Add missing symbol versions from the 1.0.1 release. * scripts/list_functions_src.pl: Add missing filenames. * ustr-srch-code.h (ustr_srch_case_chr_fwd): Added function. (ustr_srch_case_chr_rev): Added function. (ustr_srch_case_buf_fwd): Added function. (ustr_srch_case_buf_rev): Added function. (ustr_srch_case_subustr_fwd): Added function. (ustr_srch_case_subustr_rev): Added function. (ustr_srch_case_rep_chr_fwd): Added function. (ustr_srch_case_rep_chr_rev): Added function. * ustr-cmp-internal.h (ustr__memcasecmp): Made memcasecmp available outside cmp. * ustr-srch-code.h (ustr__memrepchr): Rename internal functions, as there is no existing function with this name. 2007-09-12 James Antill * libustr.ver: Add missing symbol versions from the 1.0.1 release. 2007-09-11 James Antill * ustr-cmp-code.h (ustr_cmp_prefix_subustr_eq): Added function. (ustr_cmp_suffix_subustr_eq): Added function. (ustr_cmp_case_prefix_subustr_eq): Added function. (ustr_cmp_case_suffix_subustr_eq): Added function. 2007-09-10 James Antill * ustr-main-code.h (ustr_conf): Added function. 2007-09-03 James Antill * ustr-cntl-code.h: Move stdarg.h include into code file. 2007-08-28 James Antill * ustr-main.h: Fixup struct Ustr comment. 2007-08-08 James Antill * ustr-import.in: Fix name of replace file. 2007-08-04 James Antill * NEWS: Release 1.0.1 2007-08-04 James Antill * ustr-replace-code.h (ustr_replace_rep_chr): Minor speedup, for non-owned replacements when olen == nlen. (ustr_replace_buf): Minor speedup, for non-owned replacements when olen == nlen. 2007-08-03 James Antill * Documentation/ustr-import.1: Add man page for ustr-import. 2007-08-02 James Antill * Documentation/txt2html.pl (convert): Fixup pre parsing to be more resilient. * ustr-io-code.h (ustr_io_getdelim): Added new function. 2007-08-01 James Antill * Documentation/txt2html.pl (conv_A_refs): Turn **X** into X as bold. * Documentation/txt2man.pl (conv_A_refs): Turn **X** into X as bold. 2007-07-30 James Antill * ustr-io-code.h (ustr_io_put): Fix for IO error path. 2007-07-29 James Antill * ustr-replace-code.h (ustrp__replace_buf): Fix non-pool function calls on pool access. * ustr-fmt.h: Hopefully fix va_copy() snafu, dropping a bunch of code. * ustr-main-code.h (ustr_setf_enomem_err): Set errno == ENOMEM, trickles down to all error paths. 2007-07-28 James Antill * ustr-main-internal.h (USTR__PPTR): Remove macro, it's not safe from aliasing as PPC dies. Also updated all users. 2007-07-27 James Antill * ustr-import.in (INCDIR): Get includedir from Makefile. 2007-07-26 James Antill * ustr-replace-code.h (ustr_replace_buf): Fix ustr_limited() case, and do the same thing for ustr_fixed() if we can. (ustr_replace_rep_chr): Fix ustr_limited() case, and do the same thing for ustr_fixed() if we can. (ustr_replace_buf): Use ustrp__del() for !tlen code path. (ustr_replace_rep_chr): Use ustrp__del() for !tlen code path. 2007-07-25 James Antill * Makefile (VERS_FULL): Bump version to 1.0.1 for test releases. (LDCONFIG): Add var. so we can turn off LDCONFIG at "install" time when creating rpms etc. * examples/fgrep.c: Added example program. * ustr-split-code.h (ustr_split_spn_chrs): In the default mode skip extra seperators at the end too. (ustr_split_buf): In the default mode skip extra seperators at the end too. (ustr_split_buf): Add missing free. * ustr-srch-code.h (ustr__sys_memrepchr): Fix bounds overrun. (ustr__sys_memrepchr): Move to Boyer-Moore algo. for faster searches. (ustr__sys_memrepchr): Fix length for memchr, so we don't miss things if they are > needle len away. 2007-07-24 James Antill * ustr-replace-code.h (ustr_replace_rep_chr): Completely re-wrote function to work like ustr_replace_buf() using ustr_srch_rep_chr_fwd(). * ustr-srch-code.h (ustr_srch_rep_chr_fwd): Added function. (ustr_srch_rep_chr_rev): Added function. * ustr-split-code.h (ustr_split_spn_chrs): Renamed function (ustr_split_spn): Added function. (ustr_split_spn_chrs): Use ustr_spn / ustr_cspn for main piece of code, incl. minor cleanup. * ustr-split.h (ustr_split_spn_cstr): Added function. * ustr-utf8.h (USTR__SSIZE): Add special type for ssize_t, as it's not an ISO 9899:1999 type ... currently unix only. 2007-07-24 Paul Rosenfeld * ustr-replace-code.h (ustr_replace_rep_chr): Added function. * ustr-split-code.h (ustr_sc_split_chrs): Added function. 2007-07-22 James Antill * ustr-sub.h (USTR_SUB_OBJ): Added macro. (USTR_SUB_OSTR): Added macro. (USTR_SC_SUB_OBJ): Added macro. (USTR_SC_SUB_OSTR): Added macro. * ustr-ins.h (USTR_INS_OBJ): Added macro. (USTR_INS_OSTR): Added macro. * ustr-set.h (USTR_SET_OSTR): Added macro. * ustr-main.h (USTR_ADD_OSTR): Added macro. (USTR_DUP_OSTR): Added macro. (USTR_DUPX_OSTR): Added macro. 2007-07-21 James Antill * ustr-split-code.h (ustr_split_buf): Added storage parameter, and/or have auto free on exit. 2007-07-20 James Antill * ustr-main.h (ustr_len): Add assert for NULL. (ustr_cstr): Add assert for NULL. 2007-07-19 James Antill * ustr-replace-code.h (ustrp__replace_buf): Remove underflow condition, as that can't happen. * ustr-sub-code.h (ustr_sub_subustr): Let subustr with len=0 work. (ustr_sc_sub_undef): Let subustr with len=0 work. (ustr_sc_sub_subustr): Let subustr with len=0 work. * ustr-split-code.h (ustr_split_buf): Initial cleanup. * ustr-main.h (USTR_POOL_NULL): Added NULL specific for Ustr_pool. 2007-07-19 Paul Rosenfeld * ustr-split.h (ustr_split_cstr): Added function. * ustr-split-code.h (ustr_split_buf): Added function. (ustr_split): Added function. 2007-07-18 James Antill * ustr-pool-code.h (ustr__pool_sys_free): Go back more than one ptr, so dupx + copy + free etc. works better. 2007-07-16 James Antill * ustr-sub-code.h (ustr_sc_replace_buf): Fix tlen calc. (ustr_sc_replace_buf): Fix main loop for dupx path. (ustr_sc_replace_buf): Fix length of final sub for dupx path. * ustr-ins-code.h (ustr_ins_undef): Fix memmove length. * ustr-sub-code.h (ustr_sub_rep_chr): Fix return value. * ustr-ins-code.h (ustr_ins_undef): Fix offset. * ustr-sub-code.h (ustr_sub_vfmt_lim): Add offset to vsnrptinf(), duh! (ustr_sub_vfmt_lim): Fix NIL overwrite from vsnprintf() (ustr_sc_sub_vfmt_lim): Add offset to vsnrptinf(), duh! (ustr_sc_sub_vfmt_lim): Fix NIL overwrite from vsnprintf() * ustr-ins-code.h (ustrp__ins_undef): Use current len, not new len. (ustr_ins_vfmt_lim): Add offset to vsnrptinf(), duh! (ustr_ins_vfmt_lim): Fix NIL overwrite from vsnprintf() 2007-07-15 James Antill * ustr-ins-code.h (ustr_ins_rep_chr): Fix pos. (ustr_ins_buf): Fix pos. (ustr_ins_rep_chr): Fix return value. (ustr_ins_undef): Get wstr after realloc(). * ustr-sub-code.h (ustr_sub_vfmt_lim): Added function. (ustr_sub_fmt_lim): Added function. (ustr_sub_vfmt): Added function. (ustr_sub_fmt): Added function. (ustr_sc_sub_vfmt_lim): Added function. (ustr_sc_sub_fmt_lim): Added function. (ustr_sc_sub_vfmt): Added function. (ustr_sc_sub_fmt): Added function. * ustr-ins-code.h (ustr_ins_vfmt_lim): Added function. (ustr_ins_fmt_lim): Added function. (ustr_ins_vfmt): Added function. (ustr_ins_fmt): Added function. * ustr-sub-internal.h (USTR_SUB_INTERNAL_H): Added file, and all ustrp wrapper APIs. * ustr-main-code.h (ustr_del): Try to set enomem, if dupx fails. (ustr_del_subustr): Try to set enomem, if dupx fails. (ustr_add): Try to set enomem, if dupx fails. * ustr-ins-code.h (ustr_ins_undef): Added function. (ustr_ins): Added function. (ustr_ins_subustr): Added function. (ustr_ins_rep_chr): Added function. * ustr-ins.h (ustr_ins_cstr): Added function. * ustr-sub-code.h (ustr_sc_sub_undef): Added function. (ustr_sc_sub_undef): Move to using ustr_ins*(). 2007-07-14 James Antill * ustr-main-code.h (ustr_add_buf): Remove code. (ustr_add_rep_chr): Remove code. * ustr-sub-code.h (ustr_sub_rep_chr): Added function. (ustr_sub_subustr): Fix typo of *ps1 into s2, must test! (ustr_sc_sub_subustr): Added function. (ustr_sc_replace_buf): Added function. (ustr_sub_undef): Added function. * ustr-sub.h (ustr_sc_replace_cstr): Added function. * ustr-sub-code.h (ustr_sc_replace): Optimization, so we don't go n**2. 2007-07-13 James Antill * ustr-import.in: Add sub. * T/ctst_17_sub.c: Initial fixups. * ustr-sub-code.h (ustr_sub_subustr): Added function. * ustr-sub-code.h: Initial fixups. * ustr-sub.h: Initial fixups. 2007-07-13 Paul Rosenfeld * ustr-sub-code.h (ustr_sub_buf): Added function. (ustr_sub_cstr): Added function. (ustr_sub): Added function. (ustr_sc_sub_buf): Added function. (ustr_sc_sub): Added function. (ustr_replace): Added function. 2007-07-12 James Antill * NEWS: Release 1.0.0 2007-07-12 James Antill * ustr-main-code.h (ustr__dupx_cmp_eq): More fixes for dupx comparisons. * examples/mkdir_p.c: Added example program. * ustr-sc-code.h (ustr_sc_dup): Fix implementation to call ustr_dup() directly. (ustr_sc_dupx): Fix implementation when using different configurations. * ustr-main-code.h (ustr__dupx_cmp_eq): Fix dupx comparisons, esp. when sizes are involved. 2007-07-11 James Antill * ustr-main-code.h (ustr_assert_valid_subustr): Make this a public function. * ustr-b.h (ustr_parse_b_uint16): Make the Ustr string constant. (ustr_parse_b_uint32): Make the Ustr string constant. (ustr_parse_b_uint64): Make the Ustr string constant. 2007-07-10 James Antill * ustr-io-code.h (ustr_io_getfile): Round up on first pass. * ustr-main-code.h (ustr_add): Fixup code path when using subustr on self. * ustr-set-code.h (ustr_set_subustr): Fixup code path when using subustr on sellf. 2007-07-09 James Antill * ustr-main-code.h (ustr_size): Remove special casing for read-only strings. (ustr_size_alloc): Remove special casing for read-only strings. (ustr_size_overhead): Change "" overhead value from 0 to 1, although it's debatable this matches the other values better. * ustr-pool-code.h (ustr_pool_make_pool): Move the bundled pool API into it's own file. 2007-07-08 James Antill * ustr-main-code.h (ustr_setf_enomem_err): Don't change the enomem flag if not owner. (ustr_setf_enomem_clr): Don't change the enomem flag if not owner. * ustr-set-code.h (ustrp__set_undef): Cleanup code path for set_undef to current length. * ustr-main-code.h (ustr__ref_set): Don't allow fixed storage Ustr's to set anything. (ustr_init_alloc): Remove if check for ustr__ref_set. (ustr_init_fixed): Don't call ustr__ref_set, to it all manually. (ustrp__add): Minor optimization for when we aren't adding anything. (ustr_setf_enomem_err): Only set the enomem flag if we are the owner. (ustr_setf_enomem_clr): Only clear the enomem flag if we are the owner. * Documentation/functions.txt: More docs. * ustr-main-code.h (ustr__ref_add): Remove macro function, minor cleanup. 2007-07-07 James Antill * ustr-main.h (USTR_CONF_REF_BYTES): Change default to 1 byte. 2007-07-06 James Antill * ustr-main-code.h (ustr_add): Simplify the implimentation. * examples/netstr.c (cescape_decode): Add \ EOL and \v handling. 2007-07-05 James Antill * ustr-main-code.h (ustr_realloc): Simplify the realloc API. to be closer to what people would expect. (ustr_reallocx): Remove this API. * ustr-sc-code.h (ustr_sc_wstr): Added function. * ustr-import.in: Add sc handling. * ustr-sc.h: Move most of the ustr_sc functions to a file. * ustr-utf8-code.h (ustr_sc_utf8_reverse): Added function. 2007-07-04 James Antill * examples/netstr.c (gen_csv_netstr): Added CSV functionality. * ustr-srch-code.h (ustr_srch_chr_fwd, ustr_srch_buf_fwd): Always return the position as an absolute value. 2007-07-03 James Antill * ustr-spn-code.h (ustr_spn_chr_fwd, ustr_spn_chr_rev) (ustr_spn_chrs_fwd, ustr_spn_chrs_rev) (ustr_cspn_chr_fwd, ustr_cspn_chr_rev) (ustr_cspn_chrs_fwd, ustr_cspn_chrs_rev) (ustr_utf8_spn_chrs_fwd, ustr_utf8_spn_chrs_rev) (ustr_utf8_cspn_chrs_fwd, ustr_utf8_cspn_chrs_rev): Added offset argument. 2007-07-02 James Antill * ustr-srch-code.h (ustr_srch_chr_fwd, ustr_srch_chr_rev) (ustr_srch_buf_fwd, ustr_srch_buf_rev) (ustr_srch_subustr_fwd, ustr_srch_subustr_rev): Added offset argument. * ustr-parse-code.h (ustr_parse_uintmaxx): Added offset and return length arguments. (ustr_parse_ulongx): Added offset and return length arguments. * ustr-parse.h (ustrp_parse_uintmaxx): Dito. (ustrp_parse_ulongx): Dito. * ustr-main-code.h (ustr_size_overhead): Rename function, from ustr_overhead(). * ustr-main.h: Rename ustr_overhead and ustrp_overhead to ustr_size_overhead and ustrp_size_overhead. * T/ctst_99_64bit.c (tst): Add 64bit tests. 2007-07-01 James Antill * Makefile (install): Fix pkgconfig install on x86-64. 2007-06-24 James Antill * Makefile (EXAMPLES): Add nums example to install. * examples/Makefile: Revert to using the system headers/libs. * examples/nums.c (main): Fix ustr_parse_intmaxx() call to use the pointer and not the old char API. 2007-06-24 James Antill * NEWS: Release 0.99.3 2007-06-24 James Antill * ustr-compiler.h (USTR__INLINE): Move a bit closer to being able to build without inline support. 2007-06-23 James Antill * ustr-main.h (USTR_CONF_COMPILE_USE_INLINE): Added conf. so we can compile without inline, users only atm. * ustr-set.h (USTR_SET_OBJ): Added macro. * ustr-main.h (USTR_SIZE_FIXED): Added macro for sizing fixed Ustr's. (USTR_BEG_FIXED8): Added macro. (USTR_ADD_OBJ): Added macro. (USTR_DUP_OBJ): Added macro. (USTR_DUPX_OBJ): Added macro. * scripts/gen_doc_templ_from_protos.pl: Add ustrp functions back in. * ustr-cmp.h (ustr_cmp_case_eq): Added function. (ustr_cmp_case_subustr_eq): Added function. (ustr_cmp_case_cstr_eq): Added function. (ustr_cmp_case_prefix_eq): Added function. (ustr_cmp_case_prefix_cstr_eq): Added function. (ustr_cmp_case_suffix_eq): Added function. (ustr_cmp_case_suffix_cstr_eq): Added function. (ustr_cmp_case_cstr): Added function. * ustr-cmp-code.h (ustr_cmp_case_buf): Added function. (ustr_cmp_case): Added function. (ustr_cmp_case_subustr): Added function. (ustr_cmp_case_prefix_buf_eq): Added function. (ustr_cmp_case_suffix_buf_eq): Added function. 2007-06-22 James Antill * ustr-main-code.h (ustr_sc_tolower): Added function. (ustr_sc_toupper): Added function. * ustr-parse-code.h (ustr_parse_uintmaxx): Allow utf8 seperators. 2007-06-21 James Antill * ustr-parse-code.h (ustr_parse_uintmaxx): Fixup overflow to work the same with or without the overflow error numbers. * ustr-parse-code.h (ustr_parse_uintmaxx): Add num_min argument to cleanup negative numbers support. * examples/nums.c (main): Added example program, uses ustr_parse* and ustr_sc_reverse(). * ustr-main-code.h (ustr_sc_reverse): Added function. 2007-06-20 James Antill * ustr-parse-code.h (ustr_parse_uintmaxx): Added function. (ustr_parse_intmax, ustr_parse_intmax): Added functions. (ustr_parse_ulongx): Added function. (ustr_parse_long, ustr_parse_long): Added functions. (ustr_parse_int, ustr_parse_int): Added functions. (ustr_parse_short, ustr_parse_short): Added functions. * examples/netstr.c (cescape_decode): Added new style python octal escapes. 2007-06-18 James Antill * Makefile (CFLG_LIB_OPT): Remove USTR_DEBUG from CFLG_LIB_OPT * ustr-main-code.h (ustr__pool_sys_free): Have free do the "right" thing if using the last allocated ustrp. Same as ustr__pool_sys_realloc. (ustr_pool_make_subpool): Added function. * ustr-main.h (struct Ustr_pool): Create generic "class" for pool'd data. This way multiple modules can have seperate pools, managed in different ways. Convert all pool functions to require a Ustr_pool argument. 2007-06-14 James Antill * ustr-main.h (USTR_ASSERT_NO_SWITCH_DEF): Add macro for switch statements that "can't" default. * ustr-main-code.h (ustr_owner): Only have code for 8 byte refs. in 64bit compiles. 2007-06-13 James Antill * ustr-set-code.h (ustrp__set_subustr): Simplify code. (ustrp__set_subustr): Fix off by one bug, when going to set_buf(). * T/ctst_15_enomem.c (tst): Add test, coverage now over 98% on 32bit. * Makefile (EXAMPLES): Add hexdump example. * ustr-set-code.h (ustrp__set_empty): Don't dupx, if sized and owner. * ustr-main-code.h (ustr_init_size): Fix bug with lbytes/sbytes being wrong with sizes near the byte change marks. (ustr_init_alloc): Fix bug with lbytes/sbytes being wrong on 64bit. * ustr-io-code.h (ustr_io_get): Change the API to possibly return the number of bytes read. * examples/hexdump.c (hexdump): Fix off by one typo: > should be >= (main): Add - files. (usage): Fix usage. (loop): Don't read again, if we've hit EOF. 2007-06-12 James Antill * examples/hexdump.c (main): Change read size and allow stdin reading. * examples/hexdump.c (hexdump): Added new example. * examples/netstr.c: Remove fake compat. IO for ustr-0.99.1. * examples/hello_world.c: Remove fake compat. IO for ustr-0.99.1. 2007-06-11 James Antill * ustr-main.h (ustr_xi__embed_val_get) (ustr_xi__ref_get, ustr_xi__pow2): Rename functions. * libustr.ver: Fixup ustr__ exported functions to be ustr_xi__ * libustr.ver: Added symbols to export map. * scripts/list_functions_src.pl: Added io and utf8 files to list. * ustr-utf8-code.h (ustr_utf8_chars2bytes): Deal with zero length input. * ustr-spn.h (ustr_utf8_spn_cstr_fwd, ustr_utf8_spn_cstr_rev) (ustr_utf8_cspn_cstr_fwd, ustr_utf8_cspn_cstr_rev) (ustr_utf8_spn_fwd, ustr_utf8_spn_rev, ustr_utf8_cspn_fwd) (ustr_utf8_cspn_rev): Added functions. * ustr-spn-opt-code.c: Add utf8 externs. * ustr-spn-dbg-code.c: Add utf8 externs. * ustr-debug.h: Move utf8 in front of spn, as ustr-import does. * ustr.h: Move utf8 in front of spn, as ustr-import does. * ustr-spn-code.h (ustr_utf8_spn_chrs_fwd) (ustr_utf8_spn_chrs_rev, ustr_utf8_cspn_chrs_fwd) (ustr_utf8_cspn_chrs_rev): Fixes for bad utf-8. * ustr-utf8-code.h (ustr_utf8_len): Use the same logic as ustr__utf8_prev / next. Add pointer to Wikipedia documentation on utf8. (ustr__utf8_next): Rename from _nxt. (ustr__utf8_prev): Rename from _beg. (ustr_utf8_bytes2chars): Added function. 2007-06-10 James Antill * ustr-spn-code.h (ustr_utf8_spn_chrs_fwd) (ustr_utf8_spn_chrs_rev, ustr_utf8_cspn_chrs_fwd) (ustr_utf8_cspn_chrs_rev): Added functions. UTF-8 compatible spanning. * ustr-srch-internal.h: Create internal file, so we can use USTR__SYS_MEM internally. * ustr-utf8-code.h (ustr_utf8_len): Use hardwired code, for code decrease / speed increase. * ustr-srch-code.h (ustr__sys_memmem): Changed to an internal symbol. 2007-06-08 James Antill * ustr-utf8-code.h (ustr_utf8_chars2bytes): Added function. * libustr.ver: Add local matches. 2007-06-07 James Antill * ustr-utf8-code.h (ustr__utf8_check): Fix major "porting" typo, tests are good! * ustr-utf8-internal.h (USTR__UTF8_WCHAR): Remove dep. on wchar.h for wchar_t ... use our own "wchar" that is unsigned and 32 bits. 2007-06-04 James Antill * Documentation/functions.txt: Add some more functions. * ustr-main.h (ustr_pool_sys_malloc, ustr_pool_sys_realloc): Add NONULL attribute to pool pointer argument. (ustr_pool_sys_free): Fix NONULL argument on data pointer. (ustr_pool_sys_realloc): Change behaviour to be like realloc() for zero length cases. * ustr-main-code.h (ustr_dup): Fix dupx'ing. (ustrp__del): Fix dmpx_cmp/ing. (ustrp__dupx): Fix dupx'ing. (ustrp__dup_subustr): Fix dupx'ing. (ustr_add_undef): Fix dupx'ing. (ustrp__add): Fix dupx'ing. (ustrp__sc_dup): Fix dupx'ing. (ustrp__sc_ensure_owner): Fix dupx'ing. * ustr-set-code.h (ustrp__set): Remove defunct DUPX_DEF. (ustrp__set_undef): Remove defunct DUPX_DEF. (ustrp__set_empty): Remove defunct DUPX_DEF. * ustr-io-code.h (ustrp__io_put): Remove defunct DUPX_DEF. * ustr-main-internal.h (USTR__DUPX_FROM): Change macro so it works for everything, preserves enomem etc. * ustr-cmp.h (ustr_cmp_prefix_buf_eq, ustr_cmp_prefix_eq) (ustr_cmp_prefix_cstr_eq, ustr_cmp_suffix_buf_eq) (ustr_cmp_suffix_eq, ustr_cmp_suffix_cstr_eq): Add functions. * scripts/git-push-web.sh: Add script. * ustr-utf8.h (ustr_utf8_valid): Added function. * ustr-utf8-code.h (ustr_utf8_len): Added function. (ustr_utf8_width): Added function. * ustr-io-internal.h: Fix #define protection C&P error. * Documentation/index.html: Fixup documention for examples. 2007-06-03 James Antill * NEWS: Release 0.99.2. 2007-06-03 James Antill * Documentation/index.html: Fix HREF as well as title * ustr-import.in: Split *-code.h and *-opt-code.c / *-dbg-code.c. Also fix non-cfile imports. * scripts/clean.sh: Remove .git data * libustr.ver: Fix typo * Makefile (SRC_SRCS): Install ustr-b-code.h, to help people make readable Makefiles * examples/Makefile: Import a bunch of stuff from top level Makefile to show people how to do it. * Makefile (all): Fix make all to build opt static libs. * Makefile (install): Fix install of man pages. * Documentation/index.html: Update link to 0.99.2 * Makefile (SRC_SRCS): Install ustr-io-internal.h * Makefile (install): Fix install permissions for ustr-import. * ustr-debug.pc: Update for 0.99.2 release. * ustr.pc: Update for 0.99.2 release. * libustr.ver: Update for new symbols. * Documentation/index.html: Add link to functions/constatns API references. * Makefile (install): Install examples and html / man page API references. * examples/hello_world.c (main): Added very simple example. * examples/netstr.c (cescape_decode): Add options for various stuff, add a cescape_decode() function. * examples/Makefile (LDFLAGS): Change default CFLAGS/LDFLAGS to use installed libustr.a/ustr.h. * ustr-io.h (ustr_io_putfileline): Add function. (ustrp_io_putfileline): Add function. * ustr-io-code.h (ustr_io_putline): Add function. (ustrp_io_putline): Add function. 2007-06-02 James Antill * Documentation/index.html: Add info. about development tree. 2007-06-01 James Antill * Documentation/constants.txt: Start documentation on constants. * Documentation/functions.txt: Start documentation on functions. * Documentation/txt2man.pl: Import perl script from Vstr. * Documentation/txt2html.pl: Import perl script from Vstr. * ustr-srch-code.h (ustr_srch_buf_rev): Fix buf=1 using _fwd typo. * ustr-spn.h (ustr_spn_fwd, ustr_spn_rev): Remove _ustr and _cstr namespaces. (ustr_cspn_fwd, ustr_cspn_rev): Remove _ustr and _cstr namespaces. (ustr_spn_cstr_fwd, ustr_spn_cstr_rev): Remove _ustr and _cstr namespaces. * ustr-srch-code.h (ustr_srch_subustr_fwd): Add function. (ustr_srch_subustr_rev): Add function. * TODO: Remove old cntl/srch_subustr data from TODO. * scripts/clean.sh: Remove coverage data, and examples too. * examples/netstr.c (main): Add example program. * ustr-main.h (USTRP_SC_INIT_AUTO): Add macro. 2007-05-31 James Antill * ustr-main-code.h (ustrp__reallocx): Allow reallocx to "grow", as long as we don't have to change byte storage. (ustrp__add): Cleanup code. * ustr-import.in: Add io, gdb and cntl options. * ustr-main-code.h (ustr_pool_sys_malloc): Always have the latest allocation at the top of the list, strict FIFO now. (ustr_pool_sys_realloc): Allow reallocation of the "last" -- top of the list allocation. * ustr-fmt-code.h (ustrp__add_vfmt_lim): Remove bad va_copy()/va_end() calls on error/retard call path. (ustrp__dupx_vfmt_lim): Remove bad va_copy()/va_end() calls on error/retard call path. (ustrp__set_vfmt_lim): Remove bad va_copy()/va_end() calls on error/retard call path. * ustr-main-code.h (ustr_setf_enomem_err): Change namespace from _set_ to _setf_, so it isn't confusing with ustr_set_fmt() etc. (ustr_setf_enomem_clr, ustr_setf_share, ustr_setf_owner): Dito. * ustr-main.h (ustr_rw): Remove function, as it's confusing with ustr_owner() (ustr_init_fixed, ustrp_init_fixed): Remove warn_unused_ret. * ustr-main-code.h (ustrp_init_alloc): Fix inf. recursion typo. 2007-05-30 James Antill * ustr-set-code.h (ustr_set_empty, ustrp_set_empty): Add functions, work like add_empty. (ustrp__set): Add enomem on failure to dup. (ustrp__set_subustr): Add enomem on failure to dup. * ustr-cmp.h (ustr_cmp_fast_buf): Move function to be always inline. (ustr_cmp_fast): Move function to be always inline. * ustr-main-code.h (ustr_pool_sys_free): Add function. (ustr_pool_sys_realloc, ustr_pool_sys_free): Change namespace from "ustr_pool_api_" to "ustr_pool_sys_". (ustrp__del): Fix bad usage of ustr_ro() to ustr_alloc() (ustr__rw_add): Allow growing if byte storage size doesn't increase. (ustr__treat_as_buf): Allow 0 length strings. (ustr_sc_ensure_owner, ustrp_sc_ensure_owner): Add function, makes sure the string passes the ustr_owner() test. * ustr-import.in: Add missing compiler copy. * ustr-compiler.h: Remove COMPILE_ASSERT checks, for dynamic config. * tst.h (USE_MALLOC_CHECK): Explicitly define the option. (mc_malloc, mc_realloc, mc_free): Use the new USTR_CONF_USE_DYNAMIC_CONF to change the malloc cbs with ustr_cntl_opt. (main): Move from dup_buf() to sc_ensure_owner(), tweaks for malloc-check. * ustr-cntl-code.h (ustr_cntl_opt): Added function, allow some of the global config. options to be runtime vars instead. * ustr-cmp-code.h (ustr_cmp_subustr): Fix spurious ! C&P typo. (ustr_cmp_fast_subustr): Fix spurious ! C&P typo. * tst.h (USTR_CONF_FREE): Add file/line data. * malloc-check.h (malloc_check_free): Add file/line params. to free. 2007-05-28 James Antill * ustr-fmt.h: Add warn_unused_ret() to all dup funcs. * Makefile: Move all tests into seperate T dir, generate .c files so that coverage "does the right thing" * scripts/lcov.sh: Update lcov.sh to do the right thing, must be called from Makefile now. * malloc-check.h (malloc_check_assert): Use internal namespaced assert(). (malloc_check_mem, malloc_check_alloc, malloc_check_sz_mem): Add file/line params. to other functions. (MALLOC_CHECK_TRACE): Add trace option. 2007-05-27 James Antill * ustr-io-code.h (ustrp__io_getline): Speed up getline. * Makefile: Fixup SONAME, change cc to be default. 2007-05-26 James Antill * ustr-set-code.h (ustrp__set_undef): Cleanup code. * ustr-io-code.h (ustrp__io_put): Don't allocate an entire new string, just the bits that'll be left over. * Documentation/design.html: Use new USTR_BEG_FIXEDx constants in examples. 2007-05-25 James Antill * ustr-main-code.h (ustr__rw_add): Fixup tests for if we can reuse the current Ustr, allow lbytes to be more than the minimum needed. * ustr-io-code.h (ustr_io_get, ustrp_io_get) (ustr_io_getfile, ustrp_io_getfile, ustr_io_getfilename) (ustr_io_getfilename, ustrp_io_getfilename) (ustr_io_getline, ustrp_io_getline) (ustr_io_put, ustrp_io_put, ustr_io_putfilename) (ustrp_io_putfilename): Added simple blocking stdio IO functions. * ustr-fmt.h: Add USTR__COMPILE_ATTR_WARN_UNUSED_RET() to add _dup format functions. * ustr-main.h: Remove USTR__COMPILE_ATTR_WARN_UNUSED_RET() from ustr_init_fixed. * ustr-set-internal.h: Add internal headers, to reduce obj size. * ustr-main.h: Add internal headers, to reduce obj size. (USTR_CONF_INCLUDE_INTERNAL_HEADERS): Add define on if you get internal header code or not. * ustr-main-code.h (ustr__sz_get): Fixed prototype. * Makefile (VERS_ESONAME): Fix the SONAME to just .0 2007-05-24 James Antill * ustr-import.in: Add a gdb import only mode. * ustr.spec: Fix typo of %{ver} to be %{version}. * ustr-import.in: Copy .gdbinit on import. * Makefile (install): Added .gdbinit to shared dir. * ustr.spec: Added .gdbinit to -devel package * Documentation/index.html: Tweaked documentation. * Documentation/index.html: Added link to gnumeric file * Documentation/index.html: Added link to .gdbinit file * THANKS: Added Rik and Karl. 2007-05-23 James Antill * NEWS: Release 0.99.1 2007-05-15 James Antill * tst_4_grow.c (tst): Fix for Solaris's retarded printf. * ctst_4_grow.c (tst): Fix for Solaris's retarded printf. ustr-1.0.4/ustr-utf8-opt-code.c0000644000076400007640000000127610722116131015236 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-utf8.h" ustr-1.0.4/ustr-cmp-dbg-code.c0000644000076400007640000000130310674563614015072 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-cmp.h" ustr-1.0.4/tst.h0000644000076400007640000001431110760403055012464 0ustar jamesjames #undef NDEBUG /* always use assert */ #undef assert #undef ASSERT #define assert(x) do { \ if (x) {} else { \ fprintf(stderr, " -=> ASSERT (%s) failed in (%s) from %d %s.\n", \ #x , __func__, __LINE__, __FILE__); \ abort(); } \ } while (FALSE) #define ASSERT(x) do { \ if (x) {} else { \ fprintf(stderr, " -=> ASSERT (%s) failed in (%s) from %d %s.\n", \ #x , __func__, __LINE__, __FILE__); \ abort(); } \ } while (FALSE) #define ASSERT_EQ(x, y) do { \ if (ustr_cmp_eq(x, y)) {} else { \ fprintf(stderr, " -=> ASSERT_EQ (%zu:\"%s\", %zu:\"%s\") failed " \ "in (%s) from %d %s.\n", \ ustr_len(x), ustr_cstr(x), ustr_len(y), ustr_cstr(y), \ __func__, __LINE__, __FILE__); \ abort(); } \ } while (FALSE) #define assert_eq(x, y) ASSERT_EQ(x, y) #define ASSERT_PEQ(x, y) do { \ if (ustrp_cmp_eq(x, y)) {} else { \ fprintf(stderr, " -=> ASSERT_PEQ (%zu:\"%s\", %zu:\"%s\") failed " \ "in (%s) from %d %s.\n", \ ustrp_len(x), ustrp_cstr(x), ustrp_len(y), ustrp_cstr(y), \ __func__, __LINE__, __FILE__); \ abort(); } \ } while (FALSE) #define assert_peq(x, y) ASSERT_PEQ(x, y) #if !defined(USTR_DEBUG) || USTR_DEBUG # define ustr_assert(x) assert(x) # define USTR_ASSERT(x) assert(x) # ifndef ustr_assert_ret /* ustr_assert_valid() == FALSE testing */ # define ustr_assert_ret(x, y) assert(x) # endif # ifndef USTR_ASSERT_RET # define USTR_ASSERT_RET(x, y) assert(x) # endif #endif #define _GNU_SOURCE 1 #define MALLOC_CHECK__ATTR_H() /* do nothing */ #define USE_MALLOC_CHECK 1 #include "malloc-check.h" /* doesn't work on ctst_*.c cotst_*.c -- as they alloc. from the lib. */ #define USTR_CONF_MALLOC(x) MC_MALLOC(x) #define USTR_CONF_REALLOC(x, y) MC_REALLOC(x, y) #define USTR_CONF_FREE(x) MC_FREE(x) #include #include #include #define FALSE 0 #define TRUE 1 #include "ustr-debug.h" static int tst(void); /* fwd */ #define EXIT_FAILED_OK 77 static struct Ustr *s1 = USTR(""); static struct Ustr *s2 = USTR1(\x02, "s2"); static const char *rf; MALLOC_CHECK_DECL(); #if USTR_CONF_USE_DYNAMIC_CONF static void *mc_malloc(size_t x) { (void)x; return (NULL); } static void *mc_realloc(void *p, size_t x) { (void)p; (void)x; return (NULL); } static void mc_free(void *x) { (void) x; } static unsigned long mc_mem_fail_num = 0; #define TST_MC_SET_NUM(x) assert(ustr_cntl_opt(666, 0xF0F0, x)) #define TST_MC_GET_NUM() (ustr_cntl_opt(666, 0xF0F1, &mc_mem_fail_num) ? mc_mem_fail_num : 0xFFFFFFFFU) #else #define TST_MC_SET_NUM(x) MALLOC_CHECK_STORE.mem_fail_num = (x) #define TST_MC_GET_NUM() MALLOC_CHECK_STORE.mem_fail_num #endif int main(void) { int ret = -1; struct Ustr *s2_chk1 = USTR1_CHK(\2, "s2"); struct Ustr *s2_chk2 = USTR1_CHK(\x2, "s2"); struct Ustr *s2_chk3 = USTR1_CHK(\x02, "s2"); struct Ustr *s2_chk4 = USTR2_CHK(\0, \x02, "s2"); struct Ustr *s2_chk8 = USTR4_CHK(\0, \0, \0, \x02, "s2"); ASSERT(ustr_len(s2_chk1)); ASSERT(ustr_len(s2_chk2)); ASSERT(ustr_len(s2_chk3)); ASSERT(ustr_len(s2_chk4)); ASSERT(ustr_len(s2_chk8)); assert(USTR_CNTL_MALLOC_CHECK_MEM("")); /* not enabled yet */ #if USTR_CONF_USE_DYNAMIC_CONF { static const struct Ustr_cntl_mem mc_mem = {mc_malloc, mc_realloc, mc_free}; ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_SET_MEM, &mc_mem)); assert(USTR_CNTL_MALLOC_CHECK_BEG(USTR_TRUE)); assert(!TST_MC_GET_NUM()); } #else assert(!USTR_CNTL_MALLOC_CHECK_BEG(USTR_TRUE)); #endif ASSERT(ustr_size(s1) == 0); ASSERT(ustr_size(s2) == 2); ASSERT(ustr_ro(s1)); ASSERT(ustr_ro(s2)); ASSERT(ustr_dup(s1) == s1); ASSERT(ustr_dup(s2) == s2); assert(USTR_CNTL_MALLOC_CHECK_MEM_USTR(s2)); ASSERT(ustr_sc_ensure_owner(&s2)); ASSERT(s2); assert(USTR_CNTL_MALLOC_CHECK_MEM(s2)); assert(USTR_CNTL_MALLOC_CHECK_MEM_USTR(s2)); ASSERT(!ustr_ro(s2)); { size_t esz; size_t ref; int exact; size_t lenn; size_t refc; #if USTR_CONF_USE_DYNAMIC_CONF int conf_esz; size_t conf_ref; int conf_exact; ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_HAS_SIZE, &conf_esz)); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_REF_BYTES, &conf_ref)); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_EXACT_BYTES, &conf_exact)); #endif ustr_conf(s1, NULL,NULL,NULL, NULL,NULL); ustr_conf(s1, &esz,&ref,&exact, &lenn,&refc); #if USTR_CONF_USE_DYNAMIC_CONF ASSERT(!conf_esz == !esz); ASSERT( conf_ref == ref); ASSERT( conf_exact == exact); #else ASSERT(!USTR_CONF_HAS_SIZE == !esz); ASSERT( USTR_CONF_REF_BYTES == ref); ASSERT( USTR_CONF_EXACT_BYTES == exact); #endif ustr_conf(s2, NULL,NULL,NULL, NULL,NULL); ustr_conf(s2, &esz,&ref,&exact, &lenn,&refc); #if USTR_CONF_USE_DYNAMIC_CONF ASSERT(!conf_esz == !esz); ASSERT( conf_ref == ref); ASSERT( conf_exact == exact); #else ASSERT(!USTR_CONF_HAS_SIZE == !esz); ASSERT( USTR_CONF_REF_BYTES == ref); ASSERT( USTR_CONF_EXACT_BYTES == exact); #endif } if ((ret = tst()) && (ret != EXIT_FAILED_OK)) fprintf(stderr, "Error(%s) value = %x\n", rf, ret); else { ustr_free(s1); ustr_free(s2); if (!USTR_CONF_USE_DYNAMIC_CONF) MALLOC_CHECK_EMPTY(); assert(USTR_CNTL_MALLOC_CHECK_END()); } switch (ret) { case EXIT_FAILED_OK: exit (EXIT_FAILED_OK); case EXIT_SUCCESS: exit (EXIT_SUCCESS); default: exit (EXIT_FAILURE); } } ustr-1.0.4/ustr-parse.h0000644000076400007640000002070610642536207013771 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_PARSE_H #define USTR_PARSE_H 1 #ifndef USTR_MAIN_H #error " You should have already included ustr-main.h, or just include ustr.h." #endif #define USTR_TYPE_PARSE_NUM_ERR_NONE 0 #define USTR_TYPE_PARSE_NUM_ERR_ONLY_S 1 #define USTR_TYPE_PARSE_NUM_ERR_ONLY_SPM 2 #define USTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX 3 #define USTR_TYPE_PARSE_NUM_ERR_OOB 4 #define USTR_TYPE_PARSE_NUM_ERR_OVERFLOW 5 #define USTR_TYPE_PARSE_NUM_ERR_NEGATIVE 6 #define USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO 7 #define USTR_FLAG_PARSE_NUM_DEF 0U #define USTR__MASK_PARSE_NUM_BASE (63) /* (1<<6) - 1 */ /* #define USTR_FLAG_PARSE_NUM_LOCAL (1U<<6) */ #define USTR_FLAG_PARSE_NUM_SEP (1U<<7) #define USTR_FLAG_PARSE_NUM_OVERFLOW (1U<<8) #define USTR_FLAG_PARSE_NUM_SPACE (1U<<9) #define USTR_FLAG_PARSE_NUM_NO_BEG_ZERO (1U<<10) #define USTR_FLAG_PARSE_NUM_NO_BEG_PM (1U<<11) #define USTR_FLAG_PARSE_NUM_NO_NEGATIVE (1U<<12) #define USTR_FLAG_PARSE_NUM_EXACT (1U<<13) #if USTR_CONF_HAVE_STDINT_H USTR_CONF_E_PROTO uintmax_t ustr_parse_uintmaxx(const struct Ustr *, size_t, unsigned int, uintmax_t, uintmax_t, const char *, size_t *,unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 6)); USTR_CONF_E_PROTO uintmax_t ustr_parse_uintmax(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO intmax_t ustr_parse_intmax(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); #endif USTR_CONF_E_PROTO unsigned long ustr_parse_ulongx(const struct Ustr *, size_t, unsigned int, unsigned long, unsigned long, const char *, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 6)); USTR_CONF_E_PROTO unsigned long ustr_parse_ulong(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO long ustr_parse_long(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO unsigned int ustr_parse_uint(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO int ustr_parse_int(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO unsigned short ustr_parse_ushort(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO short ustr_parse_short(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-parse-code.h" #endif /* ---------------- pool wrapper APIs ---------------- */ #if USTR_CONF_HAVE_STDINT_H USTR_CONF_EI_PROTO uintmax_t ustrp_parse_uintmaxx(const struct Ustrp *, size_t, unsigned int, uintmax_t, uintmax_t, const char *, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 6)); USTR_CONF_EI_PROTO uintmax_t ustrp_parse_uintmax(const struct Ustrp *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_EI_PROTO intmax_t ustrp_parse_intmax(const struct Ustrp *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); #endif USTR_CONF_EI_PROTO unsigned long ustrp_parse_ulongx(const struct Ustrp *, size_t, unsigned int, unsigned long, unsigned long, const char *, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 6)); USTR_CONF_EI_PROTO unsigned long ustrp_parse_ulong(const struct Ustrp *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_EI_PROTO long ustrp_parse_long(const struct Ustrp *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_EI_PROTO unsigned int ustrp_parse_uint(const struct Ustrp *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_EI_PROTO int ustrp_parse_int(const struct Ustrp *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_EI_PROTO unsigned short ustrp_parse_ushort(const struct Ustrp *, size_t, unsigned int, size_t *, unsigned *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_EI_PROTO short ustrp_parse_short(const struct Ustrp *, size_t, unsigned int, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); #if USTR_CONF_COMPILE_USE_INLINE # if USTR_CONF_HAVE_STDINT_H USTR_CONF_II_PROTO uintmax_t ustrp_parse_uintmaxx(const struct Ustrp *s1, size_t off, unsigned int flags, uintmax_t nmin, uintmax_t nmax, const char *sep, size_t *len, unsigned int *ern) { return (ustr_parse_uintmaxx(&s1->s, off, flags, nmin, nmax, sep, len, ern)); } USTR_CONF_II_PROTO uintmax_t ustrp_parse_uintmax(const struct Ustrp *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { return (ustr_parse_uintmax(&s1->s, off, flags, len, ern)); } USTR_CONF_II_PROTO intmax_t ustrp_parse_intmax(const struct Ustrp *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { return (ustr_parse_intmax(&s1->s, off, flags, len, ern)); } # endif USTR_CONF_II_PROTO unsigned long ustrp_parse_ulongx(const struct Ustrp *s1, size_t off, unsigned int flags, unsigned long nmin, unsigned long nmax, const char *sep, size_t *len, unsigned *ern) { return (ustr_parse_ulongx(&s1->s, off, flags, nmin, nmax, sep, len, ern)); } USTR_CONF_II_PROTO unsigned long ustrp_parse_ulong(const struct Ustrp *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { return (ustr_parse_ulong(&s1->s, off, flags, len, ern)); } USTR_CONF_II_PROTO long ustrp_parse_long(const struct Ustrp *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { return (ustr_parse_long(&s1->s, off, flags, len, ern)); } USTR_CONF_II_PROTO unsigned int ustrp_parse_uint(const struct Ustrp *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { return (ustr_parse_uint(&s1->s, off, flags, len, ern)); } USTR_CONF_II_PROTO int ustrp_parse_int(const struct Ustrp *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { return (ustr_parse_int(&s1->s, off, flags, len, ern)); } USTR_CONF_II_PROTO unsigned short ustrp_parse_ushort(const struct Ustrp *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { return (ustr_parse_ushort(&s1->s, off, flags, len, ern)); } USTR_CONF_II_PROTO short ustrp_parse_short(const struct Ustrp *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { return (ustr_parse_short(&s1->s, off, flags, len, ern)); } #endif #endif ustr-1.0.4/ustr-set.h0000644000076400007640000000770210650703263013450 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SET_H #define USTR_SET_H 1 #ifndef USTR_MAIN_H #error " You should have already included ustr-main.h, or just include ustr.h." #endif #define USTR_SET_OBJ(x, y) ustr_set_buf(x, y, sizeof(y)) #define USTR_SET_OSTR(x, y) ustr_set_buf(x, y, sizeof(y) - 1) #define USTRP_SET_OBJ(p, x, y) ustrp_set_buf(p, x, y, sizeof(y)) #define USTRP_SET_OSTR(p, x, y) ustrp_set_buf(p, x, y, sizeof(y) - 1) USTR_CONF_E_PROTO int ustr_set_undef(struct Ustr **, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_set_empty(struct Ustr **) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_set_buf(struct Ustr **, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_set_cstr(struct Ustr **, const char *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_set(struct Ustr **, const struct Ustr *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_set_subustr(struct Ustr **, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_set_rep_chr(struct Ustr **, char, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_set_undef(struct Ustr_pool *, struct Ustrp **, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO int ustrp_set_empty(struct Ustr_pool *, struct Ustrp **) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO int ustrp_set_buf(struct Ustr_pool *, struct Ustrp **,const void *,size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_EI_PROTO int ustrp_set_cstr(struct Ustr_pool *, struct Ustrp **, const char *) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_set(struct Ustr_pool *, struct Ustrp **, const struct Ustrp *) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_set_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_set_rep_chr(struct Ustr_pool *, struct Ustrp **, char, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); #ifdef USTR_FMT_H # if USTR_CONF_HAVE_VA_COPY USTR_CONF_E_PROTO int ustr_set_vfmt_lim(struct Ustr **, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((1, 3)) USTR__COMPILE_ATTR_FMT(3, 0); USTR_CONF_E_PROTO int ustr_set_vfmt(struct Ustr **, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((1, 2)) USTR__COMPILE_ATTR_FMT(2, 0); USTR_CONF_E_PROTO int ustrp_set_vfmt_lim(struct Ustr_pool *, struct Ustrp **, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 4)) USTR__COMPILE_ATTR_FMT(4, 0); USTR_CONF_E_PROTO int ustrp_set_vfmt(struct Ustr_pool *, struct Ustrp **, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 3)) USTR__COMPILE_ATTR_FMT(3, 0); # endif USTR_CONF_E_PROTO int ustr_set_fmt_lim(struct Ustr **, size_t,const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1, 3)) USTR__COMPILE_ATTR_FMT(3, 4); USTR_CONF_E_PROTO int ustr_set_fmt(struct Ustr **, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1, 2)) USTR__COMPILE_ATTR_FMT(2, 3); USTR_CONF_E_PROTO int ustrp_set_fmt_lim(struct Ustr_pool *, struct Ustrp **, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2, 4)) USTR__COMPILE_ATTR_FMT(4, 5); USTR_CONF_E_PROTO int ustrp_set_fmt(struct Ustr_pool *, struct Ustrp **, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2, 3)) USTR__COMPILE_ATTR_FMT(3, 4); #endif #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-set-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-set-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO int ustr_set_cstr(struct Ustr **ps1, const char *cstr) { return (ustr_set_buf(ps1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustrp_set_cstr(struct Ustr_pool *p, struct Ustrp **ps1, const char *cstr) { return (ustrp_set_buf(p, ps1, cstr, strlen(cstr))); } #endif #endif ustr-1.0.4/LICENSE_LGPL0000644000076400007640000006364410630111754013337 0ustar jamesjames GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. ^L Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. ^L GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. ^L Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. ^L 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. ^L 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. ^L 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. ^L 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ^L How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ustr-1.0.4/ustr-import.in0000644000076400007640000003077210760731334014353 0ustar jamesjames#! /bin/sh -e INCDIR=@INCLUDEDIR@ SHRDIR=@SHRDIR@ VERS=@VERS@ VERS_FULL=@VERS_FULL@ autoconf_64b=@HAVE_64bit_SIZE_MAX@ autoconf_vsnprintf=@HAVE_RETARDED_VSNPRINTF@ dbg=false fulldbg=false cfiles=false defbytes=1 exact=0 usesz=0 cmdname="`basename $0`" usage() { echo " Format: $cmdname [-d][d] [-c] [-b b] [-e 1|0] [-s 1|0] gdb|all|
..." echo " List of options:" echo " -d = Turn debugging on, assert() trigger etc." echo " -d = Turn extra debugging on" echo " -c = Import/use .c files, instead of headers only" echo " -b = Specify default ref. bytes size: 0, 1, 2, 4 or 8" echo " -e = Exact allocations used by default" echo " -s = Sized value included by default" echo " List of sections:" echo " all = All of the following" echo " b = Working with binary numbers in NBO format" echo " cmp = Comparing, strcmp() for Ustr's" echo " cntl = Control options dynamically" echo " fmt = Formatted output, sprintf() for Ustr's" echo " gdb = Copy just the .gdbinit file to the local dir" echo " ins = Inserting data" echo " io = Input Output" echo " main = The core, strcat() and delete for Ustr's" echo " parse = Parsing integers, Ie. Nice versions of strtol()" echo " pool = A bundled memory pool API" echo " replace = Replacing all occurances of data" echo " sc = Shortcut functions for Ustr's" echo " set = Setting data, strcpy() for Ustr's" echo " split = Slit the data, strtok() / strsep() for Ustr's" echo " spn = Spanning, strspn() / strcspn() for Ustr's" echo " srch = Searching, strchr() / strstr() for Ustr's" echo " sub = Substituting data" echo " utf8 = Working with UTF8" echo "" echo " Ustr Version: $VERS_FULL" exit $1 } if [ "x$1" = "x--help" ]; then usage 0 fi if [ "x$1" = "x-dd" ]; then dbg=true fulldbg=true shift else if [ "x$1" = "x-d" ]; then dbg=true shift fi if [ "x$1" = "x-d" ]; then fulldbg=true shift fi fi if [ "x$1" = "x-c" ]; then cfiles=true shift fi if [ "x$1" = "x-b" ]; then shift defbytes="$1" shift fi if [ "x$1" = "x-e" ]; then shift exact="$1" shift fi if [ "x$1" = "x-s" ]; then shift usesz="$1" shift fi all=false b=false cmp=false cntl=false fmt=false ins=false io=false main=false parse=false pool=false repl=false sc=false set=false split=false spn=false srch=false sub=false utf8=false gdb=false for i in $@; do case "$i" in all) all=true ;; b) b=true; main=true ;; cmp) cmp=true; main=true ;; cntl) cntl=true main=true ;; fmt) fmt=true; main=true ;; gdb) gdb=true; ;; ins) ins=true; main=true ;; io) io=true; main=true ;; main) main=true ;; parse) parse=true; main=true ;; pool) pool=true; main=true ;; replace) repl=true; main=true ;; sc) sc=true; main=true ;; set) set=true; main=true ;; split) split=true; main=true ;; spn) spn=true; main=true ;; srch) srch=true; main=true ;; sub) sub=true; main=true ;; utf8) utf8=true; main=true ;; *) exec 1>&2 usage 1 ;; esac done if $all; then b=true cmp=true cntl=true fmt=true gdb=true ins=true io=true main=true parse=true pool=true repl=true sc=true set=true spn=true srch=true split=true sub=true utf8=true else if $split; then set=true spn=true srch=true fi if $repl; then set=true spn=true srch=true sub=true fi if $sub; then ins=true srch=true fi if $sc; then spn=true fi if $spn; then srch=true utf8=true fi if $srch; then cmp=true fi # *.c requires file to compile... if $sc && $cfiles; then utf8=true fi if $sub && $cfiles; then fmt=true fi if $set && $cfiles; then fmt=true fi if $ins && $cfiles; then fmt=true fi fi if $gdb; then cp "$SHRDIR/.gdbinit" . if ! $main; then exit; fi else if ! $main; then exec 1>&2 usage 1 fi cp "$SHRDIR/.gdbinit" . fi if $cntl && ! $cfiles; then cntl=false echo "Warn: Can't do dynamic configuration without cfiles." 1>&2 fi # --------------------------------------------- # Copy all the files locally... # --------------------------------------------- copy() { name="$1" cp "$INCDIR/ustr-$name.h" . if test -f "$SHRDIR/ustr-$name-internal.h"; then cp "$SHRDIR/ustr-$name-internal.h" . fi if test -f "$SHRDIR/ustr-$name-code.h"; then cp "$SHRDIR/ustr-$name-code.h" . fi if $cfiles && test -f "$SHRDIR/ustr-$name-opt-code.c"; then if $dbg; then cp "$SHRDIR/ustr-$name-dbg-code.c" . else cp "$SHRDIR/ustr-$name-opt-code.c" . fi fi } if $b; then copy b fi if $cmp; then copy cmp fi if $cntl; then copy cntl cp "$SHRDIR/malloc-check.h" . fi # conf is generated from scratch copy compiler if $fmt; then copy fmt fi if $ins; then copy ins fi if $io; then copy io fi copy main if $parse; then copy parse fi if $pool; then copy pool fi if $repl; then copy replace fi if $sc; then copy sc fi if $set; then copy set fi if $split; then copy split fi if $spn; then copy spn fi if $srch; then copy srch fi if $sub; then copy sub fi if $utf8; then copy utf8 fi # --------------------------------- # Generate a valid ustr-conf.h file # --------------------------------- outname=ustr-conf.h if $dbg; then outname=ustr-conf-debug.h fi echo "/* This file is auto generated from $cmdname */" > $outname echo >> $outname echo >> $outname echo '#ifndef USTR_CONF_H' >> $outname echo '#define USTR_CONF_H 1' >> $outname echo >> $outname echo >> $outname if $cfiles; then # So they can still override, just change the default echo "/* The default is now to link against libc. */" >> $outname echo "#ifndef USTR_CONF_INCLUDE_CODEONLY_HEADERS" >> $outname echo '#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0' >> $outname echo "#endif" >> $outname echo >> $outname else echo "/* Same default, newer position. */" >> $outname echo "#ifndef USTR_CONF_INCLUDE_CODEONLY_HEADERS" >> $outname echo '#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1' >> $outname echo "#endif" >> $outname echo >> $outname fi echo "/* We can't: if defined(__GLIBC__) && (!defined(_GNU_SOURCE) || !_GNU_SOURCE)" >> $outname echo " * because by the time we've included a libc header it's too late. */ " >> $outname echo "#ifndef _GNU_SOURCE" >> $outname echo "#define _GNU_SOURCE 1" >> $outname echo "#endif" >> $outname echo >> $outname echo >> $outname if $cfiles; then echo "#if ! USTR_CONF_INCLUDE_CODEONLY_HEADERS" >> $outname echo "/* If you aren't just using the headers, these should match the .c's */" >> $outname echo >> $outname echo "# define USTR_CONF_HAVE_64bit_SIZE_MAX $autoconf_64b" >> $outname echo "# define USTR_CONF_HAVE_RETARDED_VSNPRINTF $autoconf_vsnprintf" >> $outname if [ -f "/usr/include/stdint.h" ]; then echo "# define USTR_CONF_HAVE_STDINT_H 1" >> $outname else echo "# define USTR_CONF_HAVE_STDINT_H 0" >> $outname fi if $cntl; then echo "# define USTR_CONF_HAVE_DYNAMIC_CONF 1" >> $outname else echo "# define USTR_CONF_HAVE_DYNAMIC_CONF 0" >> $outname fi echo >> $outname echo "# define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF" >> $outname echo >> $outname echo "# define USTR_CONF_REF_BYTES $defbytes" >> $outname echo "# define USTR_CONF_EXACT_BYTES $exact" >> $outname echo "# define USTR_CONF_USE_SIZE $usesz" >> $outname echo >> $outname if $dbg; then echo '# define USTR_CONF_USE_ASSERT 1' >> $outname else echo '# define USTR_CONF_USE_ASSERT 0' >> $outname fi if $fulldbg; then echo '# define USTR_CONF_USE_EOS_MARK 1' >> $outname else echo '# define USTR_CONF_USE_EOS_MARK 0' >> $outname fi echo >> $outname echo "#else" >> $outname fi echo "/* Same defaults, but can be altered at will. */" >> $outname echo "/* Note that you really shouldn't alter the _HAVE_* ones. */" >> $outname echo >> $outname echo "# ifndef USTR_CONF_HAVE_64bit_SIZE_MAX" >> $outname echo "# define USTR_CONF_HAVE_64bit_SIZE_MAX $autoconf_64b" >> $outname echo "# endif" >> $outname echo "# ifndef USTR_CONF_HAVE_RETARDED_VSNPRINTF" >> $outname echo "# define USTR_CONF_HAVE_RETARDED_VSNPRINTF $autoconf_vsnprintf" >> $outname echo "# endif" >> $outname echo "# ifndef USTR_CONF_HAVE_STDINT_H" >> $outname if [ -f "/usr/include/stdint.h" ]; then echo "# define USTR_CONF_HAVE_STDINT_H 1" >> $outname else echo "# define USTR_CONF_HAVE_STDINT_H 0" >> $outname fi echo "# endif" >> $outname echo "# ifndef USTR_CONF_HAVE_DYNAMIC_CONF" >> $outname if $cntl; then echo "# define USTR_CONF_HAVE_DYNAMIC_CONF 1" >> $outname else echo "# define USTR_CONF_HAVE_DYNAMIC_CONF 0" >> $outname fi echo "# endif" >> $outname echo >> $outname echo "/* no USE_DYNAMIC_CONF ... leave as default */" >> $outname echo >> $outname echo "# ifndef USTR_CONF_REF_BYTES" >> $outname echo "# define USTR_CONF_REF_BYTES $defbytes" >> $outname echo "# endif" >> $outname echo "# ifndef USTR_CONF_EXACT_BYTES" >> $outname echo "# define USTR_CONF_EXACT_BYTES $exact" >> $outname echo "# endif" >> $outname echo "# ifndef USTR_CONF_USE_SIZE" >> $outname echo "# define USTR_CONF_USE_SIZE $usesz" >> $outname echo "# endif" >> $outname echo >> $outname echo "# ifndef USTR_CONF_USE_ASSERT" >> $outname if $dbg; then echo '# define USTR_CONF_USE_ASSERT 1' >> $outname else echo '# define USTR_CONF_USE_ASSERT 0' >> $outname fi echo "# endif" >> $outname echo "# ifndef USTR_CONF_USE_EOS_MARK" >> $outname if $fulldbg; then echo '# define USTR_CONF_USE_EOS_MARK 1' >> $outname else echo '# define USTR_CONF_USE_EOS_MARK 0' >> $outname fi echo "# endif" >> $outname if $cfiles; then echo >> $outname echo "#endif" >> $outname echo >> $outname fi echo >> $outname echo >> $outname echo '#endif' >> $outname # ---------------------------- # Generate a valid ustr.h file # ---------------------------- outname=ustr.h if $dbg; then outname=ustr-debug.h fi echo "/* This file is auto generated from $cmdname */" > $outname echo >> $outname echo >> $outname echo '#ifndef USTR_H' >> $outname echo '#define USTR_H 1' >> $outname echo >> $outname echo >> $outname if $cfiles; then # So they can still override, just change the default echo "#ifndef USTR_CONF_INCLUDE_CODEONLY_HEADERS" >> $outname echo '#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0' >> $outname echo "#endif" >> $outname echo >> $outname fi echo >> $outname echo "#ifndef USTR_DEBUG" >> $outname if $dbg; then echo "#define USTR_DEBUG 1" >> $outname else echo "#define USTR_DEBUG 0" >> $outname fi echo "#endif" >> $outname echo >> $outname echo >> $outname # Everything deps. on CONF echo "#if USTR_DEBUG" >> $outname echo '# include "ustr-conf-debug.h"' >> $outname echo "#else" >> $outname echo '# include "ustr-conf.h"' >> $outname echo "#endif" >> $outname echo >> $outname # Everything deps. on MAIN echo '#include "ustr-main.h"' >> $outname if $b; then echo '#include "ustr-b.h"' >> $outname fi if $cmp; then echo '#include "ustr-cmp.h"' >> $outname fi # ustr-cntl is hacked into ustr-main.h ... for various reasons. if $fmt; then echo '#include "ustr-fmt.h"' >> $outname fi if $io; then echo '#include "ustr-io.h"' >> $outname fi if $ins; then # INS weak deps. on FMT echo '#include "ustr-ins.h"' >> $outname fi if $parse; then echo '#include "ustr-parse.h"' >> $outname fi if $pool; then echo '#include "ustr-pool.h"' >> $outname fi if $set; then # SET weak deps. on FMT echo '#include "ustr-set.h"' >> $outname fi if $srch; then echo '#include "ustr-srch.h"' >> $outname fi if $spn; then # SPN deps. on SRCH and weak deps. on UTF8 echo '#include "ustr-spn.h"' >> $outname fi if $split; then # SPLIT hard deps. on set, spn, srch echo '#include "ustr-split.h"' >> $outname fi if $sub; then # SUB hard deps. on ins, srch, weak dep. on FMT echo '#include "ustr-sub.h"' >> $outname fi if $repl; then # REPLACE hard deps. on set, spn, srch, sub echo '#include "ustr-replace.h"' >> $outname fi if $utf8; then echo '#include "ustr-utf8.h"' >> $outname fi if $sc; then echo '#include "ustr-sc.h"' >> $outname fi echo >> $outname echo >> $outname echo '#endif' >> $outname ustr-1.0.4/ustr-srch-internal.h0000644000076400007640000000242210674652101015420 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SRCH_INTERNAL_H #define USTR_SRCH_INTERNAL_H 1 #ifndef USTR_MAIN_H # error " You should have already included ustr-main.h, or just include ustr.h" #endif #ifndef USTR_CONF_HAVE_MEMMEM /* GNU extension */ #ifdef __GLIBC__ #define USTR_CONF_HAVE_MEMMEM 1 #else #define USTR_CONF_HAVE_MEMMEM 0 #endif #endif #if USTR_CONF_HAVE_MEMMEM /* GNU extension */ # define USTR__SYS_MEMMEM memmem #else USTR_CONF_e_PROTO void *ustr__sys_memmem(const void*, size_t,const void*,size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); # define USTR__SYS_MEMMEM ustr__sys_memmem #endif USTR_CONF_e_PROTO void *ustr__memrepchr(const void *, size_t, char, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO void *ustr__memcasechr(const void *, const char, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO void *ustr__memcasemem(const void *, size_t, const void *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO void *ustr__memcaserepchr(const void *, size_t, char, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #endif ustr-1.0.4/ustr-io-code.h0000644000076400007640000001741410735010763014175 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_IO_H #error " You should have already included ustr-io.h, or just include ustr.h." #endif USTR_CONF_i_PROTO int ustrp__io_get(struct Ustr_pool *p, struct Ustr **ps1, FILE *fp, size_t minlen, size_t *got) { size_t olen = ustr_len(*ps1); size_t ret = 0; USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1) && fp); if (!minlen) { if (got) *got = 0; return (USTR_TRUE); } if (!ustrp__add_undef(p, ps1, minlen)) return (USTR_FALSE); ret = fread(ustr_wstr(*ps1) + olen, 1, minlen, fp); if (ret < minlen) ustrp__del(p, ps1, minlen - ret); if (got) *got = ret; return (ret > 0); } USTR_CONF_I_PROTO int ustr_io_get(struct Ustr **ps1, FILE *fp, size_t minlen, size_t *got) { return (ustrp__io_get(0, ps1, fp, minlen, got)); } USTR_CONF_I_PROTO int ustrp_io_get(struct Ustr_pool *p, struct Ustrp **ps1, FILE *fp, size_t minlen, size_t *got) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__io_get(p, &tmp, fp, minlen, got); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__io_getfile(struct Ustr_pool *p, struct Ustr **ps1, FILE *fp) { const size_t blksz = (1024 * 8) - (1 + 8 + 8 + 8 + sizeof(USTR_END_ALOCDx)); size_t num = blksz; size_t got = 0; do { /* round up... not perfect as we'll be able to round up post add_undef */ size_t sz = ustr_size(*ps1); size_t clen = ustr_len(*ps1); num = blksz; if (num < (sz - clen)) num = sz - clen; } while (ustrp__io_get(p, ps1, fp, num, &got) && (got == num)); return (feof(fp)); } USTR_CONF_I_PROTO int ustr_io_getfile(struct Ustr **ps1, FILE *fp) { return (ustrp__io_getfile(0, ps1, fp)); } USTR_CONF_I_PROTO int ustrp_io_getfile(struct Ustr_pool *p, struct Ustrp **ps1, FILE *fp) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__io_getfile(p, &tmp, fp); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__io_getfilename(struct Ustr_pool *p, struct Ustr **ps1, const char *name) { FILE *fp = fopen(name, "rb"); int ret = USTR_FALSE; int save_errno = 0; if (!fp) return (USTR_FALSE); ret = ustrp__io_getfile(p, ps1, fp); save_errno = errno; fclose(fp); errno = save_errno; return (ret); } USTR_CONF_I_PROTO int ustr_io_getfilename(struct Ustr **ps1, const char *name) { return (ustrp__io_getfilename(0, ps1, name)); } USTR_CONF_I_PROTO int ustrp_io_getfilename(struct Ustr_pool *p, struct Ustrp **ps1, const char *name) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__io_getfilename(p, &tmp, name); *ps1 = USTRP(tmp); return (ret); } /* We bow to retarded GLibc getc_unlocked */ #ifdef getc_unlocked # define USTR__IO_GETC(x) getc_unlocked(x) #else # define USTR__IO_GETC(x) getc(x) #endif USTR_CONF_i_PROTO int ustrp__io_getdelim(struct Ustr_pool *p, struct Ustr **ps1, FILE *fp, char delim) { int val = EOF; size_t olen = 0; size_t clen = 0; size_t linesz = 80; /* Unix "tradition" is 80x24, assuming delim == '\n' */ USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1) && fp); olen = clen = ustr_len(*ps1); while (ustrp__add_undef(p, ps1, linesz)) { char *wstr = ustr_wstr(*ps1) + clen; size_t num = linesz; while (num && ((val = USTR__IO_GETC(fp)) != EOF)) { --num; if ((*wstr++ = val) == delim) break; } if (num) { if (!ferror(fp)) /* only way we can easily test, as it might be hanging from previously */ errno = 0; ustrp__del(p, ps1, num); break; } clen += linesz; } return ((val == delim) || ((val == EOF) && (ustr_len(*ps1) != olen))); } #undef USTR__IO_GETC USTR_CONF_I_PROTO int ustr_io_getdelim(struct Ustr **ps1, FILE *fp, char delim) { return (ustrp__io_getdelim(0, ps1, fp, delim)); } USTR_CONF_I_PROTO int ustrp_io_getdelim(struct Ustr_pool *p, struct Ustrp **ps1, FILE *fp, char delim) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__io_getdelim(p, &tmp, fp, delim); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_I_PROTO int ustr_io_getline(struct Ustr **ps1, FILE *fp) { return (ustrp__io_getdelim(0, ps1, fp, '\n')); } USTR_CONF_I_PROTO int ustrp_io_getline(struct Ustr_pool *p, struct Ustrp **ps1, FILE *fp) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__io_getdelim(p, &tmp, fp, '\n'); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__io_put(struct Ustr_pool *p, struct Ustr **ps1,FILE *fp,size_t beglen) { size_t ret = 0; size_t clen = ustr_len(*ps1); USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1) && fp); USTR_ASSERT_RET(beglen <= clen, USTR_FALSE); if (!beglen) return (USTR_TRUE); /* Because most errors only happen when a fflush() of the stdio stream, * you have to assume that any data written is indeterminate anyway. * So only go to the effort of making it determinate if beglen != clen. * If you need efficient IO, that you can deal with errors for, use Vstr * and POSIX IO. */ if ((beglen != clen) && !ustrp__sc_ensure_owner(p, ps1)) return (USTR_FALSE); if ((ret = fwrite(ustr_cstr(*ps1), 1, beglen, fp))) { int save_errno = errno; if (beglen != clen) /* Note not ret != clen, see above. */ ustrp__del_subustr(p, ps1, 1, ret); /* if it fails, see above */ else /* In certain cases this means we'll lose the config. for *ps1. But it's * worth it so we don't have to ensure_owner() all the time. If you care * pass owned Ustr's. */ ustrp__sc_del(p, ps1); errno = save_errno; } return (ret == beglen); } USTR_CONF_I_PROTO int ustr_io_put(struct Ustr **ps1, FILE *fp, size_t beglen) { return (ustrp__io_put(0, ps1, fp, beglen)); } USTR_CONF_I_PROTO int ustrp_io_put(struct Ustr_pool *p, struct Ustrp **ps1,FILE *fp,size_t beglen) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__io_put(p, &tmp, fp, beglen); *ps1 = USTRP(tmp); return (ret); } /* We bow to retarded GLibc putc_unlocked */ #ifdef putc_unlocked # define USTR__IO_PUTC(x, y) putc_unlocked(x, y) #else # define USTR__IO_PUTC(x, y) putc(x, y) #endif USTR_CONF_i_PROTO int ustrp__io_putline(struct Ustr_pool *p, struct Ustr **ps1, FILE *fp, size_t beglen) { if (!ustrp__io_put(p, ps1, fp, beglen)) return (USTR_FALSE); return (USTR__IO_PUTC('\n', fp) != EOF); } #undef USTR__IO_PUTC USTR_CONF_I_PROTO int ustr_io_putline(struct Ustr **ps1, FILE *fp, size_t beglen) { return (ustrp__io_putline(0, ps1, fp, beglen)); } USTR_CONF_I_PROTO int ustrp_io_putline(struct Ustr_pool *p, struct Ustrp **ps1, FILE *fp, size_t beglen) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__io_putline(p, &tmp, fp, beglen); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__io_putfilename(struct Ustr_pool *p, struct Ustr **ps1, const char *name, const char *mode) { FILE *fp = fopen(name, mode); int ret = USTR_FALSE; if (!fp) return (USTR_FALSE); if ((ret = ustrp__io_put(p, ps1, fp, ustr_len(*ps1)))) ret = !fclose(fp); /* if everything OK, defer to the fclose() return */ else { int save_errno = errno; /* otherwise ignore it */ fclose(fp); errno = save_errno; } return (ret); } USTR_CONF_I_PROTO int ustr_io_putfilename(struct Ustr **ps1, const char *name, const char *mode) { return (ustrp__io_putfilename(0, ps1, name, mode)); } USTR_CONF_I_PROTO int ustrp_io_putfilename(struct Ustr_pool *p, struct Ustrp **ps1, const char *name, const char *mode) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__io_putfilename(p, &tmp, name, mode); *ps1 = USTRP(tmp); return (ret); } ustr-1.0.4/LICENSE_MIT0000644000076400007640000000204010630111754013211 0ustar jamesjamesCopyright (c) 2007 James Antill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ustr-1.0.4/ustr-srch.h0000644000076400007640000004026310673027007013613 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SRCH_H #define USTR_SRCH_H 1 #ifndef USTR_MAIN_H # error " You should include ustr-main.h before this file, or just ustr.h" #endif USTR_CONF_E_PROTO size_t ustr_srch_chr_fwd(const struct Ustr *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_srch_chr_rev(const struct Ustr *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_srch_buf_fwd(const struct Ustr *, size_t, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_srch_buf_rev(const struct Ustr *, size_t, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_srch_fwd(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_srch_rev(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_srch_cstr_fwd(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_srch_cstr_rev(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_srch_subustr_fwd(const struct Ustr *, size_t, 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 size_t ustr_srch_subustr_rev(const struct Ustr *, size_t, 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 size_t ustr_srch_rep_chr_fwd(const struct Ustr *, size_t, char, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_srch_rep_chr_rev(const struct Ustr *, size_t, char, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* ignore case */ USTR_CONF_E_PROTO size_t ustr_srch_case_chr_fwd(const struct Ustr *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_srch_case_chr_rev(const struct Ustr *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_srch_case_buf_fwd(const struct Ustr *, size_t, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_srch_case_buf_rev(const struct Ustr *, size_t, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_srch_case_fwd(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_srch_case_rev(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_srch_case_cstr_fwd(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_srch_case_cstr_rev(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_srch_case_subustr_fwd(const struct Ustr *, size_t, 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 size_t ustr_srch_case_subustr_rev(const struct Ustr *, size_t, 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 size_t ustr_srch_case_rep_chr_fwd(const struct Ustr *, size_t, char, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_srch_case_rep_chr_rev(const struct Ustr *, size_t, char, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-srch-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-srch-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO size_t ustr_srch_fwd(const struct Ustr *s1, size_t off, const struct Ustr *s2) { return (ustr_srch_buf_fwd(s1, off, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO size_t ustr_srch_rev(const struct Ustr *s1, size_t off, const struct Ustr *s2) { return (ustr_srch_buf_rev(s1, off, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO size_t ustr_srch_cstr_fwd(const struct Ustr *s1, size_t off, const char *cstr) { return (ustr_srch_buf_fwd(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustr_srch_cstr_rev(const struct Ustr *s1, size_t off, const char *cstr) { return (ustr_srch_buf_rev(s1, off, cstr, strlen(cstr))); } /* ignore case */ USTR_CONF_II_PROTO size_t ustr_srch_case_fwd(const struct Ustr *s1,size_t o, const struct Ustr *s2) { return (ustr_srch_case_buf_fwd(s1, o, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO size_t ustr_srch_case_rev(const struct Ustr *s1,size_t o, const struct Ustr *s2) { return (ustr_srch_case_buf_rev(s1, o, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO size_t ustr_srch_case_cstr_fwd(const struct Ustr *s1,size_t o, const char *cstr) { return (ustr_srch_case_buf_fwd(s1, o, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustr_srch_case_cstr_rev(const struct Ustr *s1,size_t o, const char *cstr) { return (ustr_srch_case_buf_rev(s1, o, cstr, strlen(cstr))); } #endif /* ---------------- pool wrapper APIs ---------------- */ USTR_CONF_EI_PROTO size_t ustrp_srch_chr_fwd(const struct Ustrp *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_chr_rev(const struct Ustrp *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_buf_fwd(const struct Ustrp *, size_t, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_buf_rev(const struct Ustrp *, size_t, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_fwd(const struct Ustrp *, size_t, 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_srch_rev(const struct Ustrp *, size_t, 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_srch_cstr_fwd(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_cstr_rev(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_subustrp_fwd(const struct Ustrp *, size_t, 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 ustrp_srch_subustrp_rev(const struct Ustrp *, size_t, 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 ustrp_srch_rep_chr_fwd(const struct Ustrp *, size_t, char, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_rep_chr_rev(const struct Ustrp *, size_t, char, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* ignore case */ USTR_CONF_EI_PROTO size_t ustrp_srch_case_chr_fwd(const struct Ustrp *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_case_chr_rev(const struct Ustrp *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_case_buf_fwd(const struct Ustrp *,size_t, const void *,size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_case_buf_rev(const struct Ustrp *,size_t, const void *,size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_case_fwd(const struct Ustrp *, size_t, 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_srch_case_rev(const struct Ustrp *, size_t, 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_srch_case_cstr_fwd(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_case_cstr_rev(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_case_subustrp_fwd(const struct Ustrp *, size_t, 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 ustrp_srch_case_subustrp_rev(const struct Ustrp *, size_t, 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 ustrp_srch_case_rep_chr_fwd(const struct Ustrp *, size_t, char, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_srch_case_rep_chr_rev(const struct Ustrp *, size_t, char, size_t) 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_srch_chr_fwd(const struct Ustrp *s1, size_t off, char chr) { return (ustr_srch_chr_fwd(&s1->s, off, chr)); } USTR_CONF_II_PROTO size_t ustrp_srch_chr_rev(const struct Ustrp *s1, size_t off, char chr) { return (ustr_srch_chr_rev(&s1->s, off, chr)); } USTR_CONF_II_PROTO size_t ustrp_srch_buf_fwd(const struct Ustrp *s1, size_t off, const void *buf, size_t len) { return (ustr_srch_buf_fwd(&s1->s, off, buf, len)); } USTR_CONF_II_PROTO size_t ustrp_srch_buf_rev(const struct Ustrp *s1, size_t off, const void *buf, size_t len) { return (ustr_srch_buf_rev(&s1->s, off, buf, len)); } USTR_CONF_II_PROTO size_t ustrp_srch_fwd(const struct Ustrp *s1, size_t off, const struct Ustrp *s2) { return (ustr_srch_fwd(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_srch_rev(const struct Ustrp *s1, size_t off, const struct Ustrp *s2) { return (ustr_srch_rev(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_srch_cstr_fwd(const struct Ustrp *s1, size_t off, const char *cstr) { return (ustrp_srch_buf_fwd(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustrp_srch_cstr_rev(const struct Ustrp *s1, size_t off, const char *cstr) { return (ustrp_srch_buf_rev(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustrp_srch_subustrp_fwd(const struct Ustrp *s1, size_t off, const struct Ustrp *s2, size_t pos, size_t len) { return (ustr_srch_subustr_fwd(&s1->s, off, &s2->s, pos, len)); } USTR_CONF_II_PROTO size_t ustrp_srch_subustrp_rev(const struct Ustrp *s1, size_t off, const struct Ustrp *s2, size_t pos, size_t len) { return (ustr_srch_subustr_rev(&s1->s, off, &s2->s, pos, len)); } USTR_CONF_II_PROTO size_t ustrp_srch_rep_chr_fwd(const struct Ustrp *s1, size_t off, char data, size_t len) { return (ustr_srch_rep_chr_fwd(&s1->s, off, data, len)); } USTR_CONF_II_PROTO size_t ustrp_srch_rep_chr_rev(const struct Ustrp *s1, size_t off, char data, size_t len) { return (ustr_srch_rep_chr_rev(&s1->s, off, data, len)); } /* ignore case */ USTR_CONF_II_PROTO size_t ustrp_srch_case_chr_fwd(const struct Ustrp *s1, size_t off, char chr) { return (ustr_srch_case_chr_fwd(&s1->s, off, chr)); } USTR_CONF_II_PROTO size_t ustrp_srch_case_chr_rev(const struct Ustrp *s1, size_t off, char chr) { return (ustr_srch_case_chr_rev(&s1->s, off, chr)); } USTR_CONF_II_PROTO size_t ustrp_srch_case_buf_fwd(const struct Ustrp *s1, size_t off, const void *buf, size_t len) { return (ustr_srch_case_buf_fwd(&s1->s, off, buf, len)); } USTR_CONF_II_PROTO size_t ustrp_srch_case_buf_rev(const struct Ustrp *s1, size_t off, const void *buf, size_t len) { return (ustr_srch_case_buf_rev(&s1->s, off, buf, len)); } USTR_CONF_II_PROTO size_t ustrp_srch_case_fwd(const struct Ustrp *s1,size_t off, const struct Ustrp *s2) { return (ustr_srch_case_fwd(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_srch_case_rev(const struct Ustrp *s1,size_t off, const struct Ustrp *s2) { return (ustr_srch_case_rev(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_srch_case_cstr_fwd(const struct Ustrp *s1, size_t off, const char *cstr) { return (ustrp_srch_case_buf_fwd(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustrp_srch_case_cstr_rev(const struct Ustrp *s1, size_t off, const char *cstr) { return (ustrp_srch_case_buf_rev(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustrp_srch_case_subustrp_fwd(const struct Ustrp *s1, size_t off, const struct Ustrp *s2, size_t pos, size_t len) { return (ustr_srch_case_subustr_fwd(&s1->s, off, &s2->s, pos, len)); } USTR_CONF_II_PROTO size_t ustrp_srch_case_subustrp_rev(const struct Ustrp *s1, size_t off, const struct Ustrp *s2, size_t pos, size_t len) { return (ustr_srch_case_subustr_rev(&s1->s, off, &s2->s, pos, len)); } USTR_CONF_II_PROTO size_t ustrp_srch_case_rep_chr_fwd(const struct Ustrp *s1, size_t off, char data, size_t len) { return (ustr_srch_case_rep_chr_fwd(&s1->s, off, data, len)); } USTR_CONF_II_PROTO size_t ustrp_srch_case_rep_chr_rev(const struct Ustrp *s1, size_t off, char data, size_t len) { return (ustr_srch_case_rep_chr_rev(&s1->s, off, data, len)); } #endif #endif ustr-1.0.4/ustr-ins-internal.h0000644000076400007640000000241610646605207015261 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_INS_INTERNAL_H #define USTR_INS_INTERNAL_H 1 #ifndef USTR_MAIN_H # error " You should have already included ustr-main.h, or just include ustr.h" #endif USTR_CONF_e_PROTO int ustrp__ins_undef(struct Ustr_pool *, struct Ustr **ps1, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__ins_buf(struct Ustr_pool *,struct Ustr **,size_t,const void *,size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_e_PROTO int ustrp__ins(struct Ustr_pool *, struct Ustr **, size_t, const struct Ustr *) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_e_PROTO int ustrp__ins_subustr(struct Ustr_pool *, struct Ustr **, size_t, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_E_PROTO int ustrp__ins_rep_chr(struct Ustr_pool *, struct Ustr **, size_t, char, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); #ifdef USTR_FMT_H # if USTR_CONF_HAVE_VA_COPY USTR_CONF_e_PROTO int ustrp__ins_vfmt_lim(struct Ustr_pool *, struct Ustr **, size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 5)) USTR__COMPILE_ATTR_FMT(5, 0); # endif #endif #endif ustr-1.0.4/Makefile0000644000076400007640000005275010763663430013162 0ustar jamesjames # FIXME: Lots of C&P of VERSION ... # ustr*.pc, ustr.spec, Documentation/*.pl, Documentation/ustr-import.1, # ./scripts/rpms-create-james.sh VERS=1.0 VERS_FULL=$(VERS).4 VERS_BSO =1.0 VERS_ESONAME =1 VERS_ESO =$(VERS_ESONAME).0.4 DESTDIR = prefix=/usr datadir=$(prefix)/share libdir=$(prefix)/lib libexecdir=$(prefix)/libexec bindir=$(prefix)/bin includedir=$(prefix)/include SHRDIR=$(datadir)/ustr-$(VERS_FULL) DOCSHRDIR=$(datadir)/doc/ustr-devel-$(VERS_FULL) EXAMDIR=$(SHRDIR)/examples mandir=$(datadir)/doc/man MBINDIR=$(libexecdir)/ustr-$(VERS_FULL) ############################################################################### # This is here to work around the "Fedora build system requirement" that a big # pile of crap ends up in the build.log file even though all sane people don't # want that. See rhbz#248231 ############################################################################### HIDE=@ CC = cc AR = ar RANLIB = ranlib LDCONFIG = /sbin/ldconfig CFLAGS = -O2 -g # Debug versions... WARNS = -W -Wall -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Wno-format-zero-length -Wformat-nonliteral -Wformat-security # -Wfloat-equal -- no floats # Fedora policies/"reviewers" are completely retarded and refuse to allow # lowering the "Fedora build flags" even when it activley hurts their users, # this makes it easier for them to hurt you. Welcome to the lowest common # denominator collective. DBG_ONLY_BAD_POLICIES_HAVE_THIS_EMPTY_CFLAGS=-O1 DBG_CFLAGS = $(CFLAGS) $(WARNS) $(DBG_ONLY_BAD_POLICIES_HAVE_THIS_EMPTY_CFLAGS) # Inline tst_*.c and otst_*.c files. CFLG_TST = CFLG_TST_C = $(CFLG_TST) \ -DUSTR_CONF_INCLUDE_CODEONLY_HEADERS=1 -DUSTR_CONF_REF_BYTES=4 # Optimized o*.c files CFLG_TST_O = -DUSTR_DEBUG=0 $(CFLG_TST) CFLG_TST_CO = -DUSTR_DEBUG=0 $(CFLG_TST_C) # fread64/etc. CFLG_LIB = -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 CFLG_LIB_OPT = $(CFLG_LIB) -DNDEBUG CFLG_LIB_DBG = $(CFLG_LIB) DOCS = README-DEVELOPERS TODO \ Documentation/strdup\ vs.\ ustr.gnumeric \ Documentation/index.html \ Documentation/functions.html \ Documentation/constants.html \ Documentation/design.html \ Documentation/tutorial.html MAN_PAGES_1 = \ Documentation/ustr-import.1 MAN_PAGES_3 = \ Documentation/ustr.3 \ Documentation/ustr_const.3 EXAMPLES = examples/Makefile \ examples/basename.c \ examples/custr.c \ examples/dirname.c \ examples/fgrep.c \ examples/hello_world.c \ examples/hexdump.c \ examples/linecat.c \ examples/mkdir_p.c \ examples/netstr.c \ examples/nums.c \ examples/txt2html.c # Some versions of GCC really don't like all the includes with inline stuff. # so we allow the library only to be checked. This is _bad_ for a release as # it basically means ustr-import usage (without -c) will kill GCC too. TST_STATIC_ALL = tst_0_sizes tst_0_manual \ otst_0_sizes otst_0_manual \ tst_0_nothing \ otst_0_nothing \ tst_1_basic \ otst_1_basic \ tst_2_small \ otst_2_small \ tst_3_medium \ otst_3_medium \ tst_4_grow \ otst_4_grow \ tst_5_shrink \ otst_5_shrink \ tst_6_tiny \ otst_6_tiny \ tst_7_auto \ otst_7_auto \ tst_8_spn \ otst_8_spn \ tst_9_ins \ otst_9_ins \ tst_10_b \ otst_10_b \ tst_11_io \ otst_11_io \ tst_12_fmt \ otst_12_fmt \ tst_13_utf8 \ otst_13_utf8 \ tst_14_cmp \ otst_14_cmp \ tst_15_trim \ otst_15_trim \ tst_16_parse \ otst_16_parse \ tst_17_sub \ otst_17_sub \ tst_18_split \ otst_18_split \ tst_19_concat \ otst_19_concat \ tst_19_join \ otst_19_join \ tst_98_pool \ otst_98_pool \ tst_99_enomem \ otst_99_enomem \ tst_99_64bit \ otst_99_64bit TST_ALL = ctst_0_cntl \ octst_0_cntl \ ctst_0_nothing \ octst_0_nothing \ ctst_3_medium \ octst_3_medium \ ctst_4_grow \ octst_4_grow \ ctst_5_shrink \ octst_5_shrink \ ctst_7_auto \ octst_7_auto \ ctst_8_spn \ octst_8_spn \ ctst_9_ins \ octst_9_ins \ ctst_10_b \ octst_10_b \ ctst_11_io \ octst_11_io \ ctst_12_fmt \ octst_12_fmt \ ctst_13_utf8 \ octst_13_utf8 \ ctst_14_cmp \ octst_14_cmp \ ctst_15_trim \ octst_15_trim \ ctst_16_parse \ octst_16_parse \ ctst_17_sub \ octst_17_sub \ ctst_18_split \ octst_18_split \ ctst_19_concat \ octst_19_concat \ ctst_19_join \ octst_19_join \ ctst_98_pool \ octst_98_pool \ ctst_99_enomem \ octst_99_enomem \ ctst_99_64bit \ octst_99_64bit \ $(TST_STATIC_ALL) XFAIL_TESTS = SRC_HDRS = ustr.h ustr-debug.h \ ustr-conf.h ustr-conf-debug.h \ ustr-b.h \ ustr-cmp.h \ ustr-cntl.h \ ustr-compiler.h \ ustr-fmt.h \ ustr-io.h \ ustr-ins.h \ ustr-main.h \ ustr-parse.h \ ustr-pool.h \ ustr-replace.h \ ustr-sc.h \ ustr-set.h \ ustr-split.h \ ustr-spn.h \ ustr-srch.h \ ustr-sub.h \ ustr-utf8.h SRC_HDRS_MULTI_LIB = \ ustr-conf-multilib-linux.h ustr-conf-debug-multilib-linux.h \ SRC_SRCS_H = malloc-check.h \ ustr-b-code.h \ ustr-cmp-code.h \ ustr-cmp-internal.h \ ustr-cntl-code.h \ ustr-fmt-code.h \ ustr-fmt-internal.h \ ustr-io-code.h \ ustr-io-internal.h \ ustr-ins-code.h \ ustr-ins-internal.h \ ustr-main-code.h \ ustr-main-internal.h \ ustr-parse-code.h \ ustr-pool-code.h \ ustr-replace-code.h \ ustr-replace-internal.h \ ustr-sc-code.h \ ustr-sc-internal.h \ ustr-set-code.h \ ustr-set-internal.h \ ustr-split-code.h \ ustr-split-internal.h \ ustr-spn-code.h \ ustr-srch-code.h \ ustr-srch-internal.h \ ustr-sub-code.h \ ustr-sub-internal.h \ ustr-utf8-code.h \ ustr-utf8-internal.h SRC_SRCS_C = ustr-b-dbg-code.c \ ustr-cmp-dbg-code.c \ ustr-fmt-dbg-code.c \ ustr-io-dbg-code.c \ ustr-ins-dbg-code.c \ ustr-main-dbg-code.c \ ustr-parse-dbg-code.c \ ustr-pool-dbg-code.c \ ustr-replace-dbg-code.c \ ustr-sc-dbg-code.c \ ustr-set-dbg-code.c \ ustr-split-dbg-code.c \ ustr-spn-dbg-code.c \ ustr-srch-dbg-code.c \ ustr-sub-dbg-code.c \ ustr-utf8-dbg-code.c \ \ ustr-b-opt-code.c \ ustr-cmp-opt-code.c \ ustr-fmt-opt-code.c \ ustr-io-opt-code.c \ ustr-ins-opt-code.c \ ustr-main-opt-code.c \ ustr-parse-opt-code.c \ ustr-pool-opt-code.c \ ustr-replace-opt-code.c \ ustr-sc-opt-code.c \ ustr-set-opt-code.c \ ustr-split-opt-code.c \ ustr-spn-opt-code.c \ ustr-srch-opt-code.c \ ustr-sub-opt-code.c \ ustr-utf8-opt-code.c SRC_SRCS = $(SRC_SRCS_C) $(SRC_SRCS_H) XSRC_SRCS = .gdbinit DBG_LIB_SHAREDEV = libustr-debug.so DBG_LIB_SHARED_NAME = libustr-debug-$(VERS_BSO).so.$(VERS_ESONAME) DBG_LIB_SHARED = libustr-debug-$(VERS_BSO).so.$(VERS_ESO) DBG_LIB_STATIC = libustr-debug.a OPT_LIB_SHAREDEV = libustr.so OPT_LIB_SHARED_NAME = libustr-$(VERS_BSO).so.$(VERS_ESONAME) OPT_LIB_SHARED = libustr-$(VERS_BSO).so.$(VERS_ESO) OPT_LIB_STATIC = libustr.a LIB_SHARED = $(DBG_LIB_SHARED) $(OPT_LIB_SHARED) LIB_STATIC = $(DBG_LIB_STATIC) $(OPT_LIB_STATIC) DEPS_NONC_ALL = $(SRC_HDRS) $(SRC_SRCS_H) DEPS_C_ALL = $(SRC_HDRS) OBJS_C_DBG_ALL = $(DBG_LIB_STATIC) OBJS_C_OPT_ALL = $(OPT_LIB_STATIC) LIB_SHARED_DBG = \ ustr-b-code-so-dbg.o \ ustr-cmp-code-so-dbg.o \ ustr-fmt-code-so-dbg.o \ ustr-io-code-so-dbg.o \ ustr-ins-code-so-dbg.o \ ustr-main-code-so-dbg.o \ ustr-parse-code-so-dbg.o \ ustr-pool-code-so-dbg.o \ ustr-replace-code-so-dbg.o \ ustr-sc-code-so-dbg.o \ ustr-set-code-so-dbg.o \ ustr-split-code-so-dbg.o \ ustr-spn-code-so-dbg.o \ ustr-srch-code-so-dbg.o \ ustr-sub-code-so-dbg.o \ ustr-utf8-code-so-dbg.o LIB_STATIC_DBG = \ ustr-b-code-a-dbg.o \ ustr-cmp-code-a-dbg.o \ ustr-fmt-code-a-dbg.o \ ustr-io-code-a-dbg.o \ ustr-ins-code-a-dbg.o \ ustr-main-code-a-dbg.o \ ustr-parse-code-a-dbg.o \ ustr-pool-code-a-dbg.o \ ustr-replace-code-a-dbg.o \ ustr-sc-code-a-dbg.o \ ustr-set-code-a-dbg.o \ ustr-split-code-a-dbg.o \ ustr-spn-code-a-dbg.o \ ustr-srch-code-a-dbg.o \ ustr-sub-code-a-dbg.o \ ustr-utf8-code-a-dbg.o LIB_SHARED_OPT = \ ustr-b-code-so-opt.o \ ustr-cmp-code-so-opt.o \ ustr-fmt-code-so-opt.o \ ustr-io-code-so-opt.o \ ustr-ins-code-so-opt.o \ ustr-main-code-so-opt.o \ ustr-parse-code-so-opt.o \ ustr-pool-code-so-opt.o \ ustr-replace-code-so-opt.o \ ustr-sc-code-so-opt.o \ ustr-set-code-so-opt.o \ ustr-split-code-so-opt.o \ ustr-spn-code-so-opt.o \ ustr-srch-code-so-opt.o \ ustr-sub-code-so-opt.o \ ustr-utf8-code-so-opt.o LIB_STATIC_OPT = \ ustr-b-code-a-opt.o \ ustr-cmp-code-a-opt.o \ ustr-fmt-code-a-opt.o \ ustr-io-code-a-opt.o \ ustr-ins-code-a-opt.o \ ustr-main-code-a-opt.o \ ustr-parse-code-a-opt.o \ ustr-pool-code-a-opt.o \ ustr-replace-code-a-opt.o \ ustr-sc-code-a-opt.o \ ustr-set-code-a-opt.o \ ustr-split-code-a-opt.o \ ustr-spn-code-a-opt.o \ ustr-srch-code-a-opt.o \ ustr-sub-code-a-opt.o \ ustr-utf8-code-a-opt.o all: ustr-import $(LIB_STATIC) $(HIDE)echo Done static all-shared: all $(LIB_SHARED) $(HIDE)echo Done shared install: all-shared ustr.pc ustr-debug.pc $(HIDE)echo Making directories install -d $(DESTDIR)$(libdir) install -d $(DESTDIR)$(includedir) install -d $(DESTDIR)$(SHRDIR) install -d $(DESTDIR)$(DOCSHRDIR) install -d $(DESTDIR)$(EXAMDIR) install -d $(DESTDIR)$(mandir)/man1 install -d $(DESTDIR)$(mandir)/man3 install -d $(DESTDIR)$(bindir) install -d $(DESTDIR)$(libdir)/pkgconfig $(HIDE)echo Installing files install -m 644 -t $(DESTDIR)$(libdir) $(LIB_STATIC) install -m 755 -t $(DESTDIR)$(libdir) $(LIB_SHARED) -rm -f $(DESTDIR)$(libdir)/$(OPT_LIB_SHARED_NAME) ln -s $(OPT_LIB_SHARED) $(DESTDIR)$(libdir)/$(OPT_LIB_SHARED_NAME) -rm -f $(DESTDIR)$(libdir)/$(OPT_LIB_SHAREDEV) ln -s $(OPT_LIB_SHARED_NAME) $(DESTDIR)$(libdir)/$(OPT_LIB_SHAREDEV) -rm -f $(DESTDIR)$(libdir)/$(DBG_LIB_SHARED_NAME) ln -s $(DBG_LIB_SHARED) $(DESTDIR)$(libdir)/$(DBG_LIB_SHARED_NAME) -rm -f $(DESTDIR)$(libdir)/$(DBG_LIB_SHAREDEV) ln -s $(DBG_LIB_SHARED_NAME) $(DESTDIR)$(libdir)/$(DBG_LIB_SHAREDEV) $(LDCONFIG) -n $(DESTDIR)$(libdir) install -pm 644 -t $(DESTDIR)$(includedir) $(SRC_HDRS) install -pm 644 -t $(DESTDIR)$(SHRDIR) $(SRC_SRCS) install -pm 644 -t $(DESTDIR)$(SHRDIR) $(XSRC_SRCS) install -pm 644 -t $(DESTDIR)$(DOCSHRDIR) $(DOCS) install -pm 644 -t $(DESTDIR)$(EXAMDIR) $(EXAMPLES) install -pm 644 -t $(DESTDIR)$(mandir)/man1 $(MAN_PAGES_1) install -pm 644 -t $(DESTDIR)$(mandir)/man3 $(MAN_PAGES_3) install -m 755 -t $(DESTDIR)$(bindir) ustr-import install -pm 644 -t $(DESTDIR)$(libdir)/pkgconfig ustr.pc ustr-debug.pc ustr-import-multilib: ustr-import-multilib.in sed -e 's,@INCLUDEDIR@,$(includedir),g' -e 's,@MBINDIR@,$(MBINDIR),g' < $< > $@ install-multilib-linux: install autoconf_64b ustr-import-multilib install -d $(DESTDIR)$(MBINDIR) $(HIDE)mlib=`./autoconf_64b`; \ if test "x$$mlib" = "x1"; then mlib=64; else mlib=32; fi; \ mv -f $(DESTDIR)$(includedir)/ustr-conf-debug.h \ $(DESTDIR)$(includedir)/ustr-conf-debug-$$mlib.h; \ mv -f $(DESTDIR)$(includedir)/ustr-conf.h \ $(DESTDIR)$(includedir)/ustr-conf-$$mlib.h; \ mv -f $(DESTDIR)$(bindir)/ustr-import \ $(DESTDIR)$(MBINDIR)/ustr-import-$$mlib install -m 644 -t $(DESTDIR)$(includedir) $(SRC_HDRS_MULTI_LIB) $(HIDE)mv -f $(DESTDIR)$(includedir)/ustr-conf-debug-multilib-linux.h $(DESTDIR)$(includedir)/ustr-conf-debug.h $(HIDE)mv -f $(DESTDIR)$(includedir)/ustr-conf-multilib-linux.h $(DESTDIR)$(includedir)/ustr-conf.h install -m 755 -t $(DESTDIR)$(bindir) ustr-import-multilib $(HIDE)mv -f $(DESTDIR)$(bindir)/ustr-import-multilib $(DESTDIR)$(bindir)/ustr-import $(HIDE)touch --reference ustr-conf-multilib-linux.h $(DESTDIR)$(includedir)/ustr-conf.h $(HIDE)touch --reference ustr-conf-debug-multilib-linux.h $(DESTDIR)$(includedir)/ustr-conf-debug.h $(HIDE)touch --reference ustr-import-multilib.in $(DESTDIR)$(bindir)/ustr-import clean: $(HIDE)echo Cleanup $(HIDE)rm -f $(LIB_SHARED) $(LIB_STATIC) $(HIDE)rm -f $(TST_ALL) $(HIDE)rm -f *.o $(HIDE)rm -f perf-sizes perf-sizes32 perf-sizes64 $(HIDE)rm -f *.gcda *.gcno *.gcov $(HIDE)rm -f tst_*.c ctst_*.c otst_*.c octst_*.c $(HIDE)rm -f ustr-import-multilib distclean: clean rm -f ustr-import rm -f autoconf_64b autoconf_vsnprintf rm -f ustr-conf.h ustr-conf-debug.h rm -rf lcov-output ustr-import: ustr-import.in autoconf_64b autoconf_vsnprintf $(HIDE)echo Creating $@ $(HIDE)sz64=`./autoconf_64b`; vsnp=`./autoconf_vsnprintf`; \ sed -e 's,@INCLUDEDIR@,$(includedir),g' -e 's,@SHRDIR@,$(SHRDIR),g' -e 's,@VERS@,$(VERS),g' -e 's,@VERS_FULL@,$(VERS_FULL),g' -e "s,@HAVE_64bit_SIZE_MAX@,$$sz64,g" -e "s,@HAVE_RETARDED_VSNPRINTF@,$$vsnp,g" < $< > $@ $(HIDE)chmod 755 $@ # Use CFLAGS so that CFLAGS="... -m32" does the right thing autoconf_64b: autoconf_64b.c $(HIDE)echo Compiling: auto configuration test: 64bit $(HIDE)$(CC) $(CFLAGS) -o $@ $< autoconf_vsnprintf: autoconf_vsnprintf.c $(HIDE)echo Compiling: auto configuration test: vsnprintf $(HIDE)$(CC) -o $@ $< # Use LDFLAGS for LDFLAGS="-m32" $(OPT_LIB_SHARED): $(LIB_SHARED_OPT) $(HIDE)echo Linking SO OPT lib: $@ $(HIDE)$(CC) -shared $^ -Wl,-soname -Wl,$(OPT_LIB_SHARED_NAME) -Wl,-version-script -Wl,libustr.ver $(LDFLAGS) -o $@ $(DBG_LIB_SHARED): $(LIB_SHARED_DBG) $(HIDE)echo Linking SO DBG lib: $@ $(HIDE)$(CC) -shared $^ -Wl,-soname -Wl,$(DBG_LIB_SHARED_NAME) -Wl,-version-script -Wl,libustr.ver $(LDFLAGS) -o $@ libustr.a: $(LIB_STATIC_OPT) $(HIDE)echo Linking A OPT lib: $@ $(HIDE)$(AR) ru $@ $^ $(HIDE)$(RANLIB) $@ libustr-debug.a: $(LIB_STATIC_DBG) $(HIDE)echo Linking A DBG lib: $@ $(HIDE)$(AR) ru $@ $^ $(HIDE)$(RANLIB) $@ ustr-conf.h: ustr-conf.h.in autoconf_64b autoconf_vsnprintf $(HIDE)echo Creating $@ $(HIDE)have_stdint_h=0; dbg1=0; dbg2=0; \ sz64=`./autoconf_64b`; vsnp=`./autoconf_vsnprintf`; \ if test -f "/usr/include/stdint.h"; then have_stdint_h=1; fi; \ if test -f "$(prefix)/include/stdint.h"; then have_stdint_h=1; fi; \ if test -f "$(includedir)/stdint.h"; then have_stdint_h=1; fi; \ sed -e "s,@HAVE_STDINT_H@,$$have_stdint_h,g" -e "s,@USE_ASSERT@,$$dbg1,g" -e "s,@USE_EOS_MARK@,$$dbg2,g" -e "s,@HAVE_64bit_SIZE_MAX@,$$sz64,g" -e "s,@HAVE_RETARDED_VSNPRINTF@,$$vsnp,g" < $< > $@ ustr-conf-debug.h: ustr-conf.h.in autoconf_64b autoconf_vsnprintf $(HIDE)echo Creating $@ $(HIDE)have_stdint_h=0; dbg1=1; dbg2=1; \ sz64=`./autoconf_64b`; vsnp=`./autoconf_vsnprintf`; \ if test -f "/usr/include/stdint.h"; then have_stdint_h=1; fi; \ if test -f "$(prefix)/include/stdint.h"; then have_stdint_h=1; fi; \ if test -f "$(includedir)/stdint.h"; then have_stdint_h=1; fi; \ sed -e "s,@HAVE_STDINT_H@,$$have_stdint_h,g" -e "s,@USE_ASSERT@,$$dbg1,g" -e "s,@USE_EOS_MARK@,$$dbg2,g" -e "s,@HAVE_64bit_SIZE_MAX@,$$sz64,g" -e "s,@HAVE_RETARDED_VSNPRINTF@,$$vsnp,g" < $< > $@ # We don't use $(DEPS_NONC_ALL) as deps. because it then recompiles everything # too much, and we care about speed more. Do make clean to "fix". # Yes, scons fixes this. %-code-so-opt.o: %-opt-code.c %-code.h %.h $(DEPS_C_ALL) $(HIDE)echo Compiling for SO OPT lib: $< $(HIDE)$(CC) $(CFLAGS) -fPIC $(CFLG_LIB_OPT) -o $@ -c $< %-code-so-dbg.o: %-dbg-code.c %-code.h %.h $(DEPS_C_ALL) $(HIDE)echo Compiling for SO DBG lib: $< $(HIDE)$(CC) $(DBG_CFLAGS) -fPIC $(CFLG_LIB_DBG) -o $@ -c $< %-code-a-opt.o: %-opt-code.c %-code.h %.h $(DEPS_C_ALL) $(HIDE)echo Compiling for A OPT lib: $< $(HIDE)$(CC) $(CFLAGS) $(CFLG_LIB_OPT) -o $@ -c $< %-code-a-dbg.o: %-dbg-code.c %-code.h %.h $(DEPS_C_ALL) $(HIDE)echo Compiling for A DBG lib: $< $(HIDE)$(CC) $(DBG_CFLAGS) $(CFLG_LIB_DBG) -o $@ -c $< perf-sizes: perf-sizes.c $(OBJS_C_OPT_ALL) $(CC) $(WARNS) -O2 -g $(LDFLAGS) -o $@ $^ perf-sizes32: perf-sizes.c $(OBJS_C_OPT_ALL) $(CC) $(WARNS) -O2 -g $(LDFLAGS) -m32 -o $@ $^ perf-sizes64: perf-sizes.c $(OBJS_C_OPT_ALL) $(CC) $(WARNS) -O2 -g $(LDFLAGS) -m64 -o $@ $^ # We "generate" the test files ... because "make clean" then makes the # dir. readble. And it helps coverage testing. tst_%.c: T/tst_%.c T/ctst_%.c $(HIDE)cat $^ > $@ otst_%.c: T/tst_%.c T/ctst_%.c $(HIDE)cat $^ > $@ ctst_%.c: T/ctst_%.c $(HIDE)cat $< > $@ octst_%.c: T/ctst_%.c $(HIDE)cat $< > $@ # Debugging tst and "compiled" tst (links with libustr-debug) tst_%.o: tst_%.c tst.h $(DEPS_NONC_ALL) $(HIDE)echo "Compiling: " $@ $(HIDE)$(CC) $(DBG_CFLAGS) $(CFLG_TST_C) -o $@ -c $< tst_%: tst_%.o $(HIDE)$(CC) $(LDFLAGS) -o $@ $< ctst_%.o: ctst_%.c tst.h $(DEPS_C_ALL) $(HIDE)echo "Compiling: " $@ $(HIDE)$(CC) $(DBG_CFLAGS) $(CFLG_TST) -o $@ -c $< ctst_%: ctst_%.o $(OBJS_C_DBG_ALL) $(HIDE)$(CC) $(LDFLAGS) -o $@ $^ # Optimized tst and "compiled" tst (links with libustr) otst_%.o: otst_%.c tst.h $(DEPS_NONC_ALL) $(HIDE)echo "Compiling: " $@ $(HIDE)$(CC) $(CFLAGS) $(CFLG_TST_CO) -o $@ -c $< otst_%: otst_%.o $(HIDE)$(CC) $(LDFLAGS) -o $@ $< octst_%.o: octst_%.c tst.h $(DEPS_C_ALL) $(HIDE)echo "Compiling:" $@ $(HIDE)$(CC) $(CFLAGS) $(CFLG_TST_O) -o $@ -c $< octst_%: octst_%.o $(OBJS_C_OPT_ALL) $(HIDE)$(CC) $(LDFLAGS) -o $@ $^ check-lcov: check ./scripts/lcov.sh ./scripts/lcov.sh # -------------------------------- # Borrowed from automake output... # -------------------------------- PACKAGE_BUGREPORT = "james@and.org" check: $(DBG_LIB_STATIC) $(TST_ALL) $(HIDE)failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \ list=' $(TST_ALL) '; \ if test -n "$$list"; then \ for tst in $$list; do \ if ./$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *$$ws$$tst$$ws*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *$$ws$$tst$$ws*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ echo "SKIP: $$tst"; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ skipped="($$skip tests were not run)"; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ else :; fi ustr-1.0.4/ustr-sub-internal.h0000644000076400007640000000450510647723521015263 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_SUB_INTERNAL_H #define USTR_SUB_INTERNAL_H 1 #ifndef USTR_MAIN_H # error " You should have already included ustr-main.h, or just include ustr.h" #endif USTR_CONF_e_PROTO int ustrp__sub_undef(struct Ustr_pool *, struct Ustr **, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__sub_buf(struct Ustr_pool *,struct Ustr **,size_t,const void*,size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_e_PROTO int ustrp__sub(struct Ustr_pool *, struct Ustr **,size_t, const struct Ustr *) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_e_PROTO int ustrp__sub_subustr(struct Ustr_pool *, struct Ustr **, size_t, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_e_PROTO int ustrp__sub_rep_chr(struct Ustr_pool *, struct Ustr **, size_t, char,size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__sc_sub_undef(struct Ustr_pool *,struct Ustr **,size_t,size_t,size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__sc_sub_buf(struct Ustr_pool *, struct Ustr **, size_t, size_t, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 5)); USTR_CONF_e_PROTO int ustrp__sc_sub(struct Ustr_pool *, struct Ustr **, size_t, size_t, const struct Ustr *) USTR__COMPILE_ATTR_NONNULL_L((2, 5)); USTR_CONF_e_PROTO int ustrp__sc_sub_subustr(struct Ustr_pool *, struct Ustr **, size_t, size_t, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 5)); USTR_CONF_e_PROTO int ustrp__sc_sub_rep_chr(struct Ustr_pool *, struct Ustr **, size_t, size_t, char, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); #ifdef USTR_FMT_H # if USTR_CONF_HAVE_VA_COPY USTR_CONF_e_PROTO int ustrp__sub_vfmt_lim(struct Ustr_pool *, struct Ustr **, size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 5)) USTR__COMPILE_ATTR_FMT(5, 0); USTR_CONF_e_PROTO int ustrp__sc_sub_vfmt_lim(struct Ustr_pool *, struct Ustr **, size_t, size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 6)) USTR__COMPILE_ATTR_FMT(6, 0); # endif #endif #endif ustr-1.0.4/ustr-spn-code.h0000644000076400007640000001545410755352540014374 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SPN_H #error " You should have already included ustr-spn.h, or just include ustr.h." #endif #ifndef USTR_SRCH_H #error " You should have already included ustr-srch.h, or just include ustr.h." #endif USTR_CONF_I_PROTO size_t ustr_spn_chr_fwd(const struct Ustr *s1, size_t off, char chr) { const char *ptr = 0; size_t len = 0; size_t clen = 0; USTR_ASSERT(ustr_assert_valid(s1)); ptr = ustr_cstr(s1); len = ustr_len(s1); USTR_ASSERT_RET(off <= len, 0); ptr += off; len -= off; clen = len; while (len) { if (*ptr != chr) break; ++ptr; --len; } return (clen - len); } USTR_CONF_I_PROTO size_t ustr_spn_chr_rev(const struct Ustr *s1, size_t off, char chr) { const char *ptr = 0; size_t len = 0; size_t clen = 0; USTR_ASSERT(ustr_assert_valid(s1)); ptr = ustr_cstr(s1); len = ustr_len(s1); USTR_ASSERT_RET(off <= len, 0); len -= off; clen = len; ptr += len; while (len) { --ptr; if (*ptr != chr) break; --len; } return (clen - len); } USTR_CONF_I_PROTO size_t ustr_spn_chrs_fwd(const struct Ustr *s1, size_t off, const char *chrs, size_t slen) { const char *ptr = 0; size_t len = 0; size_t clen = 0; USTR_ASSERT(chrs); if (slen == 1) return (ustr_spn_chr_fwd(s1, off, *chrs)); USTR_ASSERT(ustr_assert_valid(s1)); ptr = ustr_cstr(s1); len = ustr_len(s1); USTR_ASSERT_RET(off <= len, 0); ptr += off; len -= off; clen = len; while (len) { if (!memchr(chrs, *ptr, slen)) break; ++ptr; --len; } return (clen - len); } USTR_CONF_I_PROTO size_t ustr_spn_chrs_rev(const struct Ustr *s1, size_t off, const char *chrs, size_t slen) { const char *ptr = 0; size_t len = 0; size_t clen = 0; USTR_ASSERT(chrs); if (slen == 1) return (ustr_spn_chr_rev(s1, off, *chrs)); USTR_ASSERT(ustr_assert_valid(s1)); ptr = ustr_cstr(s1); len = clen = ustr_len(s1); USTR_ASSERT_RET(off <= len, 0); len -= off; clen = len; ptr += len; while (len) { --ptr; if (!memchr(chrs, *ptr, slen)) break; --len; } return (clen - len); } USTR_CONF_I_PROTO size_t ustr_cspn_chr_fwd(const struct Ustr *s1, size_t off, char chr) { size_t f_pos = ustr_srch_chr_fwd(s1, off, chr); if (!f_pos) return (ustr_len(s1) - off); return (f_pos - off - 1); } USTR_CONF_I_PROTO size_t ustr_cspn_chr_rev(const struct Ustr *s1, size_t off, char chr) { size_t f_pos = ustr_srch_chr_rev(s1, off, chr); if (!f_pos) return (ustr_len(s1) - off); return ((ustr_len(s1) - f_pos) - off); } USTR_CONF_I_PROTO size_t ustr_cspn_chrs_fwd(const struct Ustr *s1, size_t off, const char *chrs, size_t slen) { const char *ptr = 0; size_t len = 0; size_t clen = 0; USTR_ASSERT(chrs); if (slen == 1) return (ustr_cspn_chr_fwd(s1, off, *chrs)); USTR_ASSERT(ustr_assert_valid(s1)); ptr = ustr_cstr(s1); len = ustr_len(s1); USTR_ASSERT_RET(off <= len, 0); ptr += off; len -= off; clen = len; while (len) { if (memchr(chrs, *ptr, slen)) break; ++ptr; --len; } return (clen - len); } USTR_CONF_I_PROTO size_t ustr_cspn_chrs_rev(const struct Ustr *s1, size_t off, const char *chrs, size_t slen) { const char *ptr = 0; size_t len = 0; size_t clen = 0; USTR_ASSERT(chrs); if (slen == 1) return (ustr_cspn_chr_rev(s1, off, *chrs)); USTR_ASSERT(ustr_assert_valid(s1)); ptr = ustr_cstr(s1); len = ustr_len(s1); USTR_ASSERT_RET(off <= len, 0); len -= off; clen = len; ptr += len; while (len) { --ptr; if (memchr(chrs, *ptr, slen)) break; --len; } return (clen - len); } #ifdef USTR_UTF8_H USTR_CONF_I_PROTO size_t ustr_utf8_spn_chrs_fwd(const struct Ustr*s1,size_t off, const char *pchrs, size_t slen) { const unsigned char *chrs = (const unsigned char *)pchrs; const unsigned char *ptr = 0; size_t ret = 0; USTR_ASSERT(chrs); USTR_ASSERT(ustr_assert_valid(s1)); ptr = (const unsigned char *)ustr_cstr(s1); if (off) off = ustr_utf8_chars2bytes(s1, 1, off, 0); ptr += off; while (*ptr) { const unsigned char *bptr = ptr; ptr = ustr__utf8_next(ptr); if (!ptr || !USTR__SYS_MEMMEM(chrs, slen, bptr, ptr - bptr)) break; ++ret; } return (ret); } USTR_CONF_I_PROTO size_t ustr_utf8_spn_chrs_rev(const struct Ustr*s1,size_t off, const char *pchrs, size_t slen) { const unsigned char *chrs = (const unsigned char *)pchrs; const unsigned char *ptr = 0; size_t len = 0; size_t ret = 0; USTR_ASSERT(chrs); USTR_ASSERT(ustr_assert_valid(s1)); ptr = (const unsigned char *)ustr_cstr(s1); len = ustr_len(s1); if (off) { size_t ulen = ustr_utf8_len(s1); size_t dummy; off = ustr_utf8_chars2bytes(s1, ulen - off, off, &dummy); } len -= off; while (len) { const unsigned char *eptr = ptr + len; const unsigned char *bptr = ustr__utf8_prev(eptr, len); if (!bptr || !USTR__SYS_MEMMEM(chrs, slen, bptr, eptr - bptr)) break; ++ret; len -= (eptr - bptr); } return (ret); } USTR_CONF_I_PROTO size_t ustr_utf8_cspn_chrs_fwd(const struct Ustr *s1, size_t off, const char *pchrs, size_t slen) { const unsigned char *chrs = (const unsigned char *)pchrs; const unsigned char *ptr = 0; size_t ret = 0; USTR_ASSERT(chrs); USTR_ASSERT(ustr_assert_valid(s1)); ptr = (const unsigned char *)ustr_cstr(s1); if (off) off = ustr_utf8_chars2bytes(s1, 1, off, 0); ptr += off; while (*ptr) { const unsigned char *bptr = ptr; ptr = ustr__utf8_next(ptr); if (USTR__SYS_MEMMEM(chrs, slen, bptr, ptr - bptr)) break; ++ret; } return (ret); } USTR_CONF_I_PROTO size_t ustr_utf8_cspn_chrs_rev(const struct Ustr *s1, size_t off, const char *pchrs, size_t slen) { const unsigned char *chrs = (const unsigned char *)pchrs; const unsigned char *ptr = 0; size_t len = 0; size_t ret = 0; USTR_ASSERT(chrs); USTR_ASSERT(ustr_assert_valid(s1)); ptr = (const unsigned char *)ustr_cstr(s1); len = ustr_len(s1); if (off) { size_t ulen = ustr_utf8_len(s1); size_t dummy; off = ustr_utf8_chars2bytes(s1, ulen - off, off, &dummy); } len -= off; while (len) { const unsigned char *eptr = ptr + len; const unsigned char *bptr = ustr__utf8_prev(eptr, len); if (!bptr || USTR__SYS_MEMMEM(chrs, slen, bptr, eptr - bptr)) break; ++ret; len -= (eptr - bptr); } return (ret); } #endif ustr-1.0.4/ustr.pc0000644000076400007640000000015210760727033013025 0ustar jamesjamesName: Ustr Description: String Library # FIXME: More C&P of VERSION Version: 1.0.4 Cflags: Libs: -lustr ustr-1.0.4/ustr-set-dbg-code.c0000644000076400007640000000133110674563614015107 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-fmt.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-set.h" ustr-1.0.4/ustr-fmt-internal.h0000644000076400007640000000351510721115501015242 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_FMT_INTERNAL_H #define USTR_FMT_INTERNAL_H 1 #ifndef USTR_MAIN_H # error " You should have already included ustr-main.h, or just include ustr.h" #endif /* snprintf is "expensive", so calling it once with a stack buffer followed by * a memcpy() is almost certainly better than calling it twice */ #define USTR__SNPRINTF_LOCAL 128 /* Retarded versions of snprintf() return -1 (Ie. Solaris) instead of the * desired length so we have to loop calling vsnprintf() until we find a * value "big enough". * However ISO 9899:1999 says vsnprintf returns -1 for bad multi-byte strings, * so we don't want to loop forever. * So we try and work out USTR_CONF_HAVE_RETARDED_VSNPRINTF, but if it's on * when it doesn't need to be it'll be horribly slow on multi-byte errors. */ #define USTR__RETARDED_SNPRINTF_MIN (USTR__SNPRINTF_LOCAL * 2) #define USTR__RETARDED_SNPRINTF_MAX (1024 * 1024 * 256) #ifndef USTR_CONF_HAVE_RETARDED_VSNPRINTF /* safeish, but see above */ #define USTR_CONF_HAVE_RETARDED_VSNPRINTF 1 #endif #if USTR_CONF_HAVE_VA_COPY # if USTR_CONF_HAVE_RETARDED_VSNPRINTF USTR_CONF_e_PROTO int ustr__retard_vfmt_ret(const char *fmt, va_list ap) USTR__COMPILE_ATTR_NONNULL_A() USTR__COMPILE_ATTR_FMT(1, 0); # else # define ustr__retard_vfmt_ret(x, y) (-1) # endif USTR_CONF_e_PROTO int ustrp__add_vfmt_lim(struct Ustr_pool *p, struct Ustr **ps1, size_t lim, const char *fmt, va_list ap) USTR__COMPILE_ATTR_NONNULL_L((2, 4)) USTR__COMPILE_ATTR_FMT(4, 0); USTR_CONF_e_PROTO struct Ustr *ustrp__dupx_vfmt_lim(struct Ustr_pool *, size_t, size_t, int, int, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((7)) USTR__COMPILE_ATTR_FMT(7, 0); #endif #endif ustr-1.0.4/ustr-fmt-dbg-code.c0000644000076400007640000000130310674563614015101 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-fmt.h" ustr-1.0.4/ustr-ins-opt-code.c0000644000076400007640000000132310674563614015154 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-fmt.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-ins.h" ustr-1.0.4/README0000644000076400007640000000051410645264661012373 0ustar jamesjames Compile with: make make all-shared Compile and Run test suite with: make check Install all important files with: make install Cleanup: make clean Full cleanup, incl. .in -> real convertion etc: make distclean See README-DEVELOPERS for what to do after that, or look at the website at: http://www.and.org/ustr/ ustr-1.0.4/ustr-split-internal.h0000644000076400007640000000122310651531525015613 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_SPLIT_INTERNAL_H #define USTR_SPLIT_INTERNAL_H 1 #ifndef USTR_MAIN_H # error " You should have already included ustr-main.h, or just include ustr.h" #endif USTR_CONF_e_PROTO struct Ustr *ustrp__split_buf(struct Ustr_pool *, const struct Ustr *, size_t *, const void *, size_t, struct Ustr *,unsigned int); USTR_CONF_e_PROTO struct Ustr *ustrp__split_spn_chrs(struct Ustr_pool *, const struct Ustr *, size_t *, const char *, size_t, struct Ustr * , unsigned int); #endif ustr-1.0.4/ustr-ins.h0000644000076400007640000001003510650703274013441 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_INS_H #define USTR_INS_H 1 #ifndef USTR_MAIN_H # error " You should include ustr-main.h before this file, or just ustr.h" #endif #define USTR_INS_OBJ(x, y, z) ustr_ins_buf(x, y, z, sizeof(z)) #define USTR_INS_OSTR(x, y, z) ustr_ins_buf(x, y, z, sizeof(z) - 1) #define USTRP_INS_OBJ(p, x, y, z) ustrp_ins_buf(p, x, y, z, sizeof(z)) #define USTRP_INS_OSTR(p, x, y, z) ustrp_ins_buf(p, x, y, z, sizeof(z) - 1) USTR_CONF_E_PROTO int ustr_ins_undef(struct Ustr **, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_ins_buf(struct Ustr **, size_t, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_ins(struct Ustr **, size_t, const struct Ustr *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_ins_cstr(struct Ustr **, size_t, const char *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_ins_subustr(struct Ustr **, size_t, const struct Ustr *, size_t,size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_ins_rep_chr(struct Ustr **, size_t, char, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_ins_undef(struct Ustr_pool *, struct Ustrp **, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO int ustrp_ins_buf(struct Ustr_pool *, struct Ustrp **, size_t, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_E_PROTO int ustrp_ins(struct Ustr_pool *, struct Ustrp **, size_t, const struct Ustrp *) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_EI_PROTO int ustrp_ins_cstr(struct Ustr_pool *, struct Ustrp **, size_t, const char *) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_E_PROTO int ustrp_ins_subustrp(struct Ustr_pool *, struct Ustrp **, size_t, const struct Ustrp *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_E_PROTO int ustrp_ins_rep_chr(struct Ustr_pool *, struct Ustrp **, size_t, char, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); #ifdef USTR_FMT_H # if USTR_CONF_HAVE_VA_COPY USTR_CONF_E_PROTO int ustr_ins_vfmt_lim(struct Ustr **, size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((1, 4)) USTR__COMPILE_ATTR_FMT(4, 0); USTR_CONF_E_PROTO int ustr_ins_vfmt(struct Ustr **, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((1, 3)) USTR__COMPILE_ATTR_FMT(3, 0); USTR_CONF_E_PROTO int ustrp_ins_vfmt_lim(struct Ustr_pool *, struct Ustrp **, size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 5)) USTR__COMPILE_ATTR_FMT(5, 0); USTR_CONF_E_PROTO int ustrp_ins_vfmt(struct Ustr_pool *, struct Ustrp **,size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 4)) USTR__COMPILE_ATTR_FMT(4, 0); USTR_CONF_E_PROTO int ustr_ins_fmt_lim(struct Ustr **, size_t, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1, 4)) USTR__COMPILE_ATTR_FMT(4, 5); USTR_CONF_E_PROTO int ustr_ins_fmt(struct Ustr **, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1, 3)) USTR__COMPILE_ATTR_FMT(3, 4); USTR_CONF_E_PROTO int ustrp_ins_fmt_lim(struct Ustr_pool *, struct Ustrp **, size_t, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2, 5)) USTR__COMPILE_ATTR_FMT(5, 6); USTR_CONF_E_PROTO int ustrp_ins_fmt(struct Ustr_pool *, struct Ustrp **,size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2, 4)) USTR__COMPILE_ATTR_FMT(4, 5); # endif #endif #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-ins-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-ins-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO int ustr_ins_cstr(struct Ustr **s1, size_t p, const char *c) { return (ustr_ins_buf(s1, p, c, strlen(c))); } USTR_CONF_II_PROTO int ustrp_ins_cstr(struct Ustr_pool *x, struct Ustrp **s1, size_t p, const char *c) { return (ustrp_ins_buf(x, s1, p, c, strlen(c))); } #endif #endif ustr-1.0.4/ustr-spn.h0000644000076400007640000004632410642462147013464 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SPN_H #define USTR_SPN_H 1 #ifndef USTR_MAIN_H # error " You should include ustr-main.h before this file, or just ustr.h" #endif /* normal strspn() like, deals with embeded NILs */ USTR_CONF_E_PROTO size_t ustr_spn_chr_fwd(const struct Ustr *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_spn_chr_rev(const struct Ustr *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_spn_chrs_fwd(const struct Ustr *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_spn_chrs_rev(const struct Ustr *, size_t, const 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_spn_fwd(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_spn_rev(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_spn_cstr_fwd(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_spn_cstr_rev(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_cspn_chr_fwd(const struct Ustr *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_cspn_chr_rev(const struct Ustr *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_cspn_chrs_fwd(const struct Ustr *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_cspn_chrs_rev(const struct Ustr *, size_t, const 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_cspn_fwd(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_cspn_rev(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_cspn_cstr_fwd(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_cspn_cstr_rev(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #ifdef USTR_UTF8_H USTR_CONF_E_PROTO size_t ustr_utf8_spn_chrs_fwd(const struct Ustr *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_utf8_spn_chrs_rev(const struct Ustr *, size_t, const 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_utf8_spn_fwd(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_utf8_spn_rev(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_utf8_spn_cstr_fwd(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_utf8_spn_cstr_rev(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_utf8_cspn_chrs_fwd(const struct Ustr *,size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_utf8_cspn_chrs_rev(const struct Ustr *,size_t, const 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_utf8_cspn_fwd(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_utf8_cspn_rev(const struct Ustr *, size_t, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_utf8_cspn_cstr_fwd(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_utf8_cspn_cstr_rev(const struct Ustr *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-spn-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO size_t ustr_spn_cstr_fwd(const struct Ustr *s1, size_t off, const char *cstr) { return (ustr_spn_chrs_fwd(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustr_spn_cstr_rev(const struct Ustr *s1, size_t off, const char *cstr) { return (ustr_spn_chrs_rev(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustr_cspn_cstr_fwd(const struct Ustr *s1, size_t off, const char *cstr) { return (ustr_cspn_chrs_fwd(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustr_cspn_cstr_rev(const struct Ustr *s1, size_t off, const char *cstr) { return (ustr_cspn_chrs_rev(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustr_spn_fwd(const struct Ustr *s1, size_t off, const struct Ustr *s2) { return (ustr_spn_chrs_fwd(s1, off, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO size_t ustr_spn_rev(const struct Ustr *s1, size_t off, const struct Ustr *s2) { return (ustr_spn_chrs_rev(s1, off, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO size_t ustr_cspn_fwd(const struct Ustr *s1, size_t off, const struct Ustr *s2) { return (ustr_cspn_chrs_fwd(s1, off, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO size_t ustr_cspn_rev(const struct Ustr *s1, size_t off, const struct Ustr *s2) { return (ustr_cspn_chrs_rev(s1, off, ustr_cstr(s2), ustr_len(s2))); } # ifdef USTR_UTF8_H USTR_CONF_II_PROTO size_t ustr_utf8_spn_cstr_fwd(const struct Ustr *s1,size_t off,const char *cstr) { return (ustr_utf8_spn_chrs_fwd(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustr_utf8_spn_cstr_rev(const struct Ustr *s1,size_t off,const char *cstr) { return (ustr_utf8_spn_chrs_rev(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustr_utf8_cspn_cstr_fwd(const struct Ustr*s1,size_t off,const char *cstr) { return (ustr_utf8_cspn_chrs_fwd(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustr_utf8_cspn_cstr_rev(const struct Ustr*s1,size_t off,const char *cstr) { return (ustr_utf8_cspn_chrs_rev(s1, off, cstr, strlen(cstr))); } USTR_CONF_II_PROTO size_t ustr_utf8_spn_fwd(const struct Ustr *s1,size_t off,const struct Ustr *s2) { return (ustr_utf8_spn_chrs_fwd(s1, off, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO size_t ustr_utf8_spn_rev(const struct Ustr *s1,size_t off,const struct Ustr *s2) { return (ustr_utf8_spn_chrs_rev(s1, off, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO size_t ustr_utf8_cspn_fwd(const struct Ustr*s1,size_t off,const struct Ustr *s2) { return (ustr_utf8_cspn_chrs_fwd(s1, off, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO size_t ustr_utf8_cspn_rev(const struct Ustr*s1,size_t off,const struct Ustr *s2) { return (ustr_utf8_cspn_chrs_rev(s1, off, ustr_cstr(s2), ustr_len(s2))); } # endif #endif /* ---------------- pool wrapper APIs ---------------- */ /* normal strspn() like, deals with embeded NILs */ USTR_CONF_EI_PROTO size_t ustrp_spn_chr_fwd(const struct Ustrp *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_spn_chr_rev(const struct Ustrp *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_spn_chrs_fwd(const struct Ustrp *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_spn_chrs_rev(const struct Ustrp *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_spn_fwd(const struct Ustrp *, size_t, 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_spn_rev(const struct Ustrp *, size_t, 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_spn_cstr_fwd(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_spn_cstr_rev(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_cspn_chr_fwd(const struct Ustrp *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_cspn_chr_rev(const struct Ustrp *, size_t, char) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_cspn_chrs_fwd(const struct Ustrp *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_cspn_chrs_rev(const struct Ustrp *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_cspn_fwd(const struct Ustrp *, size_t, 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_cspn_rev(const struct Ustrp *, size_t, 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_cspn_cstr_fwd(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_cspn_cstr_rev(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #ifdef USTR_UTF8_H USTR_CONF_EI_PROTO size_t ustrp_utf8_spn_chrs_fwd(const struct Ustrp *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_utf8_spn_chrs_rev(const struct Ustrp *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_utf8_spn_fwd(const struct Ustrp *, size_t, 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_utf8_spn_rev(const struct Ustrp *, size_t, 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_utf8_spn_cstr_fwd(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_utf8_spn_cstr_rev(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_utf8_cspn_chrs_fwd(const struct Ustrp *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_utf8_cspn_chrs_rev(const struct Ustrp *, size_t, const char *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_utf8_cspn_fwd(const struct Ustrp *, size_t, 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_utf8_cspn_rev(const struct Ustrp *, size_t, 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_utf8_cspn_cstr_fwd(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustrp_utf8_cspn_cstr_rev(const struct Ustrp *, size_t, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO size_t ustrp_spn_chr_fwd(const struct Ustrp *s1, size_t off, char chr) { return (ustr_spn_chr_fwd(&s1->s, off, chr)); } USTR_CONF_II_PROTO size_t ustrp_spn_chr_rev(const struct Ustrp *s1, size_t off, char chr) { return (ustr_spn_chr_rev(&s1->s, off, chr)); } USTR_CONF_II_PROTO size_t ustrp_spn_chrs_fwd(const struct Ustrp *s1, size_t off, const char *chrs, size_t len) { return (ustr_spn_chrs_fwd(&s1->s, off, chrs, len)); } USTR_CONF_II_PROTO size_t ustrp_spn_chrs_rev(const struct Ustrp *s1, size_t off, const char *chrs, size_t len) { return (ustr_spn_chrs_rev(&s1->s, off, chrs, len)); } USTR_CONF_II_PROTO size_t ustrp_spn_fwd(const struct Ustrp *s1, size_t off, const struct Ustrp *s2) { return (ustr_spn_fwd(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_spn_rev(const struct Ustrp *s1, size_t off, const struct Ustrp *s2) { return (ustr_spn_rev(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_spn_cstr_fwd(const struct Ustrp *s1, size_t off, const char *chrs) { return (ustrp_spn_chrs_fwd(s1, off, chrs, strlen(chrs))); } USTR_CONF_II_PROTO size_t ustrp_spn_cstr_rev(const struct Ustrp *s1, size_t off, const char *chrs) { return (ustrp_spn_chrs_rev(s1, off, chrs, strlen(chrs))); } USTR_CONF_II_PROTO size_t ustrp_cspn_chr_fwd(const struct Ustrp *s1, size_t off, char chr) { return (ustr_cspn_chr_fwd(&s1->s, off, chr)); } USTR_CONF_II_PROTO size_t ustrp_cspn_chr_rev(const struct Ustrp *s1, size_t off, char chr) { return (ustr_cspn_chr_rev(&s1->s, off, chr)); } USTR_CONF_II_PROTO size_t ustrp_cspn_chrs_fwd(const struct Ustrp *s1,size_t off, const char *chrs, size_t len) { return (ustr_cspn_chrs_fwd(&s1->s, off, chrs, len)); } USTR_CONF_II_PROTO size_t ustrp_cspn_chrs_rev(const struct Ustrp *s1,size_t off, const char *chrs, size_t len) { return (ustr_cspn_chrs_rev(&s1->s, off, chrs, len)); } USTR_CONF_II_PROTO size_t ustrp_cspn_fwd(const struct Ustrp *s1,size_t off, const struct Ustrp *s2) { return (ustr_cspn_fwd(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_cspn_rev(const struct Ustrp *s1,size_t off, const struct Ustrp *s2) { return (ustr_cspn_rev(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_cspn_cstr_fwd(const struct Ustrp *s1, size_t off, const char *chrs) { return (ustrp_cspn_chrs_fwd(s1, off, chrs, strlen(chrs))); } USTR_CONF_II_PROTO size_t ustrp_cspn_cstr_rev(const struct Ustrp *s1, size_t off, const char *chrs) { return (ustrp_cspn_chrs_rev(s1, off, chrs, strlen(chrs))); } # ifdef USTR_UTF8_H USTR_CONF_II_PROTO size_t ustrp_utf8_spn_chrs_fwd(const struct Ustrp *s1, size_t off, const char *chrs, size_t len) { return (ustr_utf8_spn_chrs_fwd(&s1->s, off, chrs, len)); } USTR_CONF_II_PROTO size_t ustrp_utf8_spn_chrs_rev(const struct Ustrp *s1, size_t off, const char *chrs, size_t len) { return (ustr_utf8_spn_chrs_rev(&s1->s, off, chrs, len)); } USTR_CONF_II_PROTO size_t ustrp_utf8_spn_fwd(const struct Ustrp *s1, size_t off, const struct Ustrp *s2) { return (ustr_utf8_spn_fwd(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_utf8_spn_rev(const struct Ustrp *s1, size_t off, const struct Ustrp *s2) { return (ustr_utf8_spn_rev(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_utf8_spn_cstr_fwd(const struct Ustrp *s1, size_t off, const char *chrs) { return (ustrp_utf8_spn_chrs_fwd(s1, off, chrs, strlen(chrs))); } USTR_CONF_II_PROTO size_t ustrp_utf8_spn_cstr_rev(const struct Ustrp *s1, size_t off, const char *chrs) { return (ustrp_utf8_spn_chrs_rev(s1, off, chrs, strlen(chrs))); } USTR_CONF_II_PROTO size_t ustrp_utf8_cspn_chrs_fwd(const struct Ustrp *s1, size_t off, const char *chrs, size_t len) { return (ustr_utf8_cspn_chrs_fwd(&s1->s, off, chrs, len)); } USTR_CONF_II_PROTO size_t ustrp_utf8_cspn_chrs_rev(const struct Ustrp *s1, size_t off, const char *chrs, size_t len) { return (ustr_utf8_cspn_chrs_rev(&s1->s, off, chrs, len)); } USTR_CONF_II_PROTO size_t ustrp_utf8_cspn_fwd(const struct Ustrp *s1,size_t off, const struct Ustrp *s2) { return (ustr_utf8_cspn_fwd(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_utf8_cspn_rev(const struct Ustrp *s1,size_t off, const struct Ustrp *s2) { return (ustr_utf8_cspn_rev(&s1->s, off, &s2->s)); } USTR_CONF_II_PROTO size_t ustrp_utf8_cspn_cstr_fwd(const struct Ustrp *s1, size_t off, const char *chrs) { return (ustrp_utf8_cspn_chrs_fwd(s1, off, chrs, strlen(chrs))); } USTR_CONF_II_PROTO size_t ustrp_utf8_cspn_cstr_rev(const struct Ustrp *s1, size_t off, const char *chrs) { return (ustrp_utf8_cspn_chrs_rev(s1, off, chrs, strlen(chrs))); } # endif #endif #endif ustr-1.0.4/libustr.ver0000644000076400007640000002614410763652074013724 0ustar jamesjames USTR_1.0 { global: ustr_xi__pow2; ustr_xi__embed_val_get; ustr_xi__ref_get; ustr_pool_clear; ustr_pool_free; ustr_pool_make_subpool; ustr_pool_make_pool; ustr_assert_valid; ustr_assert_valid_subustr; ustrp_assert_valid; ustrp_assert_valid_subustrp; ustr_cstr; ustr_len; ustr_wstr; ustrp_cstr; ustrp_len; ustrp_wstr; ustr_alloc; ustr_enomem; ustr_exact; ustr_fixed; ustr_limited; ustr_owner; ustr_ro; ustr_shared; ustr_size; ustr_size_alloc; ustr_size_overhead; ustr_sized; ustrp_alloc; ustrp_enomem; ustrp_exact; ustrp_fixed; ustrp_limited; ustrp_owner; ustrp_ro; ustrp_shared; ustrp_size; ustrp_size_alloc; ustrp_size_overhead; ustrp_sized; ustr_setf_enomem_err; ustr_setf_enomem_clr; ustr_setf_share; ustr_setf_owner; ustrp_setf_enomem_err; ustrp_setf_enomem_clr; ustrp_setf_share; ustrp_setf_owner; ustr_free; ustrp_free; ustr_init_size; ustr_init_alloc; ustr_init_fixed; ustrp_init_alloc; ustrp_init_fixed; ustr_realloc; ustrp_realloc; ustr_add; ustr_add_buf; ustr_add_cstr; ustr_add_rep_chr; ustr_add_subustr; ustr_add_undef; ustrp_add; ustrp_add_buf; ustrp_add_cstr; ustrp_add_rep_chr; ustrp_add_subustrp; ustrp_add_undef; ustr_dup; ustr_dup_buf; ustr_dup_cstr; ustr_dup_empty; ustr_dup_rep_chr; ustr_dup_subustr; ustr_dup_undef; ustrp_dup; ustrp_dup_buf; ustrp_dup_cstr; ustrp_dup_empty; ustrp_dup_rep_chr; ustrp_dup_subustrp; ustrp_dup_undef; ustr_dupx; ustr_dupx_buf; ustr_dupx_cstr; ustr_dupx_empty; ustr_dupx_rep_chr; ustr_dupx_subustr; ustr_dupx_undef; ustrp_dupx; ustrp_dupx_buf; ustrp_dupx_cstr; ustrp_dupx_empty; ustrp_dupx_rep_chr; ustrp_dupx_subustrp; ustrp_dupx_undef; ustr_set; ustr_set_buf; ustr_set_cstr; ustr_set_empty; ustr_set_rep_chr; ustr_set_subustr; ustr_set_undef; ustrp_set; ustrp_set_buf; ustrp_set_cstr; ustrp_set_empty; ustrp_set_rep_chr; ustrp_set_subustrp; ustrp_set_undef; ustr_del; ustr_del_subustr; ustrp_del; ustrp_del_subustrp; ustr_sc_del; ustr_sc_dupx; ustr_sc_dup; ustr_sc_ensure_owner; ustr_sc_free; ustr_sc_free2; ustr_sc_free_shared; ustr_sc_reverse; ustr_sc_tolower; ustr_sc_toupper; ustr_sc_utf8_reverse; ustr_sc_wstr; ustrp_sc_del; ustrp_sc_dupx; ustrp_sc_dup; ustrp_sc_ensure_owner; ustrp_sc_free; ustrp_sc_free2; ustrp_sc_free_shared; ustrp_sc_reverse; ustrp_sc_tolower; ustrp_sc_toupper; ustrp_sc_utf8_reverse; ustrp_sc_wstr; ustr_add_fmt; ustr_add_fmt_lim; ustr_add_vfmt; ustr_add_vfmt_lim; ustr_dup_fmt; ustr_dup_fmt_lim; ustr_dup_vfmt; ustr_dup_vfmt_lim; ustr_dupx_fmt; ustr_dupx_fmt_lim; ustr_dupx_vfmt; ustr_dupx_vfmt_lim; ustr_set_fmt; ustr_set_fmt_lim; ustr_set_vfmt; ustr_set_vfmt_lim; ustrp_add_fmt; ustrp_add_fmt_lim; ustrp_add_vfmt; ustrp_add_vfmt_lim; ustrp_dup_fmt; ustrp_dup_fmt_lim; ustrp_dup_vfmt; ustrp_dup_vfmt_lim; ustrp_dupx_fmt; ustrp_dupx_fmt_lim; ustrp_dupx_vfmt; ustrp_dupx_vfmt_lim; ustrp_set_fmt; ustrp_set_fmt_lim; ustrp_set_vfmt; ustrp_set_vfmt_lim; ustr_cmp; ustr_cmp_buf; ustr_cmp_buf_eq; ustr_cmp_case; ustr_cmp_case_buf; ustr_cmp_case_buf_eq; ustr_cmp_case_cstr; ustr_cmp_case_cstr_eq; ustr_cmp_case_eq; ustr_cmp_case_prefix_buf_eq; ustr_cmp_case_prefix_cstr_eq; ustr_cmp_case_prefix_eq; ustr_cmp_case_subustr; ustr_cmp_case_subustr_eq; ustr_cmp_case_suffix_buf_eq; ustr_cmp_case_suffix_cstr_eq; ustr_cmp_case_suffix_eq; ustr_cmp_cstr; ustr_cmp_cstr_eq; ustr_cmp_eq; ustr_cmp_fast; ustr_cmp_fast_buf; ustr_cmp_fast_cstr; ustr_cmp_fast_subustr; ustr_cmp_prefix_buf_eq; ustr_cmp_prefix_cstr_eq; ustr_cmp_prefix_eq; ustr_cmp_subustr; ustr_cmp_subustr_eq; ustr_cmp_suffix_buf_eq; ustr_cmp_suffix_cstr_eq; ustr_cmp_suffix_eq; ustrp_cmp; ustrp_cmp_buf; ustrp_cmp_buf_eq; ustrp_cmp_case; ustrp_cmp_case_buf; ustrp_cmp_case_buf_eq; ustrp_cmp_case_cstr; ustrp_cmp_case_cstr_eq; ustrp_cmp_case_eq; ustrp_cmp_case_prefix_buf_eq; ustrp_cmp_case_prefix_cstr_eq; ustrp_cmp_case_prefix_eq; ustrp_cmp_case_subustrp; ustrp_cmp_case_subustrp_eq; ustrp_cmp_case_suffix_buf_eq; ustrp_cmp_case_suffix_cstr_eq; ustrp_cmp_case_suffix_eq; ustrp_cmp_cstr; ustrp_cmp_cstr_eq; ustrp_cmp_eq; ustrp_cmp_fast; ustrp_cmp_fast_buf; ustrp_cmp_fast_cstr; ustrp_cmp_fast_subustrp; ustrp_cmp_prefix_buf_eq; ustrp_cmp_prefix_cstr_eq; ustrp_cmp_prefix_eq; ustrp_cmp_subustrp; ustrp_cmp_subustrp_eq; ustrp_cmp_suffix_buf_eq; ustrp_cmp_suffix_cstr_eq; ustrp_cmp_suffix_eq; ustr_srch_buf_fwd; ustr_srch_buf_rev; ustr_srch_chr_fwd; ustr_srch_chr_rev; ustr_srch_cstr_fwd; ustr_srch_cstr_rev; ustr_srch_fwd; ustr_srch_rev; ustr_srch_subustr_fwd; ustr_srch_subustr_rev; ustrp_srch_buf_fwd; ustrp_srch_buf_rev; ustrp_srch_chr_fwd; ustrp_srch_chr_rev; ustrp_srch_cstr_fwd; ustrp_srch_cstr_rev; ustrp_srch_fwd; ustrp_srch_rev; ustrp_srch_subustrp_fwd; ustrp_srch_subustrp_rev; ustr_spn_chr_fwd; ustr_spn_chr_rev; ustr_spn_chrs_fwd; ustr_spn_chrs_rev; ustr_spn_cstr_fwd; ustr_spn_cstr_rev; ustr_spn_fwd; ustr_spn_rev; ustrp_spn_chr_fwd; ustrp_spn_chr_rev; ustrp_spn_chrs_fwd; ustrp_spn_chrs_rev; ustrp_spn_cstr_fwd; ustrp_spn_cstr_rev; ustrp_spn_fwd; ustrp_spn_rev; ustr_cspn_chr_fwd; ustr_cspn_chr_rev; ustr_cspn_chrs_fwd; ustr_cspn_chrs_rev; ustr_cspn_cstr_fwd; ustr_cspn_cstr_rev; ustr_cspn_fwd; ustr_cspn_rev; ustrp_cspn_chr_fwd; ustrp_cspn_chr_rev; ustrp_cspn_chrs_fwd; ustrp_cspn_chrs_rev; ustrp_cspn_cstr_fwd; ustrp_cspn_cstr_rev; ustrp_cspn_fwd; ustrp_cspn_rev; ustr_add_b_uint16; ustr_add_b_uint32; ustr_add_b_uint64; ustrp_add_b_uint16; ustrp_add_b_uint32; ustrp_add_b_uint64; ustr_parse_b_uint16; ustr_parse_b_uint32; ustr_parse_b_uint64; ustrp_parse_b_uint16; ustrp_parse_b_uint32; ustrp_parse_b_uint64; ustr_io_get; ustr_io_getdelim; ustr_io_getfile; ustr_io_getfilename; ustr_io_getline; ustr_io_put; ustr_io_putfile; ustr_io_putfileline; ustr_io_putfilename; ustr_io_putline; ustrp_io_get; ustrp_io_getdelim; ustrp_io_getfile; ustrp_io_getfilename; ustrp_io_getline; ustrp_io_put; ustrp_io_putfile; ustrp_io_putfileline; ustrp_io_putfilename; ustrp_io_putline; ustr_utf8_bytes2chars; ustr_utf8_chars2bytes; ustr_utf8_len; ustr_utf8_valid; ustr_utf8_width; ustrp_utf8_bytes2chars; ustrp_utf8_chars2bytes; ustrp_utf8_len; ustrp_utf8_valid; ustrp_utf8_width; ustr_utf8_spn_chrs_fwd; ustr_utf8_spn_chrs_rev; ustr_utf8_spn_cstr_fwd; ustr_utf8_spn_cstr_rev; ustr_utf8_spn_fwd; ustr_utf8_spn_rev; ustrp_utf8_spn_chrs_fwd; ustrp_utf8_spn_chrs_rev; ustrp_utf8_spn_cstr_fwd; ustrp_utf8_spn_cstr_rev; ustrp_utf8_spn_fwd; ustrp_utf8_spn_rev; ustr_utf8_cspn_chrs_fwd; ustr_utf8_cspn_chrs_rev; ustr_utf8_cspn_cstr_fwd; ustr_utf8_cspn_cstr_rev; ustr_utf8_cspn_fwd; ustr_utf8_cspn_rev; ustrp_utf8_cspn_chrs_fwd; ustrp_utf8_cspn_chrs_rev; ustrp_utf8_cspn_cstr_fwd; ustrp_utf8_cspn_cstr_rev; ustrp_utf8_cspn_fwd; ustrp_utf8_cspn_rev; ustr_parse_int; ustr_parse_intmax; ustr_parse_long; ustr_parse_short; ustr_parse_uint; ustr_parse_uintmax; ustr_parse_uintmaxx; ustr_parse_ulong; ustr_parse_ulongx; ustr_parse_ushort; ustrp_parse_int; ustrp_parse_intmax; ustrp_parse_long; ustrp_parse_short; ustrp_parse_uint; ustrp_parse_uintmax; ustrp_parse_uintmaxx; ustrp_parse_ulong; ustrp_parse_ulongx; ustrp_parse_ushort; ustr_sub; ustr_sub_buf; ustr_sub_cstr; ustr_sub_fmt; ustr_sub_fmt_lim; ustr_sub_rep_chr; ustr_sub_subustr; ustr_sub_undef; ustr_sub_vfmt; ustr_sub_vfmt_lim; ustrp_sub; ustrp_sub_buf; ustrp_sub_cstr; ustrp_sub_fmt; ustrp_sub_fmt_lim; ustrp_sub_rep_chr; ustrp_sub_subustrp; ustrp_sub_undef; ustrp_sub_vfmt; ustrp_sub_vfmt_lim; ustr_replace; ustr_replace_buf; ustr_replace_cstr; ustrp_replace; ustrp_replace_buf; ustrp_replace_cstr; ustr_sc_sub; ustr_sc_sub_buf; ustr_sc_sub_cstr; ustr_sc_sub_fmt; ustr_sc_sub_fmt_lim; ustr_sc_sub_rep_chr; ustr_sc_sub_subustr; ustr_sc_sub_undef; ustr_sc_sub_vfmt; ustr_sc_sub_vfmt_lim; ustrp_sc_sub; ustrp_sc_sub_buf; ustrp_sc_sub_cstr; ustrp_sc_sub_fmt; ustrp_sc_sub_fmt_lim; ustrp_sc_sub_rep_chr; ustrp_sc_sub_subustrp; ustrp_sc_sub_undef; ustrp_sc_sub_vfmt; ustrp_sc_sub_vfmt_lim; ustr_split; ustr_split_buf; ustr_split_cstr; ustrp_split; ustrp_split_buf; ustrp_split_cstr; local: ustr__*; ustrp__*; }; USTR_1.0.1 { global: ustr_cntl_opt; ustr_srch_rep_chr_fwd; ustr_srch_rep_chr_rev; ustrp_srch_rep_chr_fwd; ustrp_srch_rep_chr_rev; ustr_ins; ustr_ins_buf; ustr_ins_cstr; ustr_ins_fmt; ustr_ins_fmt_lim; ustr_ins_rep_chr; ustr_ins_subustr; ustr_ins_undef; ustr_ins_vfmt; ustr_ins_vfmt_lim; ustrp_ins; ustrp_ins_buf; ustrp_ins_cstr; ustrp_ins_fmt; ustrp_ins_fmt_lim; ustrp_ins_rep_chr; ustrp_ins_subustrp; ustrp_ins_undef; ustrp_ins_vfmt; ustrp_ins_vfmt_lim; ustr_replace_rep_chr; ustrp_replace_rep_chr; ustr_split_spn; ustr_split_spn_chrs; ustr_split_spn_cstr; ustrp_split_spn; ustrp_split_spn_chrs; ustrp_split_spn_cstr; }; USTR_1.0.2 { global: ustr_pool_ll_make; ustr_pool_ll_cntl; ustr_conf; ustrp_conf; ustr_cmp_case_prefix_subustr_eq; ustr_cmp_case_suffix_subustr_eq; ustr_cmp_prefix_subustr_eq; ustr_cmp_suffix_subustr_eq; ustrp_cmp_case_prefix_subustrp_eq; ustrp_cmp_case_suffix_subustrp_eq; ustrp_cmp_prefix_subustrp_eq; ustrp_cmp_suffix_subustrp_eq; ustr_srch_case_buf_fwd; ustr_srch_case_buf_rev; ustr_srch_case_chr_fwd; ustr_srch_case_chr_rev; ustr_srch_case_cstr_fwd; ustr_srch_case_cstr_rev; ustr_srch_case_fwd; ustr_srch_case_rep_chr_fwd; ustr_srch_case_rep_chr_rev; ustr_srch_case_rev; ustr_srch_case_subustr_fwd; ustr_srch_case_subustr_rev; ustrp_srch_case_buf_fwd; ustrp_srch_case_buf_rev; ustrp_srch_case_chr_fwd; ustrp_srch_case_chr_rev; ustrp_srch_case_cstr_fwd; ustrp_srch_case_cstr_rev; ustrp_srch_case_fwd; ustrp_srch_case_rep_chr_fwd; ustrp_srch_case_rep_chr_rev; ustrp_srch_case_rev; ustrp_srch_case_subustrp_fwd; ustrp_srch_case_subustrp_rev; ustr_sc_export; ustr_sc_export_subustr; ustrp_sc_export; ustrp_sc_export_subustrp; }; USTR_1.0.3 { global: ustr_sc_rtrim; ustr_sc_rtrim_chrs; ustr_sc_rtrim_cstr; ustr_sc_ltrim; ustr_sc_ltrim_chrs; ustr_sc_ltrim_cstr; ustr_sc_trim; ustr_sc_trim_chrs; ustr_sc_trim_cstr; ustrp_sc_rtrim; ustrp_sc_rtrim_chrs; ustrp_sc_rtrim_cstr; ustrp_sc_ltrim; ustrp_sc_ltrim_chrs; ustrp_sc_ltrim_cstr; ustrp_sc_trim; ustrp_sc_trim_chrs; ustrp_sc_trim_cstr; }; USTR_1.0.4 { global: ustr_sc_join; ustr_sc_vjoin; ustr_sc_joinx; ustr_sc_vjoinx; ustr_sc_concat; ustr_sc_vconcat; ustr_sc_concatx; ustr_sc_vconcatx; ustrp_sc_join; ustrp_sc_vjoin; ustrp_sc_joinx; ustrp_sc_vjoinx; ustrp_sc_concat; ustrp_sc_vconcat; ustrp_sc_concatx; ustrp_sc_vconcatx; }; ustr-1.0.4/ustr-srch-opt-code.c0000644000076400007640000000133610674563614015326 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-cmp-internal.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-srch.h" ustr-1.0.4/ustr-sub.h0000644000076400007640000002021210707235051013433 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_SUB_H #define USTR_SUB_H 1 #ifndef USTR_MAIN_H # error " You should include ustr-main.h before this file, or just ustr.h" #endif #define USTR_SUB_OBJ(x, y, z) ustr_sub_buf(x, y, z, sizeof(z)) #define USTR_SUB_OSTR(x, y, z) ustr_sub_buf(x, y, z, sizeof(z) - 1) #define USTRP_SUB_OBJ(p, x, y, z) ustrp_sub_buf(p, x, y, z, sizeof(z)) #define USTRP_SUB_OSTR(p, x, y, z) ustrp_sub_buf(p, x, y, z, sizeof(z) - 1) #define USTR_SC_SUB_OBJ(w, x, y, z) ustr_sc_sub_buf(w, x, y, z, sizeof(z)) #define USTR_SC_SUB_OSTR(w, x, y, z) ustr_sc_sub_buf(w, x, y, z, sizeof(z) - 1) #define USTRP_SC_SUB_OBJ(p, w, x, y, z) \ ustrp_sc_sub_buf(p, w, x, y, z, sizeof(z)) #define USTRP_SC_SUB_OSTR(p, w, x, y, z) \ ustrp_sc_sub_buf(p, w, x, y, z, sizeof(z) - 1) USTR_CONF_E_PROTO int ustr_sub_undef(struct Ustr **ps1, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sub_buf(struct Ustr **, size_t, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sub(struct Ustr **, size_t, const struct Ustr *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_sub_cstr(struct Ustr **, size_t, const char *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sub_subustr(struct Ustr **, size_t, const struct Ustr *, size_t,size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sub_rep_chr(struct Ustr **, size_t, char, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_sub_undef(struct Ustr_pool *, struct Ustrp **, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO int ustrp_sub_buf(struct Ustr_pool *,struct Ustrp **,size_t,const void *,size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_E_PROTO int ustrp_sub(struct Ustr_pool *, struct Ustrp **, size_t, const struct Ustrp *) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_EI_PROTO int ustrp_sub_cstr(struct Ustr_pool *, struct Ustrp **, size_t, const char *) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_E_PROTO int ustrp_sub_subustrp(struct Ustr_pool *, struct Ustrp **, size_t, const struct Ustrp *, size_t,size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 4)); USTR_CONF_E_PROTO int ustrp_sub_rep_chr(struct Ustr_pool *, struct Ustrp **, size_t, char, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO int ustr_sc_sub_undef(struct Ustr **, size_t, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sc_sub_buf(struct Ustr **, size_t, size_t, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sc_sub(struct Ustr **, size_t, size_t, const struct Ustr *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_sc_sub_cstr(struct Ustr **, size_t, size_t, const char *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sc_sub_subustr(struct Ustr **, size_t, size_t, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sc_sub_rep_chr(struct Ustr **, size_t, size_t, char, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_sc_sub_undef(struct Ustr_pool *, struct Ustrp **,size_t,size_t,size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO int ustrp_sc_sub_buf(struct Ustr_pool *, struct Ustrp **, size_t, size_t, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 5)); USTR_CONF_E_PROTO int ustrp_sc_sub(struct Ustr_pool *, struct Ustrp **, size_t, size_t, const struct Ustrp *) USTR__COMPILE_ATTR_NONNULL_L((2, 5)); USTR_CONF_EI_PROTO int ustrp_sc_sub_cstr(struct Ustr_pool *, struct Ustrp **, size_t, size_t, const char *) USTR__COMPILE_ATTR_NONNULL_L((2, 5)); USTR_CONF_E_PROTO int ustrp_sc_sub_subustrp(struct Ustr_pool *, struct Ustrp **, size_t, size_t, const struct Ustrp *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 5)); USTR_CONF_E_PROTO int ustrp_sc_sub_rep_chr(struct Ustr_pool *, struct Ustrp **, size_t, size_t, char, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); #ifdef USTR_FMT_H # if USTR_CONF_HAVE_VA_COPY /* sub_fmt */ USTR_CONF_E_PROTO int ustr_sub_vfmt_lim(struct Ustr **, size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((1, 4)) USTR__COMPILE_ATTR_FMT(4, 0); USTR_CONF_E_PROTO int ustr_sub_vfmt(struct Ustr **, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((1, 3)) USTR__COMPILE_ATTR_FMT(3, 0); USTR_CONF_E_PROTO int ustrp_sub_vfmt_lim(struct Ustr_pool *, struct Ustrp **, size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 5)) USTR__COMPILE_ATTR_FMT(5, 0); USTR_CONF_E_PROTO int ustrp_sub_vfmt(struct Ustr_pool *, struct Ustrp **,size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 4)) USTR__COMPILE_ATTR_FMT(4, 0); USTR_CONF_E_PROTO int ustr_sub_fmt_lim(struct Ustr **, size_t, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1, 4)) USTR__COMPILE_ATTR_FMT(4, 5); USTR_CONF_E_PROTO int ustr_sub_fmt(struct Ustr **, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1, 3)) USTR__COMPILE_ATTR_FMT(3, 4); USTR_CONF_E_PROTO int ustrp_sub_fmt_lim(struct Ustr_pool *, struct Ustrp **, size_t, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2, 5)) USTR__COMPILE_ATTR_FMT(5, 6); USTR_CONF_E_PROTO int ustrp_sub_fmt(struct Ustr_pool *, struct Ustrp **,size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2, 4)) USTR__COMPILE_ATTR_FMT(4, 5); /* sc_sub_fmt */ USTR_CONF_E_PROTO int ustr_sc_sub_vfmt_lim(struct Ustr **, size_t, size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((1, 5)) USTR__COMPILE_ATTR_FMT(5, 0); USTR_CONF_E_PROTO int ustr_sc_sub_vfmt(struct Ustr **, size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((1, 4)) USTR__COMPILE_ATTR_FMT(4, 0); USTR_CONF_E_PROTO int ustrp_sc_sub_vfmt_lim(struct Ustr_pool *, struct Ustrp **, size_t, size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 6)) USTR__COMPILE_ATTR_FMT(6, 0); USTR_CONF_E_PROTO int ustrp_sc_sub_vfmt(struct Ustr_pool *, struct Ustrp **,size_t, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 5)) USTR__COMPILE_ATTR_FMT(5, 0); USTR_CONF_E_PROTO int ustr_sc_sub_fmt_lim(struct Ustr **, size_t, size_t, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1, 5)) USTR__COMPILE_ATTR_FMT(5, 6); USTR_CONF_E_PROTO int ustr_sc_sub_fmt(struct Ustr **, size_t, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1, 4)) USTR__COMPILE_ATTR_FMT(4, 5); USTR_CONF_E_PROTO int ustrp_sc_sub_fmt_lim(struct Ustr_pool *, struct Ustrp **, size_t, size_t, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2, 6)) USTR__COMPILE_ATTR_FMT(6, 7); USTR_CONF_E_PROTO int ustrp_sc_sub_fmt(struct Ustr_pool *, struct Ustrp **, size_t, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2, 5)) USTR__COMPILE_ATTR_FMT(5, 6); # endif #endif #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-sub-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-sub-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO int ustr_sub_cstr(struct Ustr **s1, size_t p, const char *c) { return (ustr_sub_buf(s1, p, c, strlen(c))); } USTR_CONF_II_PROTO int ustr_sc_sub_cstr(struct Ustr **s1, size_t pos, size_t len,const char *cstr) { return (ustr_sc_sub_buf(s1, pos, len, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustrp_sub_cstr(struct Ustr_pool *x, struct Ustrp **s1, size_t p, const char *c) { return (ustrp_sub_buf(x, s1, p, c, strlen(c))); } USTR_CONF_II_PROTO int ustrp_sc_sub_cstr(struct Ustr_pool *p, struct Ustrp **s1, size_t pos, size_t len, const char *cstr) { return (ustrp_sc_sub_buf(p, s1, pos, len, cstr, strlen(cstr))); } #endif #endif ustr-1.0.4/autoconf_64b.c0000644000076400007640000000027410630111754014137 0ustar jamesjames#include #include int main(void) { /* output a "1" is it's a 64 bit platform. Major hack. */ size_t val = -1; puts((val == 0xFFFFFFFF) ? "0" : "1"); return 0; } ustr-1.0.4/ustr-io-opt-code.c0000644000076400007640000000127410722116246014764 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-io.h" ustr-1.0.4/ustr-fmt.h0000644000076400007640000001173410755371037013451 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_FMT_H #define USTR_FMT_H 1 #ifndef USTR_MAIN_H # error " You should include ustr-main.h before this file, or just ustr.h" #endif #if USTR_CONF_HAVE_VA_COPY USTR_CONF_E_PROTO int ustr_add_vfmt_lim(struct Ustr **, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((1, 3)) USTR__COMPILE_ATTR_FMT(3, 0); USTR_CONF_E_PROTO int ustr_add_vfmt(struct Ustr **, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((1, 2)) USTR__COMPILE_ATTR_FMT(2, 0); USTR_CONF_E_PROTO struct Ustr *ustr_dupx_vfmt_lim(size_t, size_t, int, int, size_t, const char *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)) USTR__COMPILE_ATTR_FMT(6, 0); USTR_CONF_E_PROTO struct Ustr *ustr_dup_vfmt_lim(size_t, const char *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)) USTR__COMPILE_ATTR_FMT(2, 0); USTR_CONF_E_PROTO struct Ustr *ustr_dupx_vfmt(size_t, size_t, int, int, const char *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((5)) USTR__COMPILE_ATTR_FMT(5, 0); USTR_CONF_E_PROTO struct Ustr *ustr_dup_vfmt(const char *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)) USTR__COMPILE_ATTR_FMT(1, 0); USTR_CONF_E_PROTO int ustrp_add_vfmt_lim(struct Ustr_pool *, struct Ustrp **, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 4)) USTR__COMPILE_ATTR_FMT(4, 0); USTR_CONF_E_PROTO int ustrp_add_vfmt(struct Ustr_pool *, struct Ustrp **, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 3)) USTR__COMPILE_ATTR_FMT(3, 0); USTR_CONF_E_PROTO struct Ustrp *ustrp_dupx_vfmt_lim(struct Ustr_pool *, size_t, size_t, int, int, size_t, const char *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((7)) USTR__COMPILE_ATTR_FMT(7, 0); USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_vfmt_lim(struct Ustr_pool *, size_t, const char *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((3)) USTR__COMPILE_ATTR_FMT(3, 0); USTR_CONF_E_PROTO struct Ustrp *ustrp_dupx_vfmt(struct Ustr_pool *, size_t, size_t, int, int, const char *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)) USTR__COMPILE_ATTR_FMT(6, 0); USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_vfmt(struct Ustr_pool *, const char *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)) USTR__COMPILE_ATTR_FMT(2, 0); /* even without va_copy, we can still do *_fmt using lots of copy and paste */ USTR_CONF_E_PROTO int ustr_add_fmt(struct Ustr **, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1, 2)) USTR__COMPILE_ATTR_FMT(2, 3); USTR_CONF_E_PROTO int ustr_add_fmt_lim(struct Ustr **, size_t,const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1, 3)) USTR__COMPILE_ATTR_FMT(3, 4); USTR_CONF_E_PROTO struct Ustr *ustr_dupx_fmt_lim(size_t, size_t, int, int, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((6)) USTR__COMPILE_ATTR_FMT(6, 7); USTR_CONF_E_PROTO struct Ustr *ustr_dup_fmt_lim(size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2)) USTR__COMPILE_ATTR_FMT(2, 3); USTR_CONF_E_PROTO struct Ustr *ustr_dupx_fmt(size_t, size_t, int, int, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((5)) USTR__COMPILE_ATTR_FMT(5, 6); USTR_CONF_E_PROTO struct Ustr *ustr_dup_fmt(const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((1)) USTR__COMPILE_ATTR_FMT(1, 2); USTR_CONF_E_PROTO int ustrp_add_fmt(struct Ustr_pool *, struct Ustrp **, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2, 3)) USTR__COMPILE_ATTR_FMT(3, 4); USTR_CONF_E_PROTO int ustrp_add_fmt_lim(struct Ustr_pool *, struct Ustrp **, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2, 4)) USTR__COMPILE_ATTR_FMT(4, 5); USTR_CONF_E_PROTO struct Ustrp *ustrp_dupx_fmt_lim(struct Ustr_pool *, size_t, size_t, int, int, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((7)) USTR__COMPILE_ATTR_FMT(7, 8); USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_fmt_lim(struct Ustr_pool *, size_t, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((3)) USTR__COMPILE_ATTR_FMT(3, 4); USTR_CONF_E_PROTO struct Ustrp *ustrp_dupx_fmt(struct Ustr_pool *, size_t, size_t, int, int, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((6)) USTR__COMPILE_ATTR_FMT(6, 7); USTR_CONF_E_PROTO struct Ustrp *ustrp_dup_fmt(struct Ustr_pool *, const char *, ...) USTR__COMPILE_ATTR_NONNULL_L((2)) USTR__COMPILE_ATTR_FMT(2, 3); #endif #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-fmt-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-fmt-code.h" #endif #endif ustr-1.0.4/THANKS0000644000076400007640000000042310763523572012425 0ustar jamesjames Karl MacMillan - For bouncing ideas off of early on, and finally pushing me into wasting my time writing ustr ;). Rik Faith - For help making sure it worked on "legacy OSes". Václav Ovsík - Debian packaging and cleanups/bug fixes. ustr-1.0.4/LICENSE0000644000076400007640000000053410654700004012504 0ustar jamesjames This code is multi Licensed under all/any one of: LGPLv2+ - http://www.and.org/ustr/LICENSE_LGPL New Style BSD (2 clause) - http://www.and.org/ustr/LICENSE_BSD MIT - http://www.and.org/ustr/LICENSE_MIT ...if that isn't enough for you, please send an email to me. The point is for the license to not matter. ustr-1.0.4/scripts/0000755000076400007640000000000010763663475013211 5ustar jamesjamesustr-1.0.4/scripts/gen_doc_templ_from_protos.pl0000755000076400007640000001166710762446571021007 0ustar jamesjames#! /usr/bin/perl -w use strict; use FileHandle; my $inc = undef; $inc ="./"; my @files = qw(main set cmp srch spn fmt b io utf8 parse cntl sc pool ins sub replace split); for my $name (@files) { if (!open(IN, "< $inc/ustr-$name.h")) { die "open: $!\n"; } $/ = undef; $_ = ; while (/^USTR_CONF_EI?_PROTO\s+([\s0-9a-zA-Z_*]*\s+\**)(ustrp?(_)[0-9a-zA-Z][0-9a-zA-Z_]*)\((?:void|\s*([^,\)]+)|\s*([^,\)]+),\s*([^,\)]+)|\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+)|\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+)|\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+)|\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+)|\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+)|\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+)|\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+),\s*([^,\)]+))\);?\s*$/gm) { print "Function: $2()\n"; print " Returns: \n"; print " Type: $1\n"; print "\n"; if (defined ($4)) { print " Parameter[1]: \n"; print " Type[1]: $4\n"; } if (defined ($5)) { print " Parameter[1]: \n"; print " Type[1]: $5\n"; print "\n"; print " Parameter[2]: \n"; print " Type[2]: $6\n"; } if (defined ($7)) { print " Parameter[1]: \n"; print " Type[1]: $7\n"; print "\n"; print " Parameter[2]: \n"; print " Type[2]: $8\n"; print "\n"; print " Parameter[3]: \n"; print " Type[3]: $9\n"; } if (defined ($10)) { print " Parameter[1]: \n"; print " Type[1]: $10\n"; print "\n"; print " Parameter[2]: \n"; print " Type[2]: $11\n"; print "\n"; print " Parameter[3]: \n"; print " Type[3]: $12\n"; print "\n"; print " Parameter[4]: \n"; print " Type[4]: $13\n"; } if (defined ($14)) { print " Parameter[1]: \n"; print " Type[1]: $14\n"; print "\n"; print " Parameter[2]: \n"; print " Type[2]: $15\n"; print "\n"; print " Parameter[3]: \n"; print " Type[3]: $16\n"; print "\n"; print " Parameter[4]: \n"; print " Type[4]: $17\n"; print "\n"; print " Parameter[5]: \n"; print " Type[5]: $18\n"; } if (defined ($19)) { print " Parameter[1]: \n"; print " Type[1]: $19\n"; print "\n"; print " Parameter[2]: \n"; print " Type[2]: $20\n"; print "\n"; print " Parameter[3]: \n"; print " Type[3]: $21\n"; print "\n"; print " Parameter[4]: \n"; print " Type[4]: $22\n"; print "\n"; print " Parameter[5]: \n"; print " Type[5]: $23\n"; print "\n"; print " Parameter[6]: \n"; print " Type[6]: $24\n"; } if (defined ($25)) { print " Parameter[1]: \n"; print " Type[1]: $25\n"; print "\n"; print " Parameter[2]: \n"; print " Type[2]: $26\n"; print "\n"; print " Parameter[3]: \n"; print " Type[3]: $27\n"; print "\n"; print " Parameter[4]: \n"; print " Type[4]: $28\n"; print "\n"; print " Parameter[5]: \n"; print " Type[5]: $29\n"; print "\n"; print " Parameter[6]: \n"; print " Type[6]: $30\n"; print "\n"; print " Parameter[7]: \n"; print " Type[7]: $31\n"; } if (defined ($32)) { print " Parameter[1]: \n"; print " Type[1]: $32\n"; print "\n"; print " Parameter[2]: \n"; print " Type[2]: $33\n"; print "\n"; print " Parameter[3]: \n"; print " Type[3]: $34\n"; print "\n"; print " Parameter[4]: \n"; print " Type[4]: $35\n"; print "\n"; print " Parameter[5]: \n"; print " Type[5]: $36\n"; print "\n"; print " Parameter[6]: \n"; print " Type[6]: $37\n"; print "\n"; print " Parameter[7]: \n"; print " Type[7]: $38\n"; print "\n"; print " Parameter[8]: \n"; print " Type[8]: $39\n"; } if (defined ($40)) { print " Parameter[1]: \n"; print " Type[1]: $41\n"; print "\n"; print " Parameter[2]: \n"; print " Type[2]: $42\n"; print "\n"; print " Parameter[3]: \n"; print " Type[3]: $43\n"; print "\n"; print " Parameter[4]: \n"; print " Type[4]: $44\n"; print "\n"; print " Parameter[5]: \n"; print " Type[5]: $45\n"; print "\n"; print " Parameter[6]: \n"; print " Type[6]: $46\n"; print "\n"; print " Parameter[7]: \n"; print " Type[7]: $47\n"; print "\n"; print " Parameter[8]: \n"; print " Type[8]: $48\n"; print "\n"; print " Parameter[9]: \n"; print " Type[9]: $49\n"; } print "\n"; print " Explanation:\n"; print "\n"; print " This function is NOT DOCUMENTED YET!\n"; print "\n"; print "\n"; } } ustr-1.0.4/scripts/clean.sh0000755000076400007640000000057410707235621014622 0ustar jamesjames#! /bin/sh if false; then echo "Not reached." elif [ -f ./ustr.pc ]; then doln=false else echo "Not in right place, goto to the root." exit 1; fi make distclean ( cd examples; make clean ) ( cd T-installed; make clean ) # Remove arch stuff rm -rf ,,* if [ "x$1" = "xfull" ]; then rm -rf lcov-output fi rm -f gmon.out rm -f lib-all.info rm -f lib-all-ustr.info ustr-1.0.4/scripts/coverage.sh0000755000076400007640000000050410671774716015341 0ustar jamesjames#! /bin/sh -e if false; then echo "Not reached." elif [ -f ./Makefile ]; then doln=false else echo "Not in right place, goto the root." exit 1; fi make clean make CFLAGS="-g -fprofile-arcs -ftest-coverage -O0" \ LDFLAGS="-g -fprofile-arcs -ftest-coverage -O0" check-lcov \ -j $(getconf _NPROCESSORS_ONLN) ustr-1.0.4/scripts/lcov.sh0000755000076400007640000000214610630111754014473 0ustar jamesjames#! /bin/sh if false; then echo "Not reached." elif [ -f ./Makefile ]; then doln=false else echo "Not in right place, goto to the root." exit 1; fi # if [ "x$1" = "x" ]; then # echo "Not got arg." # exit 1; # fi name="$1" name="all" # gendesc $d/coverage_descriptions.txt -o descriptions lcov --capture --directory . --output-file lib-$name.info --test-name lib-$name # Remove tst data... lcov -r lib-$name.info 'malloc-check.h' 'tst*' 'ctst*' 'otst*' 'octst*' '/usr/include/*' > lib-$name-ustr.info #cd examples #lcov --capture --directory T --output-file ../examples-$1.info --test-name examples-$1 #cd .. mkdir lcov-output || true genhtml lib-$name-ustr.info --output-directory lcov-output/lib --title "Ustr coverage" --show-details # --description-file descriptions # genhtml examples*.info --output-directory output/examples --title "Ustr EXAMPLES coverage" --show-details --description-file descriptions genhtml lib-$name.info --output-directory lcov-output/all --title "Ustr ALL coverage" --show-details # --description-file descriptions echo Point your browser at file:`pwd`/lcov-output/lib/index.html ustr-1.0.4/scripts/git-push-web.sh0000755000076400007640000000015610631115201016032 0ustar jamesjames#! /bin/sh -e # From http://www.and.org/hacks/git-push-web.sh git-push-web.sh tst:public_html/ustr/ustr.git ustr-1.0.4/scripts/list_functions_doc.sh0000755000076400007640000000051210636672332017425 0ustar jamesjames#! /bin/sh if false; then echo "Do nothing" elif [ -r ./Documentation/functions.txt ]; then doc=./Documentation elif [ -r ../Documentation/functions.txt ]; then doc=../Documentation else echo "No Documentation dir" exit 1; fi egrep "^Function" $doc/functions.txt | awk '{ print $2 }' | \ egrep -v "^USTR_FLAGXX" ustr-1.0.4/scripts/rpms-create-james.sh0000755000076400007640000000271210760727137017062 0ustar jamesjames#! /bin/bash -e pkg=ustr # FIXME: More C&P of VERSION v="1.0.4" if [ ! -f ustr-main.h ]; then if [ -f ustr/ustr-main.h ]; then cd ustr else echo "No VERSION, $pkg.spec or configure file." 1&>2 exit 1 fi fi s="`pwd`" cd ../build/$pkg rm -rf $pkg-$v cp -a $s ./$pkg-$v cd ./$pkg-$v ./scripts/clean.sh full ( cd Documentation && make ) perl -p -i -e \ 's{href="(tutorial|constants|design|functions|structs)(?!\.html)\b} {href="$1.html}g;' Documentation/*.html rm -rf tmp # Backup files... find . \ \( -name "*.o" -o -name ".*[%~]" -o -name "*[%~]" -o -name "#*#" \) \ -print0 | xargs --no-run-if-empty -0 rm -f # git rm -rf .git # Arch stuff... rm -rf ./{arch} find . -name .arch-ids -type d -print0 | xargs -0 rm -rf # Create tarballs/RPMS cp $s/$pkg.spec . cd .. chk=1 rel=1 if [ "x$1" = "xnochk" ]; then echo Not doing checking. chk=0 shift else echo Doing checking. args="$args --define \"chk 1\"" fi if [ "x$1" = "xrel" ]; then shift echo Using custom release $1. rel=$1 shift else echo Using normal release of 1. fi perl -i -pe "s/^Release: 1/Release: $rel/" $pkg-$v/$pkg.spec tar -cf - $pkg-$v | \ tee >(gzip -9 -c > $pkg-$v.tar.gz) | \ bzip2 -9 -c > $pkg-$v.tar.bz2 # sudo rpmbuild -ts --define "chk $chk" $pkg-$v.tar.gz rpmbuild --define "_sourcedir `pwd`/tmp" --define "_specdir `pwd`/tmp" \ --define "_srcrpmdir `pwd`" -ts \ $pkg-$v.tar.gz mock $pkg-$v-$rel*.src.rpm ls -ahslF `pwd`/$pkg-$v-$rel*.src.rpm ustr-1.0.4/scripts/cmp_symbols_ver.sh0000755000076400007640000000104710636672776016760 0ustar jamesjames#! /bin/sh -e if false; then echo "Not reached." elif [ -f ./ustr.pc ]; then doln=false else echo "Not in right place, goto to the root." exit 1; fi sort libustr.ver > /tmp/libustr.ver.sort tr -d '; ' < /tmp/libustr.ver.sort > /tmp/ustr.libver.sort.tr egrep -v '^$' < /tmp/ustr.libver.sort.tr > /tmp/ustr.libver.sort.tr.grepv ./scripts/list_functions_src.pl | sort > /tmp/ustr.gen.sort tr -d '() ' < /tmp/ustr.gen.sort > /tmp/ustr.gen.sort.tr # -Bb doesn't work *sighs* diff -u /tmp/ustr.libver.sort.tr.grepv /tmp/ustr.gen.sort.tr ustr-1.0.4/scripts/list_functions_src.pl0000755000076400007640000000145010673035312017442 0ustar jamesjames#! /usr/bin/perl -w use strict; use FileHandle; my $inc = undef; if (0) {} elsif (-r "./Makefile") { $inc ="./"; } if (!defined ($inc)) { STDERR->print("Can't find Makefile.\n"); exit (1); } my $all = 0; $all = 1 if (@ARGV); my @files = qw(main set cmp srch spn fmt b io utf8 parse cntl sc pool ins sub replace split); for my $name (@files) { if (!open(IN, "< $inc/ustr-$name.h")) { die "open: $!\n"; } $/ = undef; $_ = ; # Not valid for everything C, but good enough... if ($all) { while (/^#define\s+(USTRP?_?[0-9a-zA-Z][0-9a-zA-Z_]*)\s*\(/gm) { print "$1()\n"; } } # Note all macro function are above prototypes... while (/^USTR_CONF_EI?_PROTO\s+[\s0-9a-zA-Z_*]*\s+\**(ustrp?_(_)?[0-9a-zA-Z][0-9a-zA-Z_]*)\(/gm) { print "$1()\n"; } } ustr-1.0.4/scripts/cmp_symbols_doc.sh0000755000076400007640000000051710636672643016723 0ustar jamesjames#! /bin/sh -e if false; then echo "Not reached." elif [ -f ./ustr.pc ]; then doln=false else echo "Not in right place, goto to the root." exit 1; fi ./scripts/list_functions_doc.sh | sort > /tmp/ustr.doc.sort ./scripts/list_functions_src.pl x | sort > /tmp/ustr.gen.sort diff -u /tmp/ustr.doc.sort /tmp/ustr.gen.sort ustr-1.0.4/LICENSE_BSD0000644000076400007640000000267310630111754013204 0ustar jamesjamesCopyright 2007 James Antill Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. ustr-1.0.4/ustr-main-opt-code.c0000644000076400007640000000060510674563614015311 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO inline #include "ustr-main.h" ustr-1.0.4/.gitignore0000644000076400007640000000127510755424363013507 0ustar jamesjames/autoconf_64b /autoconf_vsnprintf /ctst_* /octst_* /tst_* /otst_* /lcov-output /lib-all-ustr.info /lib-all.info /libustr-1.0.so.1.0.* /libustr-debug-1.0.so.1.0.* /ustr-conf-debug.h /ustr-conf.h /ustr-import examples/hello_world examples/hello_world-s examples/netstr examples/netstr-s examples/hexdump examples/hexdump-s examples/nums examples/nums-s examples/mkdir_p examples/mkdir_p-s examples/fgrep examples/fgrep-s examples/txt2html examples/txt2html-s examples/custr examples/custr-s examples/linecat_* examples/linecat*-s examples/basename examples/basename-s examples/dirname examples/dirname-s abcd T-installed/tst_*_norm T-installed/tst_*_dbg1 T-installed/tst_*_dbg2 T-installed/tst_vstr_chk ustr-1.0.4/ustr-conf-64.h0000644000076400007640000000367710760731462014044 0ustar jamesjames#ifndef USTR_CONF_H #define USTR_CONF_H 1 /* this is the custom version for the library itself, for everyone else * ustr-import generates one depending on the options. */ /* The default is now to link against libc. */ #ifndef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #endif /* We can't: if defined(__GLIBC__) && (!defined(_GNU_SOURCE) || !_GNU_SOURCE) * because by the time we've included a libc header it's too late. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif /* maybe move memmem / memrchr here? */ #if ! USTR_CONF_INCLUDE_CODEONLY_HEADERS /* If you aren't just using the headers, these should match the .c's */ # define USTR_CONF_HAVE_64bit_SIZE_MAX 1 # define USTR_CONF_HAVE_RETARDED_VSNPRINTF 0 # define USTR_CONF_HAVE_STDINT_H 1 # define USTR_CONF_HAVE_DYNAMIC_CONF 1 # define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF # define USTR_CONF_REF_BYTES 1 # define USTR_CONF_EXACT_BYTES 0 # define USTR_CONF_USE_SIZE 0 # define USTR_CONF_USE_ASSERT 0 # define USTR_CONF_USE_EOS_MARK 0 #else /* Same defaults, but can be altered at will. */ /* Note that you really shouldn't alter the _HAVE_* ones, but whatever */ # ifndef USTR_CONF_HAVE_64bit_SIZE_MAX # define USTR_CONF_HAVE_64bit_SIZE_MAX 1 # endif # ifndef USTR_CONF_HAVE_RETARDED_VSNPRINTF # define USTR_CONF_HAVE_RETARDED_VSNPRINTF 0 # endif # ifndef USTR_CONF_HAVE_STDINT_H # define USTR_CONF_HAVE_STDINT_H 1 # endif # ifndef USTR_CONF_HAVE_DYNAMIC_CONF # define USTR_CONF_HAVE_DYNAMIC_CONF 1 # endif /* no USE_DYNAMIC_CONF ... use default in ustr-main.h */ # ifndef USTR_CONF_REF_BYTES # define USTR_CONF_REF_BYTES 1 # endif # ifndef USTR_CONF_EXACT_BYTES # define USTR_CONF_EXACT_BYTES 0 # endif # ifndef USTR_CONF_USE_SIZE # define USTR_CONF_USE_SIZE 0 # endif # ifndef USTR_CONF_USE_ASSERT # define USTR_CONF_USE_ASSERT 0 # endif # ifndef USTR_CONF_USE_EOS_MARK # define USTR_CONF_USE_EOS_MARK 0 # endif #endif #endif ustr-1.0.4/ustr-sub-dbg-code.c0000644000076400007640000000140610722116212015066 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-fmt.h" #include "ustr-ins.h" #include "ustr-srch.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-sub.h" ustr-1.0.4/T/0000755000076400007640000000000010763663475011725 5ustar jamesjamesustr-1.0.4/T/tst_7_auto.c0000644000076400007640000000013310630111754014133 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 2 #define USTR_CONF_USE_EOS_MARK 0 ustr-1.0.4/T/ctst_0_sizes.c0000644000076400007640000000000010630111754014445 0ustar jamesjamesustr-1.0.4/T/tst_19_concat.c0000644000076400007640000000000010754732223014515 0ustar jamesjamesustr-1.0.4/T/otst_10_b.c0000644000076400007640000000012210630111754013633 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 0 #include "ctst_10_b.c" ustr-1.0.4/T/ctst_99_enomem.c0000644000076400007640000007000310760720047014711 0ustar jamesjames#include "tst.h" #include static const char *rf = __FILE__; int tst(void) { Ustr_pool *pool = NULL; Ustrp *sp1 = USTRP1(\x4, "abcd"); Ustrp *sp2 = USTRP1(\x4, ".xyz"); Ustrp *sp3 = USTRP1(\x8, "abcd.xyz"); Ustr *s3 = NULL; unsigned int scan = 0; unsigned int lim = 0; size_t off = 0; if (USTR_CONF_USE_DYNAMIC_CONF) { assert(USTR_CNTL_MALLOC_CHECK_LVL() == 1); TST_MC_SET_NUM(1); assert(USTR_CNTL_MALLOC_CHECK_ADD(USTR_TRUE)); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 2); assert(USTR_CNTL_MALLOC_CHECK_ADD(USTR_TRUE)); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 3); assert(!USTR_CNTL_MALLOC_CHECK_ADD(USTR_TRUE)); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 3); assert(USTR_CNTL_MALLOC_CHECK_ADD(USTR_TRUE)); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 4); assert(USTR_CNTL_MALLOC_CHECK_DEL(USTR_TRUE)); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 3); assert(USTR_CNTL_MALLOC_CHECK_DEL(USTR_TRUE)); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 2); assert(USTR_CNTL_MALLOC_CHECK_DEL(USTR_TRUE)); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 1); assert(!USTR_CNTL_MALLOC_CHECK_DEL(USTR_TRUE)); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 1); assert(!USTR_CNTL_MALLOC_CHECK_DEL(USTR_TRUE)); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 1); ustr_free(s2); s2 = USTR(""); assert(USTR_CNTL_MALLOC_CHECK_END()); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 0); assert(!USTR_CNTL_MALLOC_CHECK_END()); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 0); assert(!USTR_CNTL_MALLOC_CHECK_END()); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 0); assert(USTR_CNTL_MALLOC_CHECK_BEG(USTR_TRUE)); assert(USTR_CNTL_MALLOC_CHECK_LVL() == 1); } lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!(pool = ustr_pool_ll_make())); } ASSERT((pool = ustr_pool_ll_make())); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustr_pool_make_subpool(pool)); } ASSERT(ustr_pool_make_subpool(pool)); ASSERT(ustr_pool_make_subpool(pool)); lim = 2; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!pool->pool_sys_malloc(pool, 1)); } ASSERT(pool->pool_sys_malloc(pool, 1)); ASSERT(!ustr_dup_undef(-2)); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_dup_buf(pool, "xy", 1)); } ASSERT((sp1 = ustrp_dup_buf(pool, "xy", 1))); ASSERT_PEQ(sp1, USTRP1(\1, "x")); if (ustrp_setf_share(sp1)) { TST_MC_SET_NUM(1); ASSERT(!ustrp_enomem(sp1)); ASSERT(!ustrp_set_buf(pool, &sp1, "ab", 1)); ASSERT(!ustrp_enomem(sp1)); ASSERT_PEQ(sp1, USTRP1(\1, "x")); ASSERT(ustrp_sc_ensure_owner(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\1, "x")); /* TST_MC_SET_NUM(1); ASSERT(!ustrp_set_buf(pool, &sp1, "ab", 1)); ASSERT( ustrp_enomem(sp1)); ASSERT( ustrp_setf_enomem_clr(sp1)); ASSERT_PEQ(sp1, USTRP1(\1, "x")); */ ASSERT( ustrp_set_buf(pool, &sp1, "ab", 1)); ASSERT(!ustrp_enomem(sp1)); ASSERT_PEQ(sp1, USTRP1(\1, "a")); sp1 = USTRP1(\4, "abcd"); ASSERT(ustrp_sc_ensure_owner(pool, &sp1)); ASSERT(ustrp_setf_share(sp1)); TST_MC_SET_NUM(1); ASSERT(!ustrp_enomem(sp1)); ASSERT(!ustrp_set_subustrp(pool, &sp1, sp1, 3, 1)); ASSERT(!ustrp_enomem(sp1)); ASSERT(!ustrp_setf_enomem_clr(sp1)); ASSERT( ustrp_set_subustrp(pool, &sp1, sp1, 3, 1)); ASSERT(!ustrp_enomem(sp1)); ASSERT( ustrp_len(sp1) == 1); ASSERT( ustrp_alloc(sp1)); ASSERT_PEQ(sp1, USTRP1(\1, "c")); ASSERT(ustrp_setf_share(sp1)); TST_MC_SET_NUM(1); ASSERT(!ustrp_enomem(sp1)); ASSERT(!ustrp_set_empty(pool, &sp1)); ASSERT(!ustrp_enomem(sp1)); ASSERT(!ustrp_setf_enomem_clr(sp1)); ASSERT( ustrp_set_empty(pool, &sp1)); ASSERT(!ustrp_enomem(sp1)); ASSERT(!ustrp_len(sp1)); ASSERT( ustrp_alloc(sp1)); } lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_dup_empty(pool)); } ASSERT((sp1 = ustrp_dupx_undef(pool, 1, 0, 0, 0, 1256))); ASSERT(ustrp_del(pool, &sp1, 1000)); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT( ustrp_setf_enomem_clr(sp1)); ASSERT(!ustrp_realloc(pool, &sp1, 0)); ASSERT(!ustrp_exact(sp1)); ASSERT( ustrp_size(sp1) > ustrp_len(sp1)); ASSERT( ustrp_enomem(sp1)); } ASSERT(!ustrp_exact(sp1)); ASSERT( ustrp_size(sp1) > ustrp_len(sp1)); ASSERT( ustrp_realloc(pool, &sp1, 0)); ASSERT(!ustrp_exact(sp1)); ASSERT( ustrp_size(sp1) == ustrp_len(sp1)); TST_MC_SET_NUM(1); ASSERT(ustrp_del(pool, &sp1, 56)); ASSERT(ustrp_size_overhead(sp1) >= 6); ASSERT(!ustrp_realloc(pool, &sp1, 0)); ASSERT(ustrp_size_overhead(sp1) >= 6); ASSERT( ustrp_realloc(pool, &sp1, 0)); ASSERT(ustrp_size_overhead(sp1) >= 6); ASSERT(!ustrp_realloc(pool, &sp1, (65 * 1000) + 529)); /* too big */ ASSERT(!ustrp_realloc(pool, &sp1, (65 * 1000) + 529)); /* too big */ ASSERT(!ustrp_realloc(pool, &sp1, (65 * 1000) + 529)); /* too big */ ASSERT((sp1 = ustrp_dupx_undef(pool, 1, 0, 1, 0, 65520))); ASSERT((sp1 = ustrp_dupx_undef(pool, 1, 0, 1, 0, 65500))); ASSERT(!ustrp_realloc(pool, &sp1, 1)); /* too small */ ASSERT(!ustrp_realloc(pool, &sp1, 1)); /* too small */ ASSERT(!ustrp_realloc(pool, &sp1, 1)); /* too small */ ustr_pool_clear(pool); ASSERT((sp1 = ustrp_dupx_undef(pool, 1, 0, 0, 0, 65536))); ASSERT(!ustrp_add_undef(pool, &sp1, -65534)); ustr_pool_clear(pool); ASSERT((sp1 = ustrp_dup_undef(pool, 16))); TST_MC_SET_NUM(1); ASSERT(ustrp_len(sp1) == 16); ASSERT(!ustrp_enomem(sp1)); ASSERT( ustrp_del(pool, &sp1, 10)); ASSERT(!ustrp_enomem(sp1)); ASSERT(!TST_MC_GET_NUM()); ASSERT(ustrp_set_cstr(pool, &sp1, "abcd")); if (ustrp_setf_share(sp1)) { TST_MC_SET_NUM(1); ASSERT(ustrp_len(sp1) == 4); ASSERT(!ustrp_enomem(sp1)); ASSERT(!ustrp_sc_ensure_owner(pool, &sp1)); ASSERT( ustrp_sc_ensure_owner(pool, &sp1)); ASSERT( ustrp_sc_ensure_owner(pool, &sp1)); ASSERT((sp1 = ustrp_dup_empty(pool))); ASSERT(ustrp_setf_share(sp1)); TST_MC_SET_NUM(1); ASSERT(!ustrp_sc_ensure_owner(pool, &sp1)); ASSERT( ustrp_sc_ensure_owner(pool, &sp1)); ASSERT( ustrp_sc_ensure_owner(pool, &sp1)); ASSERT(ustrp_setf_share(sp1)); TST_MC_SET_NUM(1); ASSERT(!ustrp_sc_wstr(pool, &sp1)); ASSERT( ustrp_sc_wstr(pool, &sp1)); ASSERT( ustrp_sc_wstr(pool, &sp1)); ASSERT(ustrp_set_cstr(pool, &sp1, "abcd")); ASSERT(ustrp_setf_share(sp1)); TST_MC_SET_NUM(1); ASSERT(ustrp_len(sp1) == 4); ASSERT(!ustrp_del_subustrp(pool, &sp1, 4, 1)); ASSERT(!ustrp_enomem(sp1)); } ASSERT(!TST_MC_GET_NUM()); ASSERT( ustrp_del_subustrp(pool, &sp1, 4, 1)); ASSERT_PEQ(sp1, USTRP1(\x3, "abc")); if (!USTR_DEBUG) ASSERT(!ustrp_del_subustrp(pool, &sp1, 4, 1)); sp1 = USTRP1(\x4, "abcd"); TST_MC_SET_NUM(1); ASSERT(ustrp_len(sp1) == 4); ASSERT(!ustrp_enomem(sp1)); ASSERT(!ustrp_del_subustrp(pool, &sp1, 3, 1)); ASSERT(!ustrp_enomem(sp1)); ASSERT(!TST_MC_GET_NUM()); ASSERT( ustrp_del_subustrp(pool, &sp1, 3, 1)); ASSERT_PEQ(sp1, USTRP1(\x3, "abd")); sp1 = USTRP1(\x4, "abcd"); TST_MC_SET_NUM(1); ASSERT(!ustrp_add_fmt(pool, &sp1, "%.500d", 4)); TST_MC_SET_NUM(1); ASSERT(!ustrp_set_fmt(pool, &sp1, "%.500d", 4)); TST_MC_SET_NUM(1); ASSERT(!ustrp_ins_fmt(pool, &sp1, 1, "%.500d", 4)); TST_MC_SET_NUM(1); ASSERT(!ustrp_sub_fmt(pool, &sp1, 1, "%.500d", 4)); TST_MC_SET_NUM(1); ASSERT(!ustrp_sc_sub_fmt(pool, &sp1, 1, 2, "%.500d", 4)); TST_MC_SET_NUM(1); ASSERT(!(sp1 = ustrp_dup_fmt(pool, "%.500d", 4))); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_dup_subustrp(pool, sp3, 2, 3)); } ASSERT((sp1 = ustrp_dup_subustrp(pool, sp3, 2, 3))); ASSERT(ustrp_cmp_subustrp_eq(sp1, sp3, 2, 3)); ASSERT(ustrp_cmp_cstr_eq(sp1, "bcd")); s1 = USTR1(\x8, "12345678"); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!(s1 = ustr_dupx_subustr(0, 1, 1, 1, USTR1(\7, "abcdefg"), 1, 7))); } ASSERT((s1 = ustr_dupx_subustr(0, 1, 1, 1, USTR1(\7, "abcdefg"), 1, 7))); ASSERT_EQ(s1, USTR1(\x7, "abcdefg")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustr_add_subustr(&s1, s1, 3, 4)); } ASSERT(ustr_add_subustr(&s1, s1, 3, 4)); ASSERT(ustr_cmp_cstr_eq(s1, "abcdefgcdef")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustr_sc_dupx(0, 0, 0, 0, &s1)); } ASSERT((s3 = ustr_sc_dupx(0, 0, 0, 0, &s1))); ASSERT(ustr_cmp_cstr_eq(s1, "abcdefgcdef")); ASSERT(ustr_cmp_cstr_eq(s3, "abcdefgcdef")); ustr_sc_free(&s3); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_dup_rep_chr(pool, '-', 4)); } ASSERT((sp1 = ustrp_dup_rep_chr(pool, '-', 4))); ASSERT(ustrp_cmp_cstr_eq(sp1, "----")); ASSERT((sp1 = ustrp_dupx(pool, 0, 0, 0, 0, sp1))); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_sc_dup(pool, &sp1)); } ASSERT((sp3 = ustrp_sc_dup(pool, &sp1))); ASSERT(ustrp_cmp_cstr_eq(sp1, "----")); ASSERT(ustrp_cmp_cstr_eq(sp3, "----")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_sc_dupx(pool, 0, 0, 0, 0, &sp1)); } ASSERT((sp3 = ustrp_sc_dupx(pool, 0, 0, 0, 0, &sp1))); ASSERT(ustrp_cmp_cstr_eq(sp1, "----")); ASSERT(ustrp_cmp_cstr_eq(sp3, "----")); ustr_pool_clear(pool); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_dupx_rep_chr(pool, 0, 1, 1, 1, '=', 8)); } ASSERT((sp1 = ustrp_dupx_rep_chr(pool, 0, 1, 1, 1, '=', 8))); ASSERT(ustrp_cmp_cstr_eq(sp1, "========")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_add_rep_chr(pool, &sp1, '-', 2)); } ASSERT(ustrp_add_rep_chr(pool, &sp1, '-', 2)); ASSERT(ustrp_cmp_cstr_eq(sp1, "========--")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_add_cstr(pool, &sp1, "xyz")); } ASSERT(ustrp_add_cstr(pool, &sp1, "xyz")); ASSERT(ustrp_cmp_cstr_eq(sp1, "========--xyz")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_add(pool, &sp2, sp1)); } ASSERT(ustrp_add(pool, &sp2, sp1)); ASSERT(ustrp_cmp_cstr_eq(sp2, ".xyz========--xyz")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_add(pool, &sp2, sp1)); } ASSERT(ustrp_add(pool, &sp2, sp1)); ASSERT(ustrp_cmp_cstr_eq(sp2, ".xyz========--xyz========--xyz")); sp2 = USTRP(""); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_set(pool, &sp2, sp1)); } ASSERT(ustrp_set(pool, &sp2, sp1)); ASSERT(ustrp_cmp_cstr_eq(sp2, "========--xyz")); ASSERT((sp2 = ustrp_dupx_cstr(pool, 1, 1, 0, 0, "abcd"))); ASSERT( ustrp_sized(sp2)); ustrp_sc_del(pool, &sp2); ASSERT( ustrp_sized(sp2)); ASSERT( ustrp_alloc(sp2)); ASSERT(!ustrp_len(sp2)); ASSERT((sp2 = ustrp_dupx_cstr(pool, 1, 1, 0, 0, "abcd"))); if (!ustrp_setf_share(sp2)) sp2 = USTRP(""); else { ASSERT(ustrp_sized(sp2)); TST_MC_SET_NUM(1); ustrp_sc_del(pool, &sp2); /* failure path makes it constant */ } ASSERT(!ustrp_sized(sp2)); ASSERT(!ustrp_alloc(sp2)); ASSERT(!ustrp_len(sp2)); ASSERT(ustrp_owner(sp1)); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_add(pool, &sp2, sp1)); } ASSERT(ustrp_add(pool, &sp2, sp1)); ASSERT_PEQ(sp1, sp2); sp2 = USTRP(""); /* convert sp1 to default config. */ ASSERT((sp1 = ustrp_dup_buf(pool, ustrp_cstr(sp1), ustrp_len(sp1)))); ASSERT(ustrp_owner(sp1)); ASSERT(ustrp_add_rep_chr(pool, &sp1, '*', ustrp_size(sp1) - ustrp_len(sp1))); if (USTR_CONF_INCLUDE_CODEONLY_HEADERS) { /* no ref counts */ ASSERT(ustrp_add(pool, &sp2, sp1)); ASSERT_PEQ(sp1, sp2); ASSERT(sp1 != sp2); } else { TST_MC_SET_NUM(1); /* only adds ref. ... won't fail */ ASSERT(ustrp_add(pool, &sp2, sp1)); ASSERT_PEQ(sp1, sp2); ASSERT(sp1 == sp2); ASSERT(!ustrp_owner(sp2)); } lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_add(pool, &sp2, sp2)); } ASSERT(ustrp_add(pool, &sp2, sp2)); ASSERT(ustrp_len(sp2) == (2 * ustrp_len(sp1))); ASSERT(!(ustrp_len(sp2) % 2)); ASSERT(ustrp_cmp_prefix_buf_eq(sp2, ustrp_cstr(sp2), ustrp_len(sp2) / 2)); ASSERT(ustrp_cmp_suffix_buf_eq(sp2, ustrp_cstr(sp2), ustrp_len(sp2) / 2)); ASSERT(ustrp_cmp_subustrp_eq(sp1, sp2, 1, ustrp_len(sp2) / 2)); /* make sure sp1 isn't the last thing allocated */ ASSERT(pool->pool_sys_malloc(pool, 1)); sp2 = sp1; ASSERT( ustrp_alloc(sp2)); ASSERT( ustrp_owner(sp2)); ASSERT( ustrp_size(sp2) == ustrp_len(sp2)); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT(!ustrp_add(pool, &sp2, sp2)); } ASSERT(ustrp_add(pool, &sp2, sp2)); ASSERT(ustrp_len(sp2) == (2 * ustrp_len(sp1))); ASSERT(!(ustrp_len(sp2) % 2)); ASSERT(ustrp_cmp_prefix_buf_eq(sp2, ustrp_cstr(sp2), ustrp_len(sp2) / 2)); ASSERT(ustrp_cmp_suffix_buf_eq(sp2, ustrp_cstr(sp2), ustrp_len(sp2) / 2)); ASSERT(ustrp_cmp_subustrp_eq(sp1, sp2, 1, ustrp_len(sp2) / 2)); ustr_pool_free(pool); s3 = USTR1(\4, "1234"); TST_MC_SET_NUM(1); ASSERT(!ustr_io_get(&s3, stdin, 1, NULL)); TST_MC_SET_NUM(1); ASSERT(!ustr_io_putline(&s3, stdout, 2)); sp1 = NULL; ustrp_sc_free_shared(pool, &sp1); ustr_sc_free2(&s1, USTR1(\x8, "12345678")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\x8, "12345678")); ASSERT(!ustr_sc_reverse(&s1)); } ASSERT( ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR1(\x8, "87654321")); ustr_sc_free2(&s1, USTR1(\x8, "12345678")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\x8, "12345678")); ASSERT(!ustr_sc_utf8_reverse(&s1)); } ASSERT( ustr_sc_utf8_reverse(&s1)); ASSERT_EQ(s1, USTR1(\x8, "87654321")); ustr_sc_free2(&s1, USTR1(\x34, "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\x34, "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); ASSERT(!ustr_sc_tolower(&s1)); } ASSERT( ustr_sc_tolower(&s1)); ASSERT_EQ(s1, USTR1(\x34, "abcdefghijklmnopqrstuvwxyz" "abcdefghijklmnopqrstuvwxyz")); ustr_sc_free2(&s1, USTR1(\x34, "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\x34, "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); ASSERT(!ustr_sc_toupper(&s1)); } TST_MC_SET_NUM(scan); ASSERT( ustr_sc_toupper(&s1)); ASSERT(TST_MC_GET_NUM() == 1); ASSERT_EQ(s1, USTR1(\x34, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); ustr_sc_free2(&s1, USTR1(\x34, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\x34, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); ASSERT(!ustr_sub_buf(&s1, 1, "xyz", 3)); } TST_MC_SET_NUM(scan); ASSERT( ustr_sub_buf(&s1, 1, "xyz", 3)); ASSERT_EQ(s1, USTR1(\x34, "xyzDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); ASSERT(TST_MC_GET_NUM() == 1); ustr_sc_free2(&s1, USTR1(\x34, "xyzDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\x34, "xyzDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); ASSERT(!ustr_sc_sub_rep_chr(&s1, 4, 0x31, '-', 8)); } TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\x34, "xyzDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); ASSERT( ustr_sc_sub_rep_chr(&s1, 4, 0x31, '-', 8)); ASSERT_EQ(s1, USTR1(\xb, "xyz--------")); ASSERT(TST_MC_GET_NUM() == 1); ustr_sc_free2(&s1, USTR1(\xb, "xyz--------")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\xb, "xyz--------")); ASSERT(!ustr_sub_rep_chr(&s1, 8, '=', 8)); } TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\xb, "xyz--------")); ASSERT( ustr_sub_rep_chr(&s1, 8, '=', 8)); ASSERT_EQ(s1, USTR1(\xf, "xyz----========")); ASSERT(TST_MC_GET_NUM() == 1); ustr_sc_free2(&s1, USTR1(\xf, "xyz----========")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\xf, "xyz----========")); ASSERT(!ustr_replace_cstr(&s1, "-", "#", 0)); } TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\xf, "xyz----========")); ASSERT( ustr_replace_cstr(&s1, "-", "#", 0)); ASSERT_EQ(s1, USTR1(\xf, "xyz####========")); ASSERT(TST_MC_GET_NUM() == 1); ustr_sc_free2(&s1, USTR1(\xf, "xyz----========")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\xf, "xyz----========")); ASSERT(!ustr_replace_rep_chr(&s1, '-', 1, '#', 1, 0)); } TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\xf, "xyz----========")); ASSERT( ustr_replace_rep_chr(&s1, '-', 1, '#', 1, 0)); ASSERT_EQ(s1, USTR1(\xf, "xyz####========")); ASSERT(TST_MC_GET_NUM() == 1); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\xf, "xyz####========")); ASSERT(!ustr_replace_cstr(&s1, "x", "____", 0)); } TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\xf, "xyz####========")); ASSERT( ustr_replace_cstr(&s1, "x", "____", 0)); ASSERT_EQ(s1, USTR1(\x12, "____yz####========")); ASSERT(TST_MC_GET_NUM() == 1); ustr_sc_free2(&s2, USTR("")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR("")); off = 0; ASSERT(!ustr_split_cstr(s1, &off, "##", s2, 0)); } TST_MC_SET_NUM(scan); off = 0; ASSERT_EQ(s2, USTR("")); ASSERT((s2 = ustr_split_cstr(s1, &off, "##", s2, 0))); ASSERT_EQ(s1, USTR1(\x12, "____yz####========")); ASSERT_EQ(s2, USTR1(\6, "____yz")); if ((ustr_size(s2) - ustr_len(s2)) >= 2) { ASSERT((s2 = ustr_split(s1, &off, USTR1(\2, "!+"), s2, 0))); ASSERT_EQ(s2, USTR1(\x8, "========")); } ASSERT(TST_MC_GET_NUM() == 1); ustr_sc_free2(&s2, USTR("")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR("")); off = 0; ASSERT(!ustr_split_spn(s1, &off, USTR1(\2, "#+"), s2, 0)); } TST_MC_SET_NUM(scan); off = 0; ASSERT_EQ(s2, USTR("")); ASSERT((s2 = ustr_split_spn(s1, &off, USTR1(\2, "#+"), s2, 0))); ASSERT_EQ(s1, USTR1(\x12, "____yz####========")); ASSERT_EQ(s2, USTR1(\6, "____yz")); if ((ustr_size(s2) - ustr_len(s2)) >= 2) { ASSERT((s2 = ustr_split_spn(s1, &off, USTR1(\2, "!+"), s2, 0))); ASSERT_EQ(s2, USTR1(\x8, "========")); } ASSERT(TST_MC_GET_NUM() == 1); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\x12, "____yz####========")); ASSERT(!ustr_replace_rep_chr(&s1, '_', 1, '-', 2, 0)); } TST_MC_SET_NUM(scan); ASSERT_EQ(s1, USTR1(\x12, "____yz####========")); ASSERT( ustr_replace_rep_chr(&s1, '_', 1, '-', 2, 0)); ASSERT_EQ(s1, USTR1(\x16, "--------yz####========")); ASSERT(TST_MC_GET_NUM() == 1); ustr_sc_free2(&s2, USTR1(\6, "____yz")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR1(\6, "____yz")); ASSERT(!ustr_ins_cstr(&s2, 1, "#")); } TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR1(\6, "____yz")); ASSERT( ustr_ins_cstr(&s2, 1, "##")); ASSERT_EQ(s2, USTR1(\x8, "_##___yz")); ASSERT(TST_MC_GET_NUM() == 1); ustr_sc_free2(&s2, USTR1(\x8, "_##___yz")); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR1(\x8, "_##___yz")); ASSERT(!ustr_ins_rep_chr(&s2, 2, '+', 2)); } TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR1(\x8, "_##___yz")); ASSERT( ustr_ins_rep_chr(&s2, 2, '+', 2)); ASSERT_EQ(s2, USTR1(\xa, "_#++#___yz")); ASSERT(TST_MC_GET_NUM() == 1); lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR1(\xa, "_#++#___yz")); ASSERT(!ustr_ins_fmt(&s2, 3, "%s", "================")); } TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR1(\xa, "_#++#___yz")); ASSERT( ustr_ins_fmt(&s2, 3, "%s", "================")); ASSERT_EQ(s2, USTR1(\x1a, "_#+================+#___yz")); ASSERT(TST_MC_GET_NUM() == 1); s3 = ustr_dup(s2); if (!ustr_owner(s2)) { lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR1(\x1a, "_#+================+#___yz")); ASSERT(!ustr_sub_fmt(&s2, 4, "%s", "----------------")); } TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR1(\x1a, "_#+================+#___yz")); ASSERT( ustr_sub_fmt(&s2, 4, "%s", "----------------")); ASSERT_EQ(s2, USTR1(\x1a, "_#+----------------+#___yz")); ASSERT(TST_MC_GET_NUM() == 1); } ustr_sc_free2(&s3, ustr_dup(s2)); if (!ustr_owner(s2)) { lim = 1; scan = 0; while (scan++ < lim) { TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR1(\x1a, "_#+----------------+#___yz")); ASSERT(!ustr_sc_sub_fmt(&s2, 4, 16, "%s", "................")); } TST_MC_SET_NUM(scan); ASSERT_EQ(s2, USTR1(\x1a, "_#+----------------+#___yz")); ASSERT( ustr_sc_sub_fmt(&s2, 4, 16, "%s", "................")); ASSERT_EQ(s2, USTR1(\x1a, "_#+................+#___yz")); ASSERT(TST_MC_GET_NUM() == 1); } ustr_sc_free2(&s3, USTR("")); TST_MC_SET_NUM(0); ustr_sc_free2(&s2, USTR("")); ustr_set_rep_chr(&s2, '-', 65); ASSERT(ustr_size_alloc(s2) == 96); TST_MC_SET_NUM(1); ASSERT(ustr_del(&s2, 60)); ASSERT(ustr_size_alloc(s2) < 96); ASSERT(!ustr_enomem(s2)); ASSERT(ustr_len(s2) == 5); ASSERT(ustr_cmp_cstr_eq(s2, "-----")); assert(USTR_CNTL_MALLOC_CHECK_MEM(s2)); assert(USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(s2, ustr_size_alloc(s2))); assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(s2, ustr_size_alloc(s2))); ASSERT((pool = ustr_pool_ll_make())); sp2 = USTRP(""); ustrp_set_rep_chr(pool, &sp2, '-', 65); ASSERT(ustrp_size_alloc(sp2) == 96); TST_MC_SET_NUM(1); ASSERT(ustrp_del(pool, &sp2, 60)); ASSERT(ustrp_size_alloc(sp2) < 96); ASSERT(!ustrp_enomem(sp2)); ASSERT(ustrp_len(sp2) == 5); ASSERT(ustrp_cmp_cstr_eq(sp2, "-----")); assert(USTR_CNTL_MALLOC_CHECK_MEM(sp2)); assert(USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(sp2, ustrp_size_alloc(sp2))); assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(sp2, 96)); /* now with exact implicit SIZE */ ustr_sc_free2(&s2, ustr_dupx_empty(0, 0, 1, 0)); ustr_set_rep_chr(&s2, '-', 65); ASSERT(ustr_size_alloc(s2) < 96); off = ustr_size_alloc(s2); TST_MC_SET_NUM(1); ASSERT(ustr_del(&s2, 60)); ASSERT(ustr_size_alloc(s2) < off); ASSERT(!ustr_enomem(s2)); ASSERT(ustr_len(s2) == 5); ASSERT(ustr_cmp_cstr_eq(s2, "-----")); assert(USTR_CNTL_MALLOC_CHECK_MEM(s2)); assert(USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(s2, ustr_size_alloc(s2))); assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(s2, ustr_size_alloc(s2))); ASSERT((sp2 = ustrp_dupx_empty(pool, 0, 0, 1, 0))); ustrp_set_rep_chr(pool, &sp2, '-', 65); ASSERT(ustrp_size_alloc(sp2) < 96); off = ustrp_size_alloc(sp2); TST_MC_SET_NUM(1); ASSERT(ustrp_del(pool, &sp2, 60)); ASSERT(ustrp_size_alloc(sp2) < off); ASSERT(!ustrp_enomem(sp2)); ASSERT(ustrp_len(sp2) == 5); ASSERT(ustrp_cmp_cstr_eq(sp2, "-----")); assert(USTR_CNTL_MALLOC_CHECK_MEM(sp2)); assert(USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(sp2, ustrp_size_alloc(sp2))); assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(sp2, off)); /* now with inexact explicit stored SIZE */ ustr_sc_free2(&s2, ustr_dupx_empty(1, 0, 0, 0)); ustr_set_rep_chr(&s2, '-', 65); ASSERT(ustr_size_alloc(s2) == 96); TST_MC_SET_NUM(1); ASSERT(ustr_del(&s2, 60)); ASSERT(ustr_size_alloc(s2) == 96); ASSERT(!ustr_enomem(s2)); ASSERT(ustr_len(s2) == 5); ASSERT(ustr_cmp_cstr_eq(s2, "-----")); assert(USTR_CNTL_MALLOC_CHECK_MEM(s2)); assert(USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(s2, ustr_size_alloc(s2))); assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(s2, ustr_size_alloc(s2))); TST_MC_SET_NUM(0); ASSERT((sp2 = ustrp_dupx_empty(pool, 1, 0, 0, 0))); ustrp_set_rep_chr(pool, &sp2, '-', 65); ASSERT(ustrp_size_alloc(sp2) == 96); TST_MC_SET_NUM(1); ASSERT(ustrp_del(pool, &sp2, 60)); ASSERT(ustrp_size_alloc(sp2) == 96); ASSERT(!ustrp_enomem(sp2)); ASSERT(ustrp_len(sp2) == 5); ASSERT(ustrp_cmp_cstr_eq(sp2, "-----")); assert(USTR_CNTL_MALLOC_CHECK_MEM(sp2)); assert(USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(sp2, ustrp_size_alloc(sp2))); assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(sp2, ustrp_size_alloc(sp2))); ustr_pool_free(pool); TST_MC_SET_NUM(0); errno = 0; ustr_sc_free2(&s1, USTR("")); ASSERT(ustr_add(&s1, USTR1(\1, "a"))); ASSERT(ustr_add(&s1, USTR1(\1, "d"))); ASSERT_EQ(s1, USTR1(\2, "ad")); TST_MC_SET_NUM(1); errno = 0; ASSERT(!ustr_ins(&s1, 1, s1)); ASSERT(errno == ENOMEM); ASSERT_EQ(s1, USTR1(\2, "ad")); TST_MC_SET_NUM(2); errno = 0; ASSERT( ustr_ins(&s1, 1, s1)); ASSERT_EQ(s1, USTR1(\4, "aadd")); TST_MC_SET_NUM(0); errno = 0; ASSERT(ustr_set_cstr(&s1, "1234567")); ASSERT_EQ(s1, USTR1(\7, "1234567")); TST_MC_SET_NUM(1); errno = 0; ASSERT(!ustr_ins_subustr(&s1, 2, s1, 2, 5)); ASSERT(errno == ENOMEM); ASSERT_EQ(s1, USTR1(\7, "1234567")); TST_MC_SET_NUM(2); errno = 0; ASSERT( ustr_ins_subustr(&s1, 2, s1, 2, 5)); ASSERT_EQ(s1, USTR1(\xC, "122345634567")); TST_MC_SET_NUM(0); errno = 0; ustr_free(s1); TST_MC_SET_NUM(1); errno = 0; ASSERT(!(s1 = ustr_sc_concat(USTR1(\2, "ab"), USTR1(\2, "cd"), USTR_NULL))); ASSERT(errno == ENOMEM); #if USTR_CONF_HAVE_VA_COPY TST_MC_SET_NUM(2); errno = 0; ASSERT( (s1 = ustr_sc_concat(USTR1(\2, "ab"), USTR1(\2, "cd"), USTR_NULL))); ASSERT_EQ(s1, USTR1(\4, "abcd")); #endif TST_MC_SET_NUM(0); errno = 0; ASSERT(ustr_owner(s1)); ustr_free(s1); TST_MC_SET_NUM(1); errno = 0; ASSERT(!(s1 = ustr_sc_join(USTR1(\1, ","), USTR1(\1, "1"), USTR(""), USTR(""), USTR1(\1, "4"), USTR1(\1, "5"), USTR_NULL))); ASSERT(errno == ENOMEM); #if USTR_CONF_HAVE_VA_COPY TST_MC_SET_NUM(2); errno = 0; ASSERT( (s1 = ustr_sc_join(USTR1(\1, ","), USTR1(\1, "1"), USTR(""), USTR(""), USTR1(\1, "4"), USTR1(\1, "5"), USTR_NULL))); ASSERT_EQ(s1, USTR1(\7, "1,,,4,5")); #endif TST_MC_SET_NUM(0); errno = 0; ASSERT(ustr_owner(s1)); TST_MC_SET_NUM(1); errno = 0; ASSERT(!ustr_sc_sub_subustr(&s1, 3, 3, s1, 5, 1)); ASSERT(errno == ENOMEM); ASSERT_EQ(s1, USTR1(\7, "1,,,4,5")); TST_MC_SET_NUM(2); errno = 0; ASSERT( ustr_sc_sub_subustr(&s1, 3, 3, s1, 5, 1)); ASSERT_EQ(s1, USTR1(\5, "1,4,5")); TST_MC_SET_NUM(0); errno = 0; ASSERT(ustr_add_rep_chr(&s1, '-', 2)); ASSERT(ustr_ins_rep_chr(&s1, 0, '-', 2)); ASSERT_EQ(s1, USTR1(\x9, "--1,4,5--")); TST_MC_SET_NUM(1); errno = 0; ASSERT(!ustr_sc_sub(&s1, 5, 1, s1)); ASSERT(errno == ENOMEM); ASSERT_EQ(s1, USTR1(\x9, "--1,4,5--")); TST_MC_SET_NUM(2); errno = 0; ASSERT( ustr_sc_sub(&s1, 5, 1, s1)); ASSERT_EQ(s1, USTR1(\x11, "--1,--1,4,5--,5--")); TST_MC_SET_NUM(0); errno = 0; TST_MC_SET_NUM(1); errno = 0; ASSERT(!ustr_sub_subustr(&s1, 5, s1, 9, 5)); ASSERT_EQ(s1, USTR1(\x11, "--1,--1,4,5--,5--")); ASSERT( ustr_sub_subustr(&s1, 5, s1, 9, 5)); ASSERT_EQ(s1, USTR1(\x11, "--1,4,5--,5--,5--")); TST_MC_SET_NUM(1); errno = 0; ASSERT(!ustr_sub_subustr(&s1, 17, s1, 2, 16)); ASSERT_EQ(s1, USTR1(\x11, "--1,4,5--,5--,5--")); TST_MC_SET_NUM(2); errno = 0; ASSERT(!ustr_sub_subustr(&s1, 17, s1, 2, 16)); ASSERT_EQ(s1, USTR1(\x11, "--1,4,5--,5--,5--")); TST_MC_SET_NUM(3); errno = 0; ASSERT( ustr_sub_subustr(&s1, 17, s1, 2, 16)); ASSERT_EQ(s1, USTR1(\x20, "--1,4,5--,5--,5--1,4,5--,5--,5--")); TST_MC_SET_NUM(0); errno = 0; return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_10_b.c0000644000076400007640000000472710704211526013636 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { Ustr_pool *pool = ustr_pool_ll_make(); Ustrp *sp1 = USTRP(""); unsigned int u16[9] = { 0, 1, 2, 3, 0x00FF, 0x0F0F, 0xF0F0, 0xFF00, 0xFFFF}; unsigned int u32[9] = { 0x12345678U, 0x87654321U, 0x01234567U, 0x76543210U, 0xFF00FF00U, 0xF0F0F0F0U, 0x0F0F0F0FU, 0x00FF00FFU, 0xFFFFFFFFU }; unsigned long long u64[7] = { 0x0123456789abcdefULL, 0xfedcba9876543210ULL, 0x00FF00FF00FF00FFULL, 0xFF00FF00FF00FF00ULL, 0x0F0F0F0F0F0F0F0FULL, 0xF0F0F0F0F0F0F0F0ULL, 0xFFFFFFFFFFFFFFFFULL }; size_t num = 0; size_t off = 0; num = 0; while (num < 9) { ustr_add_b_uint16(&s1, u16[num]); ustrp_add_b_uint16(pool, &sp1, u16[num]); ustr_add_b_uint32(&s1, u16[num]); ustrp_add_b_uint32(pool, &sp1, u16[num]); ustr_add_b_uint64(&s1, u16[num]); ustrp_add_b_uint64(pool, &sp1, u16[num]); ++num; } num = 0; while (num < 9) { ustr_add_b_uint32(&s1, u32[num]); ustrp_add_b_uint32(pool, &sp1, u32[num]); ustr_add_b_uint64(&s1, u32[num]); ustrp_add_b_uint64(pool, &sp1, u32[num]); ++num; } num = 0; while (num < 7) { ustr_add_b_uint64(&s1, u64[num]); ustrp_add_b_uint64(pool, &sp1, u64[num]); ++num; } ASSERT(!ustr_enomem(s1)); ASSERT(!ustrp_enomem(sp1)); /* parse the numbers out again ... */ num = 0; off = 0; while (num < 9) { ASSERT(u16[num] == ustr_parse_b_uint16(s1, off)); ASSERT(u16[num] == ustrp_parse_b_uint16(sp1, off)); off += 2; ASSERT(u16[num] == ustr_parse_b_uint32(s1, off)); ASSERT(u16[num] == ustrp_parse_b_uint32(sp1, off)); off += 4; ASSERT(u16[num] == ustr_parse_b_uint64(s1, off)); ASSERT(u16[num] == ustrp_parse_b_uint64(sp1, off)); off += 8; ++num; } num = 0; while (num < 9) { ASSERT(u32[num] == ustr_parse_b_uint32(s1, off)); ASSERT(u32[num] == ustrp_parse_b_uint32(sp1, off)); off += 4; ASSERT(u32[num] == ustr_parse_b_uint64(s1, off)); ASSERT(u32[num] == ustrp_parse_b_uint64(sp1, off)); off += 8; ++num; } num = 0; while (num < 7) { ASSERT(u64[num] == ustr_parse_b_uint64(s1, off)); ASSERT(u64[num] == ustrp_parse_b_uint64(sp1, off)); off += 8; ++num; } ustr_pool_free(pool); return (EXIT_SUCCESS); } ustr-1.0.4/T/tst_13_utf8.c0000644000076400007640000000007210631106224014125 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 0 ustr-1.0.4/T/tst_9_ins.c0000644000076400007640000000000010646450446013762 0ustar jamesjamesustr-1.0.4/T/ctst_0_nothing.c0000644000076400007640000000006210630111754014766 0ustar jamesjames#include "ustr.h" int main(void) { return 0; } ustr-1.0.4/T/ctst_0_manual.c0000644000076400007640000000000010630111754014565 0ustar jamesjamesustr-1.0.4/T/ctst_19_join.c0000644000076400007640000000401310755655111014361 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { Ustr_pool *pool = ustr_pool_ll_make(); Ustr *tmp = ustr_sc_join(USTR(""), USTR(""), USTR(""), USTR_NULL); Ustrp *ptmp = ustrp_sc_join(pool, USTRP(""), USTRP(""),USTRP(""), USTRP_NULL); ASSERT(tmp); ASSERT(!ustr_len(tmp)); ASSERT( ustr_ro(tmp)); ASSERT(ptmp); ASSERT(!ustrp_len(ptmp)); ASSERT( ustrp_ro(ptmp)); ASSERT((ptmp = ustrp_sc_joinx(pool, 1,1,1,1, USTRP(""), USTRP(""), USTRP(""), USTRP_NULL))); ASSERT(!ustrp_len(ptmp)); ASSERT(!ustrp_ro(ptmp)); tmp = ustr_sc_join(USTR1(\1, "."), USTR1(\4, "abcd"), USTR1(\4, "/xyz"), USTR(""), USTR_NULL); ASSERT(tmp); ASSERT_EQ(tmp, USTR1(\xa, "abcd./xyz.")); ustr_free(tmp); tmp = ustr_sc_join(USTR1(\1, "."), USTR1(\4, "abcd"), USTR1(\4, "/xyz"), USTR(""), USTR1(\4, " ---"), USTR(""),USTR1(\4, "- 12"), USTR_NULL); ASSERT_EQ(tmp, USTR1(\x15, "abcd./xyz.. ---..- 12")); ustr_free(tmp); tmp = ustr_sc_joinx(1, 1, 1, 1, USTR1(\1, "."), USTR1(\4, "abcd"),USTR1(\4, "/xyz"),USTR(""), USTR_NULL); ASSERT(tmp); ASSERT(ustr_enomem(tmp)); ASSERT_EQ(tmp, USTR1(\xa, "abcd./xyz.")); ustr_free(tmp); ptmp = ustrp_sc_join(pool, USTRP1(\1, "."), USTRP(""), USTRP1(\4, "abcd"), USTRP1(\4, "/xyz"), USTRP_NULL); ASSERT(ptmp); ASSERT_PEQ(ptmp, USTRP1(\xa, ".abcd./xyz")); ptmp = ustrp_sc_join(pool, USTRP1(\1, "."), USTRP(""), USTRP1(\4, "abcd"), USTRP1(\4, "/xyz"), USTRP1(\4, " ---"), USTRP(""),USTRP1(\4, "- 12"), USTRP_NULL); ASSERT_PEQ(ptmp, USTRP1(\x15, ".abcd./xyz. ---..- 12")); ptmp = ustrp_sc_joinx(pool, 1, 1, 1, 1, USTRP1(\1, "."), USTRP(""), USTRP1(\4, "abcd"), USTRP1(\4, "/xyz"), USTRP_NULL); ASSERT(ptmp); ASSERT(ustrp_enomem(ptmp)); ASSERT_PEQ(ptmp, USTRP1(\xa, ".abcd./xyz")); ustr_pool_free(pool); return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_3_medium.c0000644000076400007640000003263310760377353014631 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; #include #if USTR_CONF_HAVE_VA_COPY static Ustr *my_dup_fmt(const char *, ...) USTR__COMPILE_ATTR_NONNULL_A() USTR__COMPILE_ATTR_FMT(1, 2); static Ustr *my_dup_fmt(const char *fmt, ...) { va_list ap; Ustr *ret = NULL; va_start(ap, fmt); ret = ustr_dupx_vfmt(0, 0, 1, 0, fmt, ap); va_end(ap); return (ret); } static int my_fmt(Ustr **, const char *, ...) USTR__COMPILE_ATTR_NONNULL_A() USTR__COMPILE_ATTR_FMT(2, 3); static int my_fmt(Ustr **ps1, const char *fmt, ...) { va_list ap; int ret = 0; va_start(ap, fmt); ret = ustr_set_vfmt(ps1, fmt, ap); va_end(ap); return (ret); } #endif static void *fail_malloc(size_t len) { (void)len; return NULL; } int tst(void) { unsigned int num = 65534; unsigned int i; struct Ustr *tmp = NULL; Ustr *s3 = USTR1(\xb, "abcd 42 xyz"); Ustr *s4 = USTR_NULL; assert(!USTR_CONF_USE_DYNAMIC_CONF || ustr_cntl_opt(USTR_CNTL_OPT_SET_REF_BYTES, 2)); if (USTR_CONF_USE_DYNAMIC_CONF) ustr_sc_free2(&s2, ustr_dup_buf(ustr_cstr(s2), ustr_len(s2))); ASSERT((s4 = ustr_dup_undef(18))); ASSERT(ustr_len(s1) == 0); ASSERT(ustr_len(s2) == strlen("s2")); ASSERT(ustr_size(s1) == 0); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size_overhead(s2) == 5); /* info[1] + ref[2] + len[1] ... NIL */ if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s2) == 3); /* ustr__ns(1 + 2 + 1 + 2 + 1) - * 1 + 2 + 1 + 1 */ if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size_overhead(s4) == 5); ustr_sc_free(&s4); ASSERT( ustr_cmp_eq(s1, s1)); ASSERT( ustr_cmp_eq(s2, s2)); ASSERT(!ustr_cmp_eq(s1, s2)); ASSERT( ustr_cmp_cstr_eq(s1, "")); ASSERT( ustr_cmp_cstr_eq(s2, "s2")); ASSERT( ustr_cmp_eq(s2, USTR1(\x0002, "s2"))); ASSERT(!ustr_cmp( s2, USTR1(\x2, "s2"))); ASSERT(!ustr_cmp_cstr_eq(s1, "s2")); ASSERT(!ustr_cmp_cstr_eq(s2, "")); ASSERT(!ustr_cmp_cstr_eq(s2, "s3")); ASSERT(!ustr_cmp_cstr_eq(s2, "s2x")); ASSERT(!ustr_cmp_buf_eq(s2, "s2", 1)); ASSERT( ustr_cmp_buf_eq(s2, "s2", 2)); ASSERT(!ustr_cmp_buf_eq(s2, "s2", 3)); ASSERT( ustr_cmp(s1, s1) == 0); ASSERT( ustr_cmp(s2, s2) == 0); ASSERT( ustr_cmp(s1, s2) < 0); ASSERT( ustr_cmp_fast(s1, s2) < 0); ASSERT( ustr_cmp(s2, s1) > 0); ASSERT( ustr_cmp_fast(s2, s1) > 0); ASSERT( ustr_cmp_cstr(s2, "s2") == 0); ASSERT( ustr_cmp_buf(s2, "s2", 2) == 0); ASSERT( ustr_srch_fwd(s1, 0, s1) == 0); ASSERT( ustr_srch_fwd(s1, 0, s2) == 0); ASSERT( ustr_srch_fwd(s2, 0, s1) == 1); ASSERT( ustr_srch_fwd(s2, 0, s2) == 1); ASSERT( ustr_srch_rev(s1, 0, s1) == 0); ASSERT( ustr_srch_rev(s1, 0, s2) == 0); ASSERT( ustr_srch_rev(s2, 0, s1) == 2); ASSERT( ustr_srch_rev(s2, 0, s2) == 1); ASSERT(!ustr_srch_cstr_fwd(s1, 0, "x")); ASSERT(!ustr_srch_cstr_fwd(s2, 0, "x")); ASSERT(!ustr_srch_cstr_fwd(s2, 0, "x")); ASSERT( ustr_srch_cstr_fwd(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_fwd(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_fwd(s2, 0, "s2") == 1); ASSERT( ustr_srch_cstr_fwd(s2, 0, "s") == 1); ASSERT( ustr_srch_cstr_fwd(s2, 0, "2") == 2); ASSERT(!ustr_srch_cstr_rev(s1, 0, "x")); ASSERT(!ustr_srch_cstr_rev(s2, 0, "x")); ASSERT(!ustr_srch_cstr_rev(s2, 0, "x")); ASSERT( ustr_srch_cstr_rev(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_rev(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_rev(s2, 0, "s2") == 1); ASSERT( ustr_srch_cstr_rev(s2, 0, "s") == 1); ASSERT( ustr_srch_cstr_rev(s2, 0, "2") == 2); ASSERT( ustr_srch_cstr_rev(s2, 1, "s") == 1); for (i = 0; i < num; ++i) { tmp = ustr_dup(s1); ASSERT(tmp == s1); tmp = ustr_dup(s2); ASSERT(tmp == s2); } ASSERT(ustr_sc_dup(&s2)); ASSERT(tmp && (tmp != s2)); ASSERT(ustr_cmp_eq(tmp, s2)); ustr_sc_free(&s2); s2 = tmp; for (i = 0; i < num; ++i) { ustr_free(s1); ustr_free(s1); ustr_free(s2); } ustr_sc_free(&s2); { struct Ustr *s99 = ustr_dup_cstr("x"); ASSERT(ustr_len(s99) == 1); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s99) == 1); ustr_sc_free(&s99); } s2 = USTR1(\x02, "xy"); ASSERT(ustr_size(s2) == 2); ASSERT(ustr_len(s2) == 2); ASSERT( ustr_ro(s2)); ASSERT( ustr_shared(s2)); ASSERT(!ustr_enomem(s2)); ASSERT(!ustr_setf_enomem_err(s2)); ASSERT(!ustr_enomem(s2)); ASSERT(!ustr_setf_enomem_clr(s2)); ASSERT(!ustr_enomem(s2)); #if USTR_CONF_HAVE_VA_COPY ASSERT((s2 = my_dup_fmt("abcd %d xyz", 42))); ASSERT(my_fmt(&s2, "abcd %.200d xyz", 42)); ASSERT(s2); ASSERT(ustr_len(s2) == 209); ASSERT(ustr_cmp_subustr_eq(USTR1(\x4, "abcd"), s2, 1, 4)); ASSERT(!ustr_cmp_subustr(USTR1(\x7, "042 xyz"), s2, ustr_len(s2) - 6, 7)); ASSERT(!ustr_setf_share(s2)); ASSERT( ustr_add_undef(&s2, 8)); ASSERT(ustr_len(s2) == (209 + 8)); ASSERT(ustr_cmp_subustr_eq(USTR1(\x4, "abcd"), s2, 1, 4)); ASSERT(!ustr_cmp_subustr(USTR1(\x7, "042 xyz"), s2, ustr_len(s2) - (6+8), 7)); ustr_sc_free2(&s2, USTR("")); ASSERT(my_fmt(&s2, "abcd %.200d xyz", 42)); ASSERT(s2); ASSERT(ustr_len(s2) == 209); ASSERT(ustr_cmp_subustr_eq(USTR1(\x4, "abcd"), s2, 1, 4)); ASSERT(!ustr_cmp_subustr(USTR1(\x7, "042 xyz"), s2, ustr_len(s2) - 6, 7)); ASSERT( ustr_setf_share(s2)); ASSERT( ustr_setf_owner(s2)); ASSERT( ustr_add(&s2, USTR(""))); #ifdef __linux__ { wchar_t *wt = (wchar_t *)"\xFF\xFF\xFF\xFF"; /* test multi-byte conversion failure */ ASSERT(!ustr_add_fmt(&s2, "%ls", wt)); ASSERT(!ustr_dup_fmt( "%ls", wt)); ASSERT(!ustr_set_fmt(&s2, "%ls", wt)); ASSERT(!ustr_ins_fmt(&s2, 1, "%ls", wt)); ASSERT(!ustr_sub_fmt(&s2, 1, "%ls", wt)); ASSERT(!ustr_sc_sub_fmt(&s2, 1, 2, "%ls", wt)); } #endif #endif ustr_sc_free2(&s2, ustr_dupx(1, 0, 0, 0, s2)); ASSERT(!ustr_exact(s2)); ASSERT(ustr_len(s2) == 209); ASSERT(ustr_size(s2) > 209); ASSERT( ustr_setf_share(s2)); ASSERT( ustr_setf_owner(s2)); ASSERT(ustr_len(s2) == 209); ASSERT(ustr_size(s2) > 209); ASSERT(!ustr_exact(s2)); ASSERT( ustr_realloc(&s2, 209)); ASSERT(ustr_len(s2) == 209); ASSERT(ustr_size(s2) == 209); ASSERT(!ustr_exact(s2)); ASSERT( ustr_realloc(&s2, 210)); ASSERT(ustr_len(s2) == 209); ASSERT(ustr_size(s2) == 210); ASSERT(!ustr_exact(s2)); ASSERT(ustr_cmp_subustr_eq(USTR1(\x4, "abcd"), s2, 1, 4)); ASSERT(!ustr_cmp_subustr(USTR1(\x7, "042 xyz"), s2, ustr_len(s2) - 6, 7)); ustr_sc_free2(&s2, USTR("")); ASSERT(ustr_sc_ensure_owner(&s2)); ustr_sc_free2(&s2, USTR("")); ASSERT(ustr_sc_wstr(&s2)); ustr_sc_free2(&s2, USTR1(\1, "1")); ASSERT(ustr_sc_wstr(&s2)); ASSERT( ustr_setf_share(USTR(""))); ASSERT(!ustr_setf_owner(USTR(""))); ASSERT(ustr_set_cstr(&s2, "abcd 42 xyz")); ASSERT(!ustr_cmp_fast_cstr(s2, "abcd 42 xyz")); ASSERT( ustr_owner(s2)); ASSERT(s3 != s2); assert_eq(s3, s2); ASSERT(ustr_set(&s3, s2)); ASSERT_EQ(s3, s2); ASSERT(s3 == s2); ASSERT(!ustr_owner(s2)); ASSERT(ustr_set_fmt(&s2, "abcd %.5000d xyz", 42)); ASSERT( ustr_owner(s2)); ASSERT((tmp = ustr_dup(s2))); ASSERT(tmp == s2); ASSERT(!ustr_owner(s2)); ASSERT(ustr_set(&tmp, s3)); assert_eq(s3, tmp); ASSERT(ustr_set_rep_chr(&tmp, 'x', 0)); ASSERT(ustr_len(tmp) == 0); ustr_free(tmp); ustr_free(s3); ASSERT(!ustr_enomem(s2)); ASSERT(ustr_setf_enomem_err(s2)); ASSERT( ustr_enomem(s2)); ASSERT(ustr_setf_enomem_clr(s2)); ASSERT(!ustr_enomem(s2)); ASSERT(!ustr_shared(s2)); ASSERT(ustr_set_fmt(&s2, "%x", 0xf0)); ASSERT( ustr_setf_share(s2)); ASSERT( ustr_shared(s2)); for (i = 0; i < 70000; ++i) { tmp = ustr_dup(s2); ASSERT(tmp == s2); } for (i = 0; i < 80000; ++i) ustr_free(s2); ASSERT( ustr_setf_owner(s2)); ASSERT(!ustr_shared(s2)); ASSERT( ustr_owner(s2)); ASSERT(tmp == s2); ASSERT( ustr_set_fmt(&s2, "%x", 0xff)); ASSERT(tmp == s2); /* realloc's down */ ASSERT(!ustr_shared(s2)); ASSERT( ustr_owner(s2)); tmp = ustr_dup(s2); ASSERT(tmp == s2); ASSERT(!ustr_shared(s2)); ASSERT(!ustr_owner(s2)); ASSERT(!ustr_owner(tmp)); ASSERT( ustr_set_fmt(&s2, "%x", 0xff)); ASSERT(tmp != s2); ASSERT(ustr_cmp_eq(tmp, s2)); ASSERT( ustr_owner(s2)); ASSERT( ustr_owner(tmp)); ustr_free(tmp); ustr_sc_free2(&s1, ustr_dupx_cstr(1, 1, 1, 1, "1234abcd")); ASSERT_EQ(s1, USTR1(\x8, "1234abcd")); ASSERT(ustr_enomem(s1)); ASSERT(ustr_sized(s1)); ASSERT(ustr_exact(s1)); ASSERT(ustr_setf_enomem_clr(s1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR1(\x8, "dcba4321")); ASSERT(ustr_del(&s1, 1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR1(\x7, "234abcd")); ASSERT(ustr_del(&s1, 1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR1(\x6, "cba432")); ASSERT(ustr_del(&s1, 1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR1(\x5, "34abc")); ASSERT(ustr_del(&s1, 1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR1(\x4, "ba43")); ASSERT(ustr_del(&s1, 1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR1(\x3, "4ab")); ASSERT(ustr_del(&s1, 1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR1(\x2, "a4")); ASSERT(ustr_del(&s1, 1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR1(\x1, "a")); ASSERT(ustr_del(&s1, 1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR("")); ASSERT(ustr_sc_reverse(&s1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT(ustr_sc_reverse(&s1)); ASSERT_EQ(s1, USTR("")); ustr_sc_free2(&s1, ustr_dupx_cstr(1, 1, 1, 1, "aBcDeFgHiJ")); ASSERT(ustr_sc_tolower(&s1)); ASSERT_EQ(s1, USTR1(\xa, "abcdefghij")); ASSERT(ustr_sc_toupper(&s1)); ASSERT_EQ(s1, USTR1(\xa, "ABCDEFGHIJ")); ustr_sc_free2(&s1, ustr_dupx_cstr(1, 1, 1, 1, "aBcDeFgHiJ")); ASSERT(ustr_sc_toupper(&s1)); ASSERT_EQ(s1, USTR1(\xa, "ABCDEFGHIJ")); ASSERT(ustr_sc_tolower(&s1)); ASSERT_EQ(s1, USTR1(\xa, "abcdefghij")); ASSERT(!ustr_srch_rep_chr_fwd(s1, 0, 'j', 2)); ASSERT(!ustr_srch_rep_chr_rev(s1, 0, 'j', 2)); ASSERT(ustr_srch_rep_chr_fwd(s1, 0, 'j', 1) == 10); ASSERT(ustr_srch_rep_chr_rev(s1, 0, 'j', 1) == 10); { size_t esz; size_t ref; int exact; size_t lenn; size_t refc; s4 = ustr_dup_cstr("x"); ustr_conf(s4, NULL,NULL,NULL, NULL,NULL); ustr_conf(s4, &esz,&ref,&exact, &lenn,&refc); ASSERT(!esz); ASSERT(ref == 2); ASSERT(!exact); ASSERT(lenn == 1); ASSERT(refc == 1); ASSERT(ustr_len(s4) == 1); if (!USTR_DEBUG) ASSERT(ustr_size(s4) == 1); ustr_sc_free(&s4); } { /* bug */ int scan = 0; Ustr *os1 = s1; while (scan++ < 65534) { s1 = ustr_dupx(1, 1, 1, 1, s1); ASSERT(s1 == os1); } ASSERT((s1 = ustr_dupx(1, 1, 1, 1, s1))); ASSERT(s1 != os1); ASSERT(s1->data[0] == os1->data[0]); ustr_sc_free2(&s1, os1); scan = 0; while (scan++ < 65534) ustr_free(s1); if (USTR_CONF_USE_DYNAMIC_CONF) { assert(ustr_cntl_opt(USTR_CNTL_OPT_SET_REF_BYTES, 0)); assert(ustr_cntl_opt(USTR_CNTL_OPT_SET_HAS_SIZE, 1)); ASSERT((os1 = ustr_dupx_undef(1, 2, 0, 0, 0))); ASSERT(ustr_ro(os1)); } } ustr_sc_free2(&s1, USTR1(\x14, "123456789912345xxxxx")); ASSERT(!ustr_srch_rep_chr_fwd(s1, 0, 'x', 6)); ASSERT(!ustr_srch_rep_chr_rev(s1, 0, 'x', 6)); ASSERT(ustr_srch_rep_chr_fwd(s1, 0, 'x', 5) == 16); ASSERT(ustr_srch_rep_chr_rev(s1, 0, 'x', 5) == 16); ASSERT(ustr_srch_rep_chr_fwd(s1, 0, 'x', 4) == 16); ASSERT(ustr_srch_rep_chr_rev(s1, 0, 'x', 4) == 17); ASSERT(ustr_srch_rep_chr_fwd(s1, 0, 'x', 3) == 16); ASSERT(ustr_srch_rep_chr_rev(s1, 0, 'x', 3) == 18); ASSERT(ustr_srch_rep_chr_fwd(s1, 0, 'x', 2) == 16); ASSERT(ustr_srch_rep_chr_rev(s1, 0, 'x', 2) == 19); ASSERT(ustr_srch_rep_chr_fwd(s1, 0, 'x', 1) == 16); ASSERT(ustr_srch_rep_chr_rev(s1, 0, 'x', 1) == 20); ASSERT(ustr_srch_rep_chr_fwd(s1, 0, '9', 2) == 9); ASSERT(ustr_srch_rep_chr_rev(s1, 0, '9', 2) == 9); ASSERT(ustr_srch_rep_chr_fwd(s1, 0, '9', 1) == 9); ASSERT(ustr_srch_rep_chr_rev(s1, 0, '9', 1) == 10); ASSERT(!ustr_srch_rep_chr_fwd(s1, 0, '5', 2)); ASSERT(!ustr_srch_rep_chr_rev(s1, 0, '5', 2)); ASSERT(ustr_srch_rep_chr_fwd(s1, 0, '5', 1) == 5); ASSERT(ustr_srch_rep_chr_rev(s1, 0, '5', 1) == 15); ASSERT(ustr_srch_rep_chr_fwd(s1, 0, '5', 0) == 1); ASSERT(ustr_srch_rep_chr_rev(s1, 0, '5', 0) == 20); { size_t scan = 0x15; char *cstr = ustr_sc_export(s1, malloc); ASSERT(cstr); ASSERT(strlen(cstr) == ustr_len(s1)); ASSERT(ustr_cmp_cstr_eq(s1, cstr)); free(cstr); while (scan--) { cstr = ustr_sc_export_subustr(s1, 1, scan, malloc); ASSERT(cstr); ASSERT(strlen(cstr) == scan); ASSERT(ustr_cmp_prefix_cstr_eq(s1, cstr)); free(cstr); } scan = 0x14; while (scan--) { cstr = ustr_sc_export_subustr(s1, scan + 1, ustr_len(s1) - scan, malloc); ASSERT(cstr); ASSERT(strlen(cstr) == ustr_len(s1) - scan); ASSERT(ustr_cmp_suffix_cstr_eq(s1, cstr)); free(cstr); } cstr = ustr_sc_export_subustr(s1, 4, 3, malloc); ASSERT(cstr); ASSERT(strlen(cstr) == 3); ASSERT(ustr_cmp_cstr_eq(USTR1(\3, "456"), cstr)); free(cstr); cstr = ustr_sc_export_subustr(s1, 4, 0, malloc); ASSERT(cstr); ASSERT(strlen(cstr) == 0); free(cstr); if (!USTR_DEBUG) ASSERT(!ustr_sc_export_subustr(s1, 1, 0x15, malloc)); if (!USTR_DEBUG) ASSERT(!ustr_sc_export_subustr(s1, 2, 0x14, malloc)); } ASSERT(!ustr_sc_export(s1, fail_malloc)); ASSERT(!ustr_sc_export_subustr(s1, 1, 4, fail_malloc)); return (EXIT_SUCCESS); } ustr-1.0.4/T/tst_0_sizes.c0000644000076400007640000000460210644621031014315 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; /* this doesn't really tes the SS API, just the allocating sizes */ int tst(void) { static const size_t ans[] = { 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512}; static const size_t ohoff = 2; /* 1 + x + y + z + 1, x == ref_bytes, y = len bytes, z = len */ size_t num = 0; /* ref_bytes = 0 */ ASSERT(ustr__ns(ohoff + 0 + 1 + 1) == ans[0]); ASSERT(ustr__ns(ohoff + 1 + 2) == ans[1]); ASSERT(ustr__ns(ohoff + 1 + 3) == ans[1]); ASSERT(ustr__ns(ohoff + 1 + 4) == ans[2]); ASSERT(ustr__ns(ohoff + 1 + 5) == ans[2]); ASSERT(ustr__ns(ohoff + 1 + 6) == ans[3]); ASSERT(ustr__ns(ohoff + 1 + 7) == ans[3]); ASSERT(ustr__ns(ohoff + 1 + 8) == ans[3]); ASSERT(ustr__ns(ohoff + 1 + 9) == ans[3]); ASSERT(ustr__ns(ohoff + 1 + 10) == ans[4]); ASSERT(ustr__ns(ohoff + 1 + 11) == ans[4]); ASSERT(ustr__ns(ohoff + 1 + 12) == ans[4]); ASSERT(ustr__ns(ohoff + 1 + 13) == ans[4]); ASSERT(ustr__ns(ohoff + 1 + 14) == ans[5]); ASSERT(ustr__ns(ohoff + 1 + 15) == ans[5]); ASSERT(ustr__ns(ohoff + 2 + 16) == ans[5]); ASSERT(ustr__ns(ohoff + 2 + 17) == ans[5]); ASSERT(ustr__ns(ohoff + 2 + 18) == ans[5]); ASSERT(ustr__ns(ohoff + 2 + 19) == ans[5]); ASSERT(ustr__ns(ohoff + 2 + 20) == ans[5]); for (num = 21; num < 29; ++num) ASSERT(ustr__ns(ohoff + 2 + num) == ans[6]); for (num = 29; num < 45; ++num) ASSERT(ustr__ns(ohoff + 2 + num) == ans[7]); for (num = 45; num < 61; ++num) ASSERT(ustr__ns(ohoff + 2 + num) == ans[8]); for (num = 61; num < 93; ++num) ASSERT(ustr__ns(ohoff + 2 + num) == ans[9]); for (num = 93; num < 125; ++num) ASSERT(ustr__ns(ohoff + 2 + num) == ans[10]); ASSERT(ustr__ns(SIZE_MAX - (SIZE_MAX / 8)) == SIZE_MAX); assert(USTR_SIZE_FIXED(0) == (7 + sizeof(USTR_END_CONSTx))); ASSERT(ustr_size_overhead(USTR("")) == 1); ASSERT(ustr_size_alloc(USTR("")) == 1); ASSERT(ustr_size(USTR("")) == 0); ASSERT(ustr_size_overhead(USTR1(\0, "")) >= 3); ASSERT(ustr_size_alloc(USTR1(\0, "")) >= 3); ASSERT(ustr_size(USTR1(\0, "")) == 0); ASSERT(ustr_size_overhead(USTR1(\1, "a")) >= 3); ASSERT(ustr_size_alloc(USTR1(\1, "a")) >= 4); ASSERT(ustr_size(USTR1(\1, "a")) == 1); return (EXIT_SUCCESS); } ustr-1.0.4/T/tst_99_64bit.c0000644000076400007640000000015310645605042014214 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 0 #define ustr_cntl_opt(x, y) 0 /* return FALSE */ ustr-1.0.4/T/tst_0_cntl.c0000644000076400007640000000000010651670474014121 0ustar jamesjamesustr-1.0.4/T/tst_11_io.c0000644000076400007640000000007210630111754013647 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 0 ustr-1.0.4/T/ctst_15_trim.c0000644000076400007640000000610210725564416014376 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { Ustr_pool *pool = ustr_pool_ll_make(); Ustrp *sp1 = USTRP(""); s1 = USTR1_CHK(\6, " \ns1\f "); ASSERT(ustr_sc_trim(&s1, USTR1_CHK(\2, "\t "))); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_rtrim_cstr(&s1, "\n")); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_ltrim_cstr(&s1, "\f")); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_trim_chrs(&s1, "\n\f", 0)); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_ltrim_chrs(&s1, "\n\f", 0)); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_ltrim_cstr(&s1, "")); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_ltrim(&s1, USTR1(\2, "\f "))); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_ltrim(&s1, USTR(""))); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_rtrim_chrs(&s1, "\n\f", 0)); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_rtrim_cstr(&s1, "")); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_rtrim(&s1, USTR1(\2, "\n "))); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_rtrim(&s1, USTR(""))); ASSERT_EQ(s1, USTR1(\4, "\ns1\f")); ASSERT(ustr_sc_trim_chrs(&s1, "\n\f", 1)); ASSERT_EQ(s1, USTR1(\3, "s1\f")); ASSERT(ustr_sc_trim_chrs(&s1, "\n\f", 2)); ASSERT_EQ(s1, USTR1(\2, "s1")); ASSERT(ustr_sc_trim_cstr(&s1, " s 1 ")); ASSERT_EQ(s1, USTR("")); sp1 = USTRP1_CHK(\5, " s1\t "); ASSERT(ustrp_sc_trim(pool, &sp1, USTRP1_CHK(\2, "\t "))); ASSERT_PEQ(sp1, USTRP1(\2, "s1")); sp1 = USTRP1_CHK(\7, " \nsp1\f "); ASSERT(ustrp_sc_trim(pool, &sp1, USTRP1_CHK(\2, "\t "))); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_rtrim_cstr(pool, &sp1, "\n")); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_ltrim_cstr(pool, &sp1, "\f")); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_trim_chrs(pool, &sp1, "\n\f", 0)); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_ltrim_chrs(pool, &sp1, "\n\f", 0)); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_ltrim_cstr(pool, &sp1, "")); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_ltrim(pool, &sp1, USTRP1(\2, "\f "))); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_ltrim(pool, &sp1, USTRP(""))); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_rtrim_chrs(pool, &sp1, "\n\f", 0)); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_rtrim_cstr(pool, &sp1, "")); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_rtrim(pool, &sp1, USTRP1(\2, "\n "))); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_rtrim(pool, &sp1, USTRP(""))); ASSERT_PEQ(sp1, USTRP1(\5, "\nsp1\f")); ASSERT(ustrp_sc_trim_chrs(pool, &sp1, "\n\f", 1)); ASSERT_PEQ(sp1, USTRP1(\4, "sp1\f")); ASSERT(ustrp_sc_trim_chrs(pool, &sp1, "\n\f", 2)); ASSERT_PEQ(sp1, USTRP1(\3, "sp1")); ASSERT(ustrp_sc_trim_cstr(pool, &sp1, " s 1 p ")); ASSERT_PEQ(sp1, USTRP("")); sp1 = USTRP1_CHK(\7, " \nsp1\f "); ASSERT(ustrp_sc_trim_cstr(pool, &sp1, " s 1 p \f \n ")); ASSERT_PEQ(sp1, USTRP("")); ustr_pool_free(pool); return (EXIT_SUCCESS); } ustr-1.0.4/T/tst_98_pool.c0000644000076400007640000000013310630111754014226 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 2 #define USTR_CONF_USE_EOS_MARK 0 ustr-1.0.4/T/tst_10_b.c0000644000076400007640000000007210630111754013460 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 0 ustr-1.0.4/T/ctst_2_small.c0000644000076400007640000000000010630111754014422 0ustar jamesjamesustr-1.0.4/T/ctst_13_utf8.c0000644000076400007640000003360510760402207014303 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { Ustr_pool *pool = ustr_pool_ll_make(); Ustrp *sp1 = USTRP1(\x3, "\xE2\x80\xA0"); Ustrp *sp2 = USTRP1(\x3, "†"); size_t c2b_pos = 1; ASSERT_PEQ(sp1, sp2); ASSERT( ustrp_utf8_valid(sp1)); ASSERT(ustrp_len(sp2) == 3); ASSERT(ustrp_utf8_len(sp2) == 1); ASSERT(ustrp_utf8_width(sp2) == 1); s1 = USTR(""); ASSERT( ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 0); ASSERT(ustr_utf8_len(s1) == 0); ASSERT(ustr_utf8_width(s1) == 0); ASSERT(ustr_utf8_chars2bytes(s1, 1, 0, &c2b_pos) == 0); ASSERT(c2b_pos == 0); ASSERT(ustr_utf8_bytes2chars(s1, 1, 0, &c2b_pos) == 0); ASSERT(c2b_pos == 0); s1 = USTR1(\x5, "ab\0xy"); ASSERT(!ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 5); ASSERT(ustr_utf8_width(s1) == 0); ASSERT(ustr_utf8_len(s1) == 2); ASSERT(ustr_utf8_chars2bytes(s1, 1, 5, NULL) == 0); ASSERT(c2b_pos == 0); ASSERT(ustr_utf8_bytes2chars(s1, 1, 5, NULL) == 5); ASSERT(c2b_pos == 0); s1 = USTR1(\x2, "ab"); ASSERT( ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 2); ASSERT(ustr_utf8_len(s1) == 2); ASSERT(ustr_utf8_width(s1) == 2); ASSERT(ustr_utf8_chars2bytes(s1, 1, 2, NULL) == 2); ASSERT(c2b_pos == 0); ASSERT(ustr_utf8_bytes2chars(s1, 1, 2, NULL) == 2); ASSERT(c2b_pos == 0); ASSERT(ustr_utf8_chars2bytes(s1, 1, 0, &c2b_pos) == 1); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_bytes2chars(s1, 1, 0, &c2b_pos) == 0); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_chars2bytes(s1, 2, 0, &c2b_pos) == 1); ASSERT(c2b_pos == 2); ASSERT(ustr_utf8_bytes2chars(s1, 2, 0, &c2b_pos) == 0); ASSERT(c2b_pos == 2); s1 = USTR1(\x1, "\x90"); ASSERT(!ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 1); ASSERT(ustr_utf8_width(s1) == 0); ASSERT(ustr_utf8_len(s1) == 0); ASSERT(ustr_utf8_chars2bytes(s1, 1, 1, &c2b_pos) == 1); ASSERT(c2b_pos == 1); s1 = USTR1(\x1, "\b"); ASSERT( ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 1); ASSERT(ustr_utf8_len(s1) == 1); ASSERT(ustr_utf8_width(s1) == -1); ASSERT(ustr_utf8_chars2bytes(s1, 1, 1, &c2b_pos) == 1); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_bytes2chars(s1, 1, 1, &c2b_pos) == 1); ASSERT(c2b_pos == 1); s1 = USTR1(\x2, "\xc2\x80"); ASSERT( ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 2); ASSERT(ustr_utf8_len(s1) == 1); ASSERT(ustr_utf8_width(s1) == -1); ASSERT(ustr_utf8_chars2bytes(s1, 1, 1, &c2b_pos) == 2); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_bytes2chars(s1, 1, 2, &c2b_pos) == 1); ASSERT(c2b_pos == 1); s1 = USTR1(\x2, "\xca\x80"); ASSERT( ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 2); ASSERT(ustr_utf8_len(s1) == 1); ASSERT(ustr_utf8_width(s1) == 1); ASSERT(ustr_utf8_chars2bytes(s1, 1, 1, &c2b_pos) == 2); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_bytes2chars(s1, 1, 2, &c2b_pos) == 1); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_chars2bytes(s1, 1, 0, &c2b_pos) == 2); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_bytes2chars(s1, 1, 0, &c2b_pos) == 0); ASSERT(c2b_pos == 1); s1 = USTR1(\x2, "\xcd\x80"); ASSERT( ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 2); ASSERT(ustr_utf8_len(s1) == 1); ASSERT(ustr_utf8_width(s1) == 0); ASSERT(ustr_utf8_chars2bytes(s1, 1, 1, &c2b_pos) == 2); ASSERT(c2b_pos == 1); s1 = USTR1(\x3, "\xe1\x83\x8c"); ASSERT( ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 3); ASSERT(ustr_utf8_len(s1) == 1); ASSERT(ustr_utf8_width(s1) == 1); ASSERT(ustr_utf8_chars2bytes(s1, 1, 1, &c2b_pos) == 3); ASSERT(c2b_pos == 1); s1 = USTR1(\x4, "\xf1\x83\x8c\x89"); ASSERT( ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 4); ASSERT(ustr_utf8_len(s1) == 1); ASSERT(ustr_utf8_width(s1) == 1); ASSERT(ustr_utf8_chars2bytes(s1, 1, 1, &c2b_pos) == 4); ASSERT(c2b_pos == 1); /* chars2bytes */ s1 = USTR1(\xa, "a\xca\x80\xe1\x83\x8c\xf1\x83\x8c\x89"); ASSERT( ustr_utf8_valid(s1)); ASSERT(ustr_len(s1) == 10); ASSERT(ustr_utf8_len(s1) == 4); ASSERT(ustr_utf8_width(s1) == 4); ASSERT(ustr_utf8_chars2bytes(s1, 1, 4, &c2b_pos) == 10); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_bytes2chars(s1, 1, 10, &c2b_pos) == 4); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_chars2bytes(s1, 1, 3, &c2b_pos) == 6); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_bytes2chars(s1, 1, 6, &c2b_pos) == 3); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_chars2bytes(s1, 1, 2, &c2b_pos) == 3); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_bytes2chars(s1, 1, 3, &c2b_pos) == 2); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_chars2bytes(s1, 1, 1, &c2b_pos) == 1); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_bytes2chars(s1, 1, 1, &c2b_pos) == 1); ASSERT(c2b_pos == 1); ASSERT(ustr_utf8_chars2bytes(s1, 2, 3, &c2b_pos) == 9); ASSERT(c2b_pos == 2); ASSERT(ustr_utf8_bytes2chars(s1, 2, 9, &c2b_pos) == 3); ASSERT(c2b_pos == 2); ASSERT(ustr_utf8_chars2bytes(s1, 2, 2, &c2b_pos) == 5); ASSERT(c2b_pos == 2); ASSERT(ustr_utf8_bytes2chars(s1, 2, 9, &c2b_pos) == 3); ASSERT(c2b_pos == 2); ASSERT(ustr_utf8_chars2bytes(s1, 2, 1, &c2b_pos) == 2); ASSERT(c2b_pos == 2); ASSERT(ustr_utf8_bytes2chars(s1, 2, 2, &c2b_pos) == 1); ASSERT(c2b_pos == 2); ASSERT(ustr_utf8_chars2bytes(s1, 3, 2, &c2b_pos) == 7); ASSERT(c2b_pos == 4); ASSERT(ustr_utf8_bytes2chars(s1, 4, 7, &c2b_pos) == 2); ASSERT(c2b_pos == 3); ASSERT(ustr_utf8_chars2bytes(s1, 3, 1, &c2b_pos) == 3); ASSERT(c2b_pos == 4); ASSERT(ustr_utf8_bytes2chars(s1, 4, 3, &c2b_pos) == 1); ASSERT(c2b_pos == 3); ASSERT(ustr_utf8_chars2bytes(s1, 4, 1, &c2b_pos) == 4); ASSERT(c2b_pos == 7); ASSERT(ustr_utf8_bytes2chars(s1, 7, 4, &c2b_pos) == 1); ASSERT(c2b_pos == 4); sp1 = USTRP1(\x2, "-\x90"); ASSERT(!ustrp_utf8_valid(sp1)); ASSERT(ustrp_len(sp1) == 2); ASSERT(ustrp_utf8_width(sp1) == 0); ASSERT(ustrp_utf8_len(sp1) == 1); ASSERT(ustrp_utf8_chars2bytes(sp1, 1, 2, &c2b_pos) == 0); ASSERT(c2b_pos == 4); ASSERT(ustrp_utf8_chars2bytes(sp1, 1, 1, &c2b_pos) == 2); ASSERT(c2b_pos == 1); sp1 = USTRP1(\x1e,"\xc2\xa0\xc2\xa1\xc2\xa2\xc2\xa3\xc2\xa4\xc2\xa5\xc2\xa6" "\xc2\xa7\xc2\xa8\xc2\xa9\xc2\xaa\xc2\xab\xc2\xac\xc2\xad" "\xc2\xae"); sp2 = USTRP1(\x1e," ¡¢£¤¥¦§¨©ª«¬­®"); ASSERT( ustrp_utf8_valid(sp1)); ASSERT( ustrp_utf8_valid(sp2)); ASSERT(ustrp_len(sp1) == 0x1e); ASSERT(ustrp_utf8_len(sp1) == 15); ASSERT_PEQ(sp1, sp2); ASSERT(ustrp_utf8_chars2bytes(sp1, 1, 15, &c2b_pos) == 0x1e); ASSERT(c2b_pos == 1); ASSERT(ustrp_utf8_bytes2chars(sp1, 1, 0x1e, &c2b_pos) == 15); ASSERT(c2b_pos == 1); ASSERT(ustrp_utf8_chars2bytes(sp1, 4, 4, &c2b_pos) == 8); ASSERT(c2b_pos == 7); ASSERT(ustrp_utf8_bytes2chars(sp1, 7, 8, &c2b_pos) == 4); ASSERT(c2b_pos == 4); ASSERT_PEQ(sp2, USTRP1(\x1e," ¡¢£¤¥¦§¨©ª«¬­®")); ASSERT(ustrp_sc_utf8_reverse(pool, &sp2)); ASSERT_PEQ(sp2, USTRP1(\x1e,"®­¬«ª©¨§¦¥¤£¢¡ ")); ASSERT(ustrp_sc_utf8_reverse(pool, &sp2)); ASSERT_PEQ(sp2, USTRP1(\x1e," ¡¢£¤¥¦§¨©ª«¬­®")); ASSERT(ustrp_spn_cstr_fwd(sp2, 0, " ¡¢ãäåæçèé") == 21); ASSERT(ustrp_spn_cstr_fwd(sp2, 0, "ãäåæçèéàáâµ") == 21); ASSERT(ustrp_utf8_spn_cstr_fwd(sp2, 0, "ãäåæçèé ¡¢") == 3); ASSERT(ustrp_utf8_spn_cstr_rev(sp2, 0, "ãäåæçèé ¡¢") == 0); ASSERT(ustrp_utf8_spn_cstr_rev(sp2, 0, "ãä嬭®æçèé ¡¢") == 3); ASSERT(ustrp_utf8_spn_fwd(sp2, 0, USTRP1(\xa, " ¡¢ãäåæçèé")) == 3); ASSERT(ustrp_utf8_spn_rev(sp2, 0, USTRP1(\x14, "¡¢ãäåæçèé ")) == 0); ASSERT(ustrp_utf8_spn_rev(sp2, 0, USTRP1(\x1a, "¡¢ãä嬭®æçèé ")) == 3); ASSERT(ustrp_cspn_cstr_fwd(sp2, 0, "àáâãäåæçèé") == 1); ASSERT(ustrp_cspn_cstr_fwd(sp2, 0, "àáâãäåæçèéµ") == 0); ASSERT(ustrp_cspn_cstr_rev(sp2, 0, "àáâãäåæçèéµ") == 1); ASSERT(ustrp_cspn_cstr_rev(sp2, 0, "àáâãäåæçèéµî") == 0); ASSERT(ustrp_utf8_cspn_fwd(sp2, 0, USTRP1(\xb, "àáâãäåæçèéµ")) == 15); ASSERT(ustrp_utf8_cspn_rev(sp2, 0, USTRP1(\xb, "àáâãäåæçèéµ")) == 15); ASSERT(ustrp_utf8_cspn_cstr_fwd(sp2, 0, "©®¢") == 2); ASSERT(ustrp_utf8_cspn_cstr_fwd(sp2, 0, "¢©®") == 2); ASSERT(ustrp_utf8_cspn_cstr_rev(sp2, 0, "©¢®") == 0); ASSERT(ustrp_utf8_cspn_cstr_rev(sp2, 0, "©¢") == 5); ASSERT(ustrp_utf8_spn_cstr_fwd(sp2, 1, "ãäåæçèé ¡¢") == 2); ASSERT(ustrp_utf8_spn_cstr_fwd(sp2, 2, "ãäåæçèé ¡¢") == 1); ASSERT(ustrp_utf8_spn_cstr_fwd(sp2, 3, "ãäåæçèé ¡¢") == 0); ASSERT(ustrp_utf8_spn_rev(sp2, 1, USTRP1(\x1a, "¡¢ãä嬭®æçèé ")) == 2); ASSERT(ustrp_utf8_spn_rev(sp2, 2, USTRP1(\x1a, "¡¢ãä嬭®æçèé ")) == 1); ASSERT(ustrp_utf8_spn_rev(sp2, 3, USTRP1(\x1a, "¡¢ãä嬭®æçèé ")) == 0); ASSERT(ustrp_utf8_cspn_fwd(sp2, 0, USTRP1(\xb, "àáâãäåæçèéµ")) == 15); ASSERT(ustrp_utf8_cspn_fwd(sp2, 1, USTRP1(\xb, "àáâãäåæçèéµ")) == 14); ASSERT(ustrp_utf8_cspn_fwd(sp2, 2, USTRP1(\xb, "àáâãäåæçèéµ")) == 13); ASSERT(ustrp_utf8_cspn_fwd(sp2, 3, USTRP1(\xb, "àáâãäåæçèéµ")) == 12); ASSERT(ustrp_utf8_cspn_fwd(sp2, 4, USTRP1(\xb, "àáâãäåæçèéµ")) == 11); ASSERT(ustrp_utf8_cspn_fwd(sp2, 5, USTRP1(\xb, "àáâãäåæçèéµ")) == 10); ASSERT(ustrp_utf8_cspn_fwd(sp2, 6, USTRP1(\xb, "àáâãäåæçèéµ")) == 9); ASSERT(ustrp_utf8_cspn_fwd(sp2, 7, USTRP1(\xb, "àáâãäåæçèéµ")) == 8); ASSERT(ustrp_utf8_cspn_fwd(sp2, 8, USTRP1(\xb, "àáâãäåæçèéµ")) == 7); ASSERT(ustrp_utf8_cspn_fwd(sp2, 9, USTRP1(\xb, "àáâãäåæçèéµ")) == 6); ASSERT(ustrp_utf8_cspn_rev(sp2, 0, USTRP1(\xb, "àáâãäåæçèéµ")) == 15); ASSERT(ustrp_utf8_cspn_rev(sp2, 1, USTRP1(\xb, "àáâãäåæçèéµ")) == 14); ASSERT(ustrp_utf8_cspn_rev(sp2, 2, USTRP1(\xb, "àáâãäåæçèéµ")) == 13); ASSERT(ustrp_utf8_cspn_rev(sp2, 3, USTRP1(\xb, "àáâãäåæçèéµ")) == 12); ASSERT(ustrp_utf8_cspn_rev(sp2, 4, USTRP1(\xb, "àáâãäåæçèéµ")) == 11); ASSERT(ustrp_utf8_cspn_rev(sp2, 5, USTRP1(\xb, "àáâãäåæçèéµ")) == 10); ASSERT(ustrp_utf8_cspn_rev(sp2, 6, USTRP1(\xb, "àáâãäåæçèéµ")) == 9); ASSERT(ustrp_utf8_cspn_rev(sp2, 7, USTRP1(\xb, "àáâãäåæçèéµ")) == 8); ASSERT(ustrp_utf8_cspn_rev(sp2, 8, USTRP1(\xb, "àáâãäåæçèéµ")) == 7); ASSERT(ustrp_utf8_cspn_rev(sp2, 9, USTRP1(\xb, "àáâãäåæçèéµ")) == 6); ASSERT(ustr_utf8_spn_cstr_fwd(&sp2->s, 0, "ãäåæçèé ¡¢") == 3); ASSERT(ustr_utf8_spn_cstr_rev(&sp2->s, 0, "ãäåæçèé ¡¢") == 0); ASSERT(ustr_utf8_spn_cstr_rev(&sp2->s, 0, "ãä嬭®æçèé ¡¢") == 3); ASSERT(ustr_utf8_cspn_cstr_fwd(&sp2->s, 0, "©®¢") == 2); ASSERT(ustr_utf8_cspn_cstr_fwd(&sp2->s, 0, "¢©®") == 2); ASSERT(ustr_utf8_cspn_cstr_rev(&sp2->s, 0, "©¢®") == 0); ASSERT(ustr_utf8_cspn_cstr_rev(&sp2->s, 0, "©¢") == 5); ASSERT(ustr_srch_cstr_fwd(&sp2->s, 0, "¢") == 5); ASSERT(ustr_srch_cstr_rev(&sp2->s, 0, "¢") == 5); ASSERT(ustr_srch_subustr_fwd(&sp2->s, 0, USTR1(\x4, "¢£"), 1, 4) == 5); ASSERT(ustr_srch_subustr_fwd(&sp2->s, 0, USTR1(\x4, "¡¢"), 1, 4) == 3); ASSERT(ustr_srch_subustr_rev(&sp2->s, 0, USTR1(\x4, "¢£"), 1, 4) == 5); ASSERT(ustr_srch_subustr_rev(&sp2->s, 0, USTR1(\x4, "¡¢"), 1, 4) == 3); ASSERT(ustr_srch_subustr_fwd(&sp2->s, 0, USTR1(\x4, "¢©"), 3, 2) == 19); ASSERT(ustr_srch_subustr_fwd(&sp2->s, 0, USTR1(\x4, "©¢"), 1, 2) == 19); ASSERT(ustr_srch_subustr_rev(&sp2->s, 0, USTR1(\x4, "¢©"), 3, 2) == 19); ASSERT(ustr_srch_subustr_rev(&sp2->s, 0, USTR1(\x4, "©¢"), 1, 2) == 19); ASSERT(ustr_srch_subustr_fwd(&sp2->s, 0, USTR1(\x4, "¢©"), 1, 2) == 5); ASSERT(ustr_srch_subustr_fwd(&sp2->s, 0, USTR1(\x4, "©¢"), 3, 2) == 5); ASSERT(ustr_srch_subustr_rev(&sp2->s, 0, USTR1(\x4, "¢©"), 1, 2) == 5); ASSERT(ustr_srch_subustr_rev(&sp2->s, 0, USTR1(\x4, "©¢"), 3, 2) == 5); if (!USTR_DEBUG) { ASSERT(ustr_srch_subustr_fwd(&sp2->s, 0, USTR1(\x4, "©¢"), 3, 8) == 1); ASSERT(ustr_srch_subustr_rev(&sp2->s, 0, USTR1(\x4, "¢©"), 1, 8) == 0x1e); } /* hack ... invalid utf-8 cstr, ask to go backwards */ ASSERT(ustr_utf8_cspn_cstr_fwd(USTR1(\x4, "\x80\x80\x80\x80"), 0, "©¢") == 1); ASSERT(ustr_utf8_cspn_cstr_rev(USTR1(\x4, "\x80\x80\x80\x80"), 0, "©¢") == 0); ASSERT(ustr_utf8_cspn_cstr_fwd(USTR1(\x5, ".\x80\x80\x80\x80"),0, "©¢") == 1); ASSERT(ustr_utf8_cspn_cstr_rev(USTR1(\x5, ".\x80\x80\x80\x80"),0, "©¢") == 1); c2b_pos = 99; ASSERT(ustr_utf8_bytes2chars(USTR1(\x4, "\x80\x80\x80\x80"), 1, 1, &c2b_pos) == 0); ASSERT(c2b_pos == 99); ASSERT(ustr_utf8_bytes2chars(USTR1(\x4, "\x80\x80\x80\x80"), 2, 1, &c2b_pos) == 0); ASSERT(c2b_pos == 99); ASSERT(ustr_utf8_bytes2chars(USTR1(\x4, "\x80\x80\x80\x80"), 3, 0, &c2b_pos) == 0); ASSERT(c2b_pos == 99); if (!USTR_DEBUG) ASSERT(ustr_utf8_bytes2chars(USTR1(\x4, "\x80\x80\x80\x80"), 8, 0, &c2b_pos) == 0); ASSERT(c2b_pos == 99); ASSERT(ustr_utf8_bytes2chars(USTR1(\x5, ".\x80\x80\x80\x80"), 1, 1, &c2b_pos) == 1); ASSERT(c2b_pos == 1); c2b_pos = 99; ASSERT(ustr_utf8_bytes2chars(USTR1(\x5, ".\x80\x80\x80\x80"), 1, 2, &c2b_pos) == 1); ASSERT(c2b_pos == 1); c2b_pos = 99; ASSERT(ustr_utf8_bytes2chars(USTR1(\x5, ".\x80\x80\x80\x80"), 3, 1, &c2b_pos) == 1); ASSERT(c2b_pos == 1); ASSERT(12345 == ustr_parse_ulongx(USTR1(\xb, "1âº234âº5"), 0, USTR_FLAG_PARSE_NUM_SEP, 0, ULONG_MAX, "âº", NULL, NULL)); ASSERT(ustrp_add_cstr(pool, &sp2, "0123456789")); ASSERT_PEQ(sp2, USTRP1(\x28," ¡¢£¤¥¦§¨©ª«¬­®0123456789")); ASSERT(ustrp_sc_utf8_reverse(pool, &sp2)); ASSERT_PEQ(sp2, USTRP1(\x28,"9876543210®­¬«ª©¨§¦¥¤£¢¡ ")); ASSERT(ustrp_owner(sp2)); { Ustr *st = &sp2->s; ASSERT(ustr_sc_utf8_reverse(&st)); } ASSERT_PEQ(sp2, USTRP1(\x28," ¡¢£¤¥¦§¨©ª«¬­®0123456789")); ustr_pool_free(pool); #ifdef USTR__UTF8_WCHAR /* internal testing for utf8 functions */ ASSERT(ustr__utf8_mk_wcwidth(0) == 0); #endif return (EXIT_SUCCESS); } ustr-1.0.4/T/tst_0_manual.c0000644000076400007640000000077210722117462014446 0ustar jamesjames/* can't include ustr.h ... because that assumes it's library linkage */ #define USTR_H 1 #include "ustr-conf.h" #include "ustr-main.h" #include "ustr-set.h" #include "ustr-fmt.h" #include "ustr-cmp.h" #include "ustr-srch.h" #include "ustr-b.h" #include "ustr-spn.h" #include "ustr-io.h" #include "ustr-ins.h" #include "ustr-parse.h" #include "ustr-pool.h" #include "ustr-utf8.h" #include "ustr-sub.h" #include "ustr-replace.h" #include "ustr-split.h" #include "ustr-sc.h" int main(void) { return 0; } ustr-1.0.4/T/tst_19_join.c0000644000076400007640000000000010755237207014210 0ustar jamesjamesustr-1.0.4/T/tst_2_small.c0000644000076400007640000004571510711021070014274 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 1 #define USTR_CONF_USE_EOS_MARK 0 #include "tst.h" static const char *rf = __FILE__; int tst(void) { unsigned int num = 254; unsigned int i; struct Ustr *tmp = NULL; ASSERT(ustr_len(s1) == 0); ASSERT(ustr_len(s2) == strlen("s2")); ASSERT(ustr_size(s1) == 0); ASSERT(ustr_size(s2) == 2); /* ustr__ns(1 + 1 + 1 + 2 + 1) - * 1 + 1 + 1 + 1 */ ASSERT(ustr_len(s2) == strlen("s2")); ASSERT( ustr_cmp_eq(s1, s1)); ASSERT( ustr_cmp_eq(s2, s2)); ASSERT(!ustr_cmp_eq(s1, s2)); ASSERT( ustr_cmp_cstr_eq(s1, "")); ASSERT( ustr_cmp_cstr_eq(s2, "s2")); ASSERT( ustr_cmp_eq(s2, USTR1(\x02, "s2"))); ASSERT(!ustr_cmp( s2, USTR1(\x02, "s2"))); ASSERT(!ustr_cmp_cstr_eq(s1, "s2")); ASSERT(!ustr_cmp_cstr_eq(s2, "")); ASSERT(!ustr_cmp_cstr_eq(s2, "s3")); ASSERT(!ustr_cmp_cstr_eq(s2, "s2x")); ASSERT(!ustr_cmp_buf_eq(s2, "s2", 1)); ASSERT( ustr_cmp_buf_eq(s2, "s2", 2)); ASSERT(!ustr_cmp_buf_eq(s2, "s2", 3)); ASSERT( ustr_cmp(s1, s1) == 0); ASSERT( ustr_cmp(s2, s2) == 0); ASSERT( ustr_cmp(s1, s2) < 0); ASSERT( ustr_cmp_fast(s1, s2) < 0); ASSERT( ustr_cmp(s2, s1) > 0); ASSERT( ustr_cmp_fast(s2, s1) > 0); ASSERT( ustr_cmp_cstr(s2, "s2") == 0); ASSERT( ustr_cmp_buf(s2, "s2", 2) == 0); ASSERT( ustr_srch_fwd(s1, 0, s1) == 0); ASSERT( ustr_srch_fwd(s1, 0, s2) == 0); ASSERT( ustr_srch_fwd(s2, 0, s1) == 1); ASSERT( ustr_srch_fwd(s2, 0, s2) == 1); ASSERT( ustr_srch_rev(s1, 0, s1) == 0); ASSERT( ustr_srch_rev(s1, 0, s2) == 0); ASSERT( ustr_srch_rev(s2, 0, s1) == 2); ASSERT( ustr_srch_rev(s2, 0, s2) == 1); ASSERT(!ustr_srch_cstr_fwd(s1, 0, "x")); ASSERT(!ustr_srch_cstr_fwd(s2, 0, "x")); ASSERT(!ustr_srch_cstr_fwd(s2, 0, "x")); ASSERT( ustr_srch_cstr_fwd(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_fwd(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_fwd(s2, 0, "s2") == 1); ASSERT( ustr_srch_cstr_fwd(s2, 0, "s") == 1); ASSERT( ustr_srch_cstr_fwd(s2, 0, "2") == 2); ASSERT( ustr_srch_cstr_fwd(s2, 1, "2") == 2); ASSERT( ustr_srch_cstr_fwd(s2, 1, "s2") == 0); ASSERT(!ustr_srch_cstr_rev(s1, 0, "x")); ASSERT(!ustr_srch_cstr_rev(s2, 0, "x")); ASSERT(!ustr_srch_cstr_rev(s2, 0, "x")); ASSERT( ustr_srch_cstr_rev(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_rev(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_rev(s2, 0, "s2") == 1); ASSERT( ustr_srch_cstr_rev(s2, 0, "s") == 1); ASSERT( ustr_srch_cstr_rev(s2, 0, "2") == 2); for (i = 0; i < num; ++i) { tmp = ustr_dup(s1); ASSERT(tmp == s1); tmp = ustr_dup(s2); ASSERT(tmp == s2); } ASSERT(ustr_sc_dup(&s2)); ASSERT(tmp && (tmp != s2)); ASSERT(ustr_cmp_eq(tmp, s2)); ustr_sc_free(&s2); s2 = tmp; for (i = 0; i < num; ++i) { ustr_free(s1); ustr_free(s1); ustr_free(s2); } ustr_sc_free(&s2); { struct Ustr *s4 = ustr_dup_cstr("x"); size_t esz; size_t ref; int exact; size_t lenn; size_t refc; ustr_conf(s4, NULL,NULL,NULL, NULL,NULL); ustr_conf(s4, &esz,&ref,&exact, &lenn,&refc); ASSERT(!esz); ASSERT(ref == 1); ASSERT(!exact); ASSERT(lenn == 1); ASSERT(refc == 1); ASSERT(ustr_len(s4) == 1); ASSERT(ustr_size(s4) == 2); ustr_sc_free(&s4); } ustr_sc_free2(&s1, USTR1(\x12, "22xxxyyyyyyyyyyyyy")); /* copy and paste between here and ctst_98_pool.c */ /* test some of the data ... */ /* spn */ ASSERT_EQ(s1, USTR1(\x12, "22xxxyyyyyyyyyyyyy")); ASSERT(ustr_spn_chr_fwd(s1, 0, 'x') == 0); ASSERT(ustr_spn_chr_fwd(s1, 0, '2') == 2); ASSERT(ustr_spn_cstr_fwd(s1, 0, "2") == 2); ASSERT(ustr_spn_cstr_fwd(s1, 0, "22") == 2); ASSERT(ustr_spn_cstr_fwd(s1, 0, "2x") == 5); ASSERT(ustr_spn_cstr_fwd(s1, 0, "x2") == 5); ASSERT(ustr_spn_cstr_fwd(s1, 0, "x2y") == 18); ASSERT(ustr_spn_fwd(s1, 0, USTR1(\x2, "22")) == 2); ASSERT(ustr_spn_fwd(s1, 0, USTR1(\x2, "2x")) == 5); ASSERT(ustr_spn_fwd(s1, 0, USTR1(\x2, "x2")) == 5); ASSERT(ustr_spn_fwd(s1, 0, USTR1(\x3, "x2y")) == 18); ASSERT(ustr_spn_cstr_rev(s1, 0, "x2") == 0); ASSERT(ustr_spn_cstr_rev(s1, 0, "x2y") == 18); ASSERT(ustr_spn_cstr_rev(s1, 0, "2y") == 13); ASSERT(ustr_spn_cstr_rev(s1, 0, "y") == 13); ASSERT(ustr_spn_rev(s1, 0, USTR1(\x2, "x2")) == 0); ASSERT(ustr_spn_rev(s1, 0, USTR1(\x3, "x2y")) == 18); ASSERT(ustr_spn_rev(s1, 0, USTR1(\x2, "2y")) == 13); ASSERT(ustr_spn_rev(s1, 0, USTR1(\x1, "y")) == 13); ASSERT(ustr_spn_chr_rev(s1, 0, 'x') == 0); ASSERT(ustr_spn_chr_rev(s1, 0, 'y') == 13); ASSERT(ustr_spn_cstr_rev(s1, 0, "yx") == 16); ASSERT(ustr_spn_cstr_rev(s1, 0, "xy") == 16); /* cspn */ ASSERT_EQ(s1, USTR1(\x12, "22xxxyyyyyyyyyyyyy")); ASSERT(ustr_cspn_chr_fwd(s1, 0, 'y') == 5); ASSERT(ustr_cspn_chr_fwd(s1, 0, 'x') == 2); ASSERT(ustr_cspn_chr_fwd(s1, 0, '2') == 0); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "2") == 0); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "y") == 5); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "22") == 0); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "x") == 2); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "xx") == 2); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "yx") == 2); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "xy") == 2); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "yz") == 5); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "zy") == 5); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x1, "2")) == 0); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x1, "y")) == 5); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x2, "22")) == 0); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x1, "x")) == 2); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x2, "xx")) == 2); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x2, "yx")) == 2); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x2, "xy")) == 2); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x2, "yz")) == 5); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x2, "zy")) == 5); ASSERT(ustr_cspn_cstr_rev(s1, 0, "2x") == 13); ASSERT(ustr_cspn_cstr_rev(s1, 0, "x2") == 13); ASSERT(ustr_cspn_chr_rev(s1, 0, '2') == 16); ASSERT(ustr_cspn_cstr_rev(s1, 0, "2") == 16); ASSERT(ustr_cspn_cstr_rev(s1, 0, "2a") == 16); ASSERT(ustr_cspn_rev(s1, 0, USTR1(\x2, "2x")) == 13); ASSERT(ustr_cspn_rev(s1, 0, USTR1(\x2, "x2")) == 13); ASSERT(ustr_cspn_rev(s1, 0, USTR1(\x1, "2")) == 16); ASSERT(ustr_cspn_rev(s1, 0, USTR1(\x2, "2a")) == 16); ASSERT(ustr_cspn_chr_fwd(s1, 0, 'a') == 18); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "a") == 18); ASSERT(ustr_cspn_cstr_rev(s1, 0, "a") == 18); ASSERT(ustr_cspn_chr_rev(s1, 0, 'a') == 18); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x1, "a")) == 18); ASSERT(ustr_cspn_rev(s1, 0, USTR1(\x1, "a")) == 18); ASSERT(ustr_cspn_cstr_fwd(s1, 0, "abc") == 18); ASSERT(ustr_cspn_cstr_rev(s1, 0, "abc") == 18); ASSERT(ustr_cspn_fwd(s1, 0, USTR1(\x3, "abc")) == 18); ASSERT(ustr_cspn_rev(s1, 0, USTR1(\x3, "abc")) == 18); /* srch */ ASSERT_EQ(s1, USTR1(\x12, "22xxxyyyyyyyyyyyyy")); ASSERT(ustr_srch_cstr_fwd(s1, 0, "xy") == 5); ASSERT(ustr_srch_cstr_rev(s1, 0, "xy") == 5); ASSERT(ustr_srch_fwd(s1, 0, USTR1(\x2, "xy")) == 5); ASSERT(ustr_srch_rev(s1, 0, USTR1(\x2, "xy")) == 5); ASSERT(ustr_srch_subustr_fwd(s1, 0, USTR1(\x2, "xy"), 1, 2) == 5); ASSERT(ustr_srch_subustr_rev(s1, 0, USTR1(\x2, "xy"), 1, 2) == 5); ASSERT(ustr_srch_subustr_fwd(s1, 0, USTR1(\x2, "xy"), 1, 1) == 3); ASSERT(ustr_srch_subustr_rev(s1, 0, USTR1(\x2, "xy"), 1, 1) == 5); ASSERT(ustr_srch_subustr_fwd(s1, 0, USTR1(\x2, "xy"), 2, 1) == 6); ASSERT(ustr_srch_subustr_rev(s1, 0, USTR1(\x2, "xy"), 2, 1) == 18); ASSERT(ustr_srch_chr_fwd(s1, 0, 'x') == 3); ASSERT(ustr_srch_chr_rev(s1, 0, 'x') == 5); ASSERT(ustr_srch_chr_fwd(s1, 0, 'y') == 6); ASSERT(ustr_srch_chr_rev(s1, 0, 'y') == 18); /* srch_case */ ASSERT_EQ(s1, USTR1(\x12, "22xxxyyyyyyyyyyyyy")); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "Xy") == 5); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "xY") == 5); ASSERT(ustr_srch_case_fwd(s1, 0, USTR1(\x2, "xY")) == 5); ASSERT(ustr_srch_case_rev(s1, 0, USTR1(\x2, "Xy")) == 5); ASSERT(ustr_srch_case_subustr_fwd(s1, 0, USTR1(\x2, "Xy"), 1, 2) == 5); ASSERT(ustr_srch_case_subustr_rev(s1, 0, USTR1(\x2, "xY"), 1, 2) == 5); ASSERT(ustr_srch_case_subustr_fwd(s1, 0, USTR1(\x2, "Xy"), 1, 1) == 3); ASSERT(ustr_srch_case_subustr_rev(s1, 0, USTR1(\x2, "xY"), 1, 1) == 5); ASSERT(ustr_srch_case_subustr_fwd(s1, 0, USTR1(\x2, "XY"), 2, 1) == 6); ASSERT(ustr_srch_case_subustr_rev(s1, 0, USTR1(\x2, "XY"), 2, 1) == 18); if (!USTR_DEBUG) ASSERT(ustr_srch_case_subustr_fwd(s1, 0, USTR1(\4, "YYYY"), 4, 2) == 1); if (!USTR_DEBUG) ASSERT(ustr_srch_case_subustr_rev(s1, 0, USTR1(\4, "1248"), 4, 2) == 18); if (!USTR_DEBUG) ASSERT(ustr_srch_case_subustr_fwd(s1, 2, USTR1(\4, "yyyy"), 5, 1) == 3); if (!USTR_DEBUG) ASSERT(ustr_srch_case_subustr_rev(s1, 2, USTR1(\4, "1248"), 5, 1) == 16); ASSERT(ustr_srch_case_chr_fwd(s1, 0, 'x') == 3); ASSERT(ustr_srch_case_chr_rev(s1, 0, 'x') == 5); ASSERT(ustr_srch_case_chr_fwd(s1, 0, 'y') == 6); ASSERT(ustr_srch_case_chr_rev(s1, 0, 'y') == 18); ASSERT(ustr_srch_case_chr_fwd(s1, 0, 'X') == 3); ASSERT(ustr_srch_case_chr_rev(s1, 0, 'X') == 5); ASSERT(ustr_srch_case_chr_fwd(s1, 0, 'Y') == 6); ASSERT(ustr_srch_case_chr_rev(s1, 0, 'Y') == 18); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'x', 1) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'x', 1) == 5); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 1) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 1) == 18); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'X', 1) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'X', 1) == 5); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 1) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 1) == 18); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'z', 1) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'z', 1) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Z', 1) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Z', 1) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'z', 2) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'z', 2) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Z', 2) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Z', 2) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Z', 0) == 1); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Z', 0) == 18); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 1, 'Z', 0) == 2); ASSERT(ustr_srch_case_rep_chr_rev(s1, 1, 'Z', 0) == 17); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'x', 2) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'x', 2) == 4); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'x', 3) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'x', 3) == 3); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'x', 4) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'x', 4) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'X', 2) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'X', 2) == 4); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'X', 3) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'X', 3) == 3); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'X', 4) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'X', 4) == 0); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "xx") == 3); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "xx") == 4); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "xxx") == 3); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "xxx") == 3); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "xxxx") == 0); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "xxxx") == 0); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "XX") == 3); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "XX") == 4); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "XXX") == 3); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "XXX") == 3); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "XXXX") == 0); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "XXXX") == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 2) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 2) == 17); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 3) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 3) == 16); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 4) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 4) == 15); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 13) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 13) == 6); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 14) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 14) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 2) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 2) == 17); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 3) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 3) == 16); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 4) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 4) == 15); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 13) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 13) == 6); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 14) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 14) == 0); /* try srch_case with other case */ ustr_sc_free2(&s1, USTR1(\x12, "22XXXYYYYYYYYYYYYY")); ASSERT_EQ(s1, USTR1(\x12, "22XXXYYYYYYYYYYYYY")); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "Xy") == 5); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "xY") == 5); ASSERT(ustr_srch_case_fwd(s1, 0, USTR1(\x2, "xY")) == 5); ASSERT(ustr_srch_case_rev(s1, 0, USTR1(\x2, "Xy")) == 5); ASSERT(ustr_srch_case_subustr_fwd(s1, 0, USTR1(\x2, "Xy"), 1, 2) == 5); ASSERT(ustr_srch_case_subustr_rev(s1, 0, USTR1(\x2, "xY"), 1, 2) == 5); ASSERT(ustr_srch_case_subustr_fwd(s1, 0, USTR1(\x2, "Xy"), 1, 1) == 3); ASSERT(ustr_srch_case_subustr_rev(s1, 0, USTR1(\x2, "xY"), 1, 1) == 5); ASSERT(ustr_srch_case_subustr_fwd(s1, 0, USTR1(\x2, "XY"), 2, 1) == 6); ASSERT(ustr_srch_case_subustr_rev(s1, 0, USTR1(\x2, "XY"), 2, 1) == 18); ASSERT(ustr_srch_case_chr_fwd(s1, 0, 'x') == 3); ASSERT(ustr_srch_case_chr_rev(s1, 0, 'x') == 5); ASSERT(ustr_srch_case_chr_fwd(s1, 0, 'y') == 6); ASSERT(ustr_srch_case_chr_rev(s1, 0, 'y') == 18); ASSERT(ustr_srch_case_chr_fwd(s1, 0, 'X') == 3); ASSERT(ustr_srch_case_chr_rev(s1, 0, 'X') == 5); ASSERT(ustr_srch_case_chr_fwd(s1, 0, 'Y') == 6); ASSERT(ustr_srch_case_chr_rev(s1, 0, 'Y') == 18); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'x', 1) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'x', 1) == 5); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 1) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 1) == 18); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'X', 1) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'X', 1) == 5); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 1) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 1) == 18); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'z', 1) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'z', 1) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Z', 1) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Z', 1) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'z', 2) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'z', 2) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Z', 2) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Z', 2) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Z', 0) == 1); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Z', 0) == 18); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 1, 'Z', 0) == 2); ASSERT(ustr_srch_case_rep_chr_rev(s1, 1, 'Z', 0) == 17); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'x', 2) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'x', 2) == 4); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'x', 3) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'x', 3) == 3); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'x', 4) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'x', 4) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'X', 2) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'X', 2) == 4); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'X', 3) == 3); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'X', 3) == 3); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'X', 4) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'X', 4) == 0); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "xx") == 3); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "xx") == 4); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "xxx") == 3); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "xxx") == 3); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "xxxx") == 0); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "xxxx") == 0); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "XX") == 3); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "XX") == 4); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "XXX") == 3); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "XXX") == 3); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "XXXX") == 0); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "XXXX") == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 2) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 2) == 17); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 3) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 3) == 16); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 4) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 4) == 15); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 13) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 13) == 6); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'y', 14) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'y', 14) == 0); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 2) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 2) == 17); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 3) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 3) == 16); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 4) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 4) == 15); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 13) == 6); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 13) == 6); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 0, 'Y', 14) == 0); ASSERT(ustr_srch_case_rep_chr_rev(s1, 0, 'Y', 14) == 0); /* show srch still works this way */ ASSERT(ustr_srch_cstr_fwd(s1, 0, "XY") == 5); ASSERT(ustr_srch_cstr_rev(s1, 0, "XY") == 5); ASSERT(ustr_srch_fwd(s1, 0, USTR1(\x2, "XY")) == 5); ASSERT(ustr_srch_rev(s1, 0, USTR1(\x2, "XY")) == 5); ASSERT(ustr_srch_subustr_fwd(s1, 0, USTR1(\x2, "XY"), 1, 2) == 5); ASSERT(ustr_srch_subustr_rev(s1, 0, USTR1(\x2, "XY"), 1, 2) == 5); ASSERT(ustr_srch_subustr_fwd(s1, 0, USTR1(\x2, "XY"), 1, 1) == 3); ASSERT(ustr_srch_subustr_rev(s1, 0, USTR1(\x2, "XY"), 1, 1) == 5); ASSERT(ustr_srch_subustr_fwd(s1, 0, USTR1(\x2, "XY"), 2, 1) == 6); ASSERT(ustr_srch_subustr_rev(s1, 0, USTR1(\x2, "XY"), 2, 1) == 18); ASSERT(ustr_srch_chr_fwd(s1, 0, 'X') == 3); ASSERT(ustr_srch_chr_rev(s1, 0, 'X') == 5); ASSERT(ustr_srch_chr_fwd(s1, 0, 'Y') == 6); ASSERT(ustr_srch_chr_rev(s1, 0, 'Y') == 18); ASSERT(ustr_srch_cstr_fwd(s1, 0, "") == 1); ASSERT(ustr_srch_cstr_rev(s1, 0, "") == ustr_len(s1)); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "") == 1); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "") == ustr_len(s1)); ASSERT(ustr_srch_cstr_fwd(s1, 2, "") == 3); ASSERT(ustr_srch_cstr_rev(s1, 2, "") == ustr_len(s1) - 2); ASSERT(ustr_srch_case_cstr_fwd(s1, 2, "") == 3); ASSERT(ustr_srch_case_cstr_rev(s1, 2, "") == ustr_len(s1) - 2); return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_18_split.c0000644000076400007640000001676510651733745014602 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { /* single char sep; do not keep sep; do keep blank strings */ Ustr *a = ustr_dup_cstr("blue,yellow,red,green,,orange"); const char *ans[] = {"blue","yellow","red","green","","orange"}; size_t off = 0; unsigned int flags = (USTR_FLAG_SPLIT_RET_NON); Ustr *sep = ustr_dup_cstr(","); Ustr *tok = NULL; Ustr *ret = NULL; size_t i = 0; const char *ans2[] = {"a==","b,c==","d,c==","==","==",",12==","xzy==","=="}; const char *ans3[] = {"a","bx","cx","dx","xx"}; const char *ans4[] = {"a,bx","cx","dx",",xx"}; const char *ans5[] = {"this","is","a","test","of","the","emergency","broadcast","system"}; const char *ans6[] = {" ", " ", "this ","is ","a ","test ","of ","the\t","emergency\n"," ","broadcast ","system"}; const char *ans7[] = {"a ","b ","c ","d "," "," "," "," "," "," "," "," "," ","e|","f|","g|","|","h"}; const char *ans8[] = {"a","b","c","d","e","f","g","h"}; const char *ans9[] = {"a","b","c","d","","","","","","","","","","e","f","g","","h"}; const char *ans10[] = {"a b c d e|f|g||h"}; const char *chrs = "\t\n "; while ((tok = ustr_split(a,&off,sep, NULL,flags))) { ASSERT(ustr_cmp_cstr_eq(tok,ans[i])); ++i; ustr_sc_free(&tok); } ASSERT(i == 6); ustr_sc_free(&a); ustr_sc_free(&sep); /* mult-char sep; keep sep; do not keep blank strings */ a = ustr_dup_cstr("a==b,c==d,c======,12==xzy===="); sep = ustr_dup_cstr("=="); flags = (USTR_FLAG_SPLIT_RET_SEP); i=0; off=0; while ((tok = ustr_split(a,&off,sep, NULL,flags))) { ASSERT(ustr_cmp_cstr_eq(tok,ans2[i])); ++i; ustr_sc_free(&tok); } ASSERT(i == 8); ustr_sc_free(&a); ustr_sc_free(&sep); /* single-char sep; skip sep, skip blank */ a = ustr_dup_cstr("a,bx,,,,cx,,dx,,,xx,,,,"); sep = ustr_dup_cstr(","); flags = 0; i=0; off=0; while ((tok = ustr_split(a,&off,sep, NULL,flags))) { ASSERT(ustr_cmp_cstr_eq(tok,ans3[i])); ++i; ustr_sc_free(&tok); } ustr_sc_free(&sep); /* multi-char sep; skip sep; skip blank */ sep = ustr_dup_cstr(",,"); i=0; off=0; while ((tok = ustr_split(a,&off,sep, NULL,flags))) { ASSERT(ustr_cmp_cstr_eq(tok,ans4[i])); ++i; ustr_sc_free(&tok); } ustr_sc_free(&sep); ASSERT(i==4); /* blank sep */ off = 0; sep = USTR(""); ASSERT((ret = ustr_split(a,&off,sep, NULL,flags)) == USTR_FALSE); ASSERT(off==0); ustr_sc_free(&ret); /* blank target */ sep = ustr_dup_cstr(","); ustr_sc_free(&a); a = USTR(""); ASSERT((ret = ustr_split(a,&off,sep, NULL,flags)) == USTR_FALSE); ASSERT(off==0); ustr_sc_free(&sep); ustr_sc_free(&ret); a = USTR1(\x15, "a||bx||||cx||dx||||xx"); i = 0; off = 0; while ((tok = ustr_split_cstr(a, &off, "||", NULL, USTR_FLAG_SPLIT_DEF))) { ASSERT(!ustr_sized(a)); ASSERT(!ustr_sized(tok)); ASSERT(ustr_cmp_cstr_eq(tok, ans3[i++])); ustr_sc_free(&tok); } ASSERT((a = ustr_dupx(1, 0, 0, 0, a))); off = 1; ASSERT((tok = ustr_split_cstr(a, &off, "||", NULL, USTR_FLAG_SPLIT_RET_NON))); ASSERT( ustr_sized(a)); ASSERT(!ustr_sized(tok)); ASSERT( ustr_ro(tok)); ASSERT(!ustr_len(tok)); ustr_sc_free(&tok); off = 1; ASSERT((tok = ustr_split_cstr(a, &off, "||", NULL, USTR_FLAG_SPLIT_RET_SEP))); ASSERT( ustr_sized(a)); ASSERT(!ustr_sized(tok)); ASSERT(!ustr_ro(tok)); ASSERT(ustr_cmp_cstr_eq(tok, "||")); ustr_sc_free(&tok); ASSERT((tok = ustr_split_cstr(a, &off, "||", NULL, USTR_FLAG_SPLIT_RET_SEP))); ASSERT( ustr_sized(a)); ASSERT(!ustr_sized(tok)); ASSERT(!ustr_ro(tok)); ASSERT(ustr_cmp_cstr_eq(tok, "bx||")); ustr_sc_free(&tok); i = 2; while ((tok = ustr_split_cstr(a, &off, "||", tok, USTR_FLAG_SPLIT_KEEP_CONF))) { ASSERT( ustr_sized(a)); ASSERT( ustr_sized(tok)); ASSERT(ustr_cmp_cstr_eq(tok, ans3[i++])); ustr_sc_free(&tok); } off = 0; i = 0; flags = USTR_FLAG_SPLIT_KEEP_CONF; while ((tok = ustr_split_cstr(a, &off, "||", tok, flags))) { ASSERT( ustr_sized(a)); ASSERT( ustr_sized(tok)); ASSERT(ustr_cmp_cstr_eq(tok, ans3[i++])); flags = USTR_FLAG_SPLIT_DEF; /* doesn't matter after first one */ } off = 0; ASSERT(!ustr_split(a, &off, a, NULL, 0)); ASSERT((off == ustr_len(a))); off = 0; ASSERT((tok = ustr_split(a, &off, a, NULL, (USTR_FLAG_SPLIT_RET_NON | USTR_FLAG_SPLIT_KEEP_CONF)))); ASSERT((off == ustr_len(a))); ASSERT( ustr_sized(tok)); ASSERT( ustr_cstr(tok)); ASSERT_EQ(tok, USTR("")); ustr_sc_free(&tok); off = 0; ASSERT((tok = ustr_split(a, &off, a, NULL, (USTR_FLAG_SPLIT_RET_SEP | USTR_FLAG_SPLIT_KEEP_CONF)))); ASSERT((off == ustr_len(a))); ASSERT_EQ(tok, a); ASSERT( ustr_sized(tok)); ASSERT( ustr_cstr(tok)); off = 0; ASSERT((tok = ustr_split(a, &off, a, tok, USTR_FLAG_SPLIT_RET_NON))); ASSERT( ustr_sized(tok)); ASSERT(!ustr_ro(tok)); ustr_sc_free(&tok); off = 0; ASSERT((tok = ustr_split(a, &off, a, tok, USTR_FLAG_SPLIT_RET_NON))); ASSERT(!ustr_sized(tok)); ASSERT( ustr_ro(tok)); off = 0; ASSERT((tok = ustr_dup_cstr("abcd"))); ASSERT(!ustr_split(a, &off, a, tok, 0)); /* does the free */ ustr_sc_free(&a); /* ustr_split_spn_cstr */ a = ustr_dup_cstr(" this is a test of the\temergency\n broadcast system"); off = 0; i=0; tok = USTR_NULL; while ((tok = ustr_split_spn_cstr(a,&off,chrs,USTR_NULL,0))) { ASSERT(ustr_cmp_cstr_eq(tok,ans5[i++])); ustr_sc_free(&tok); } ASSERT(i==9); i=0; off=0; while ((tok = ustr_split_spn_cstr(a,&off,chrs,USTR_NULL,USTR_FLAG_SPLIT_RET_SEP))) { ASSERT(ustr_cmp_cstr_eq(tok,ans6[i++])); ustr_sc_free(&tok); } ASSERT(i==12); i=0; off=0; while ((tok = ustr_split_spn_cstr(a,&off,chrs,USTR_NULL,USTR_FLAG_SPLIT_RET_SEP|USTR_FLAG_SPLIT_RET_NON))) { ASSERT(ustr_cmp_cstr_eq(tok,ans6[i++])); ustr_sc_free(&tok); } ASSERT(i==12); ustr_sc_free(&a); chrs = " |"; a = ustr_dup_cstr("a b c d e|f|g||h"); i=0; off=0; while ((tok = ustr_split_spn_cstr(a,&off,chrs,USTR_NULL,USTR_FLAG_SPLIT_RET_SEP|USTR_FLAG_SPLIT_RET_NON))) { ASSERT(ustr_cmp_cstr_eq(tok,ans7[i++])); ustr_sc_free(&tok); } ASSERT(i==18); i=0; off=0; while ((tok = ustr_split_spn_cstr(a,&off,chrs,USTR_NULL,0))) { ASSERT(ustr_cmp_cstr_eq(tok,ans8[i++])); ustr_sc_free(&tok); } ASSERT(i==8); i=0; off=0; while ((tok = ustr_split_spn_cstr(a,&off,chrs,USTR_NULL,USTR_FLAG_SPLIT_RET_NON))) { ASSERT(ustr_cmp_cstr_eq(tok,ans9[i++])); ustr_sc_free(&tok); } ASSERT(i==18); chrs = "xyz"; i=0; off=0; while ((tok = ustr_split_spn_cstr(a,&off,chrs,tok,USTR_FLAG_SPLIT_RET_NON))) { ASSERT(ustr_cmp_cstr_eq(tok,ans10[i++])); } off=0; chrs = "g"; ASSERT(i==1); ustr_sc_free(&a); a = USTR1(\x3, "agg"); ASSERT(ustr_assert_valid(a)); ASSERT( ustr_ro(a)); ASSERT(!ustr_sized(a)); tok = ustr_split_spn_cstr(a,&off,chrs,tok,USTR_FLAG_SPLIT_RET_NON); ASSERT(ustr_cmp_cstr_eq(tok,"a")); ASSERT(!ustr_ro(tok)); ASSERT(!ustr_sized(tok)); tok = ustr_split_spn_cstr(a,&off,chrs,tok,USTR_FLAG_SPLIT_RET_NON); ASSERT(ustr_cmp_cstr_eq(tok,"")); ASSERT( ustr_ro(tok)); ASSERT(!ustr_sized(tok)); ustr_sc_free(&tok); ASSERT((a = ustr_dupx(1, 0, 0, 0, a))); off=0; tok = ustr_split_spn(a,&off,USTR1(\1, "g"),tok,USTR_FLAG_SPLIT_KEEP_CONF); ASSERT(ustr_cmp_cstr_eq(tok,"a")); ASSERT(ustr_sized(a)); ASSERT(ustr_sized(tok)); ustr_sc_free(&a); ustr_sc_free(&tok); return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_14_cmp.c0000644000076400007640000002346310704211571014176 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { Ustr_pool *pool = ustr_pool_ll_make(); Ustrp *sp1 = USTRP1(\x4, "abcd"); Ustrp *sp2 = USTRP1(\x4, ".xyz"); Ustrp *sp3 = USTRP1(\x8, "abcd.xyz"); ASSERT(!ustrp_cmp_cstr(sp1, "abcd")); ASSERT( ustrp_cmp_cstr(sp2, "abcd") < 0); ASSERT( ustrp_cmp_cstr(sp3, "abcd") > 0); ASSERT( ustrp_cmp_cstr(sp1, ".xyz") > 0); ASSERT(!ustrp_cmp_cstr(sp2, ".xyz")); ASSERT( ustrp_cmp_cstr(sp3, ".xyz") > 0); ASSERT( ustrp_cmp_cstr(sp1, "abcd.xyz") < 0); ASSERT( ustrp_cmp_cstr(sp2, "abcd.xyz") < 0); ASSERT(!ustrp_cmp_cstr(sp3, "abcd.xyz")); ASSERT(ustrp_cmp_buf_eq(sp1, "abcd.xyz", 4)); ASSERT(ustrp_cmp_cstr_eq(sp1, ustrp_cstr(USTRP1(\x4, "abcd")))); ASSERT(ustrp_sc_ensure_owner(pool, &sp1)); ASSERT(ustrp_cmp_cstr_eq(sp1, ustrp_wstr(sp1))); ASSERT(ustrp_cmp_cstr_eq(sp1, "abcd")); ASSERT(ustrp_cmp_cstr_eq(sp2, ".xyz")); ASSERT(ustrp_cmp_cstr_eq(sp3, "abcd.xyz")); ASSERT(!ustrp_cmp_fast_cstr(sp1, "abcd")); ASSERT(!ustrp_cmp_fast_cstr(sp2, ".xyz")); ASSERT(!ustrp_cmp_fast_cstr(sp3, "abcd.xyz")); ASSERT(ustrp_cmp_prefix_eq(sp3, sp3)); ASSERT(ustrp_cmp_prefix_eq(sp3, sp1)); ASSERT(ustrp_cmp_suffix_eq(sp3, sp2)); ASSERT(ustrp_cmp_suffix_eq(sp3, sp3)); ASSERT(!ustrp_cmp_prefix_cstr_eq(sp3, "z")); ASSERT(!ustrp_cmp_prefix_subustrp_eq(sp3, sp3, 4, 1)); ASSERT(!ustrp_cmp_prefix_subustrp_eq(sp3, sp1, 4, 1)); ASSERT(ustrp_cmp_prefix_cstr_eq(sp3, "a")); ASSERT(ustrp_cmp_prefix_subustrp_eq(sp3, sp1, 1, 1)); ASSERT(ustrp_cmp_prefix_cstr_eq(sp3, "ab")); ASSERT(ustrp_cmp_prefix_subustrp_eq(sp3, sp1, 1, 2)); ASSERT(ustrp_cmp_prefix_cstr_eq(sp3, "abc")); ASSERT(ustrp_cmp_prefix_subustrp_eq(sp3, sp1, 1, 3)); ASSERT(ustrp_cmp_prefix_subustrp_eq(sp3, USTRP1(\7, "--abc--"), 3, 3)); ASSERT(ustrp_cmp_case_prefix_subustrp_eq(sp3, USTRP1(\7, "--aBc--"), 3, 3)); ASSERT(ustrp_cmp_prefix_cstr_eq(sp3, "abcd")); ASSERT(ustrp_cmp_prefix_subustrp_eq(sp3, sp1, 1, 4)); ASSERT(ustrp_cmp_prefix_subustrp_eq(sp3, USTRP1(\x8, "--abcd--"), 3, 4)); ASSERT(ustrp_cmp_case_prefix_subustrp_eq(sp3, USTRP1(\x8, "--AbCD--"), 3, 4)); ASSERT(ustrp_cmp_prefix_cstr_eq(sp3, "abcd.")); ASSERT(ustrp_cmp_prefix_cstr_eq(sp3, "abcd.x")); ASSERT(ustrp_cmp_prefix_cstr_eq(sp3, "abcd.xy")); ASSERT(ustrp_cmp_prefix_cstr_eq(sp3, "abcd.xyz")); ASSERT(!ustrp_cmp_prefix_cstr_eq(sp3, "abcd.xyzz")); ASSERT(!ustrp_cmp_prefix_cstr_eq(sp3, "aabcd.xyz")); ASSERT(ustrp_cmp_suffix_cstr_eq(sp3, "abcd.xyz")); ASSERT(ustrp_cmp_suffix_cstr_eq(sp3, "bcd.xyz")); ASSERT(ustrp_cmp_suffix_cstr_eq(sp3, "cd.xyz")); ASSERT(ustrp_cmp_suffix_cstr_eq(sp3, "d.xyz")); ASSERT(ustrp_cmp_suffix_cstr_eq(sp3, ".xyz")); ASSERT(ustrp_cmp_suffix_subustrp_eq(sp3, sp3, 5, 4)); ASSERT(ustrp_cmp_suffix_cstr_eq(sp3, "xyz")); ASSERT(ustrp_cmp_suffix_subustrp_eq(sp3, sp2, 2, 3)); ASSERT(ustrp_cmp_case_suffix_subustrp_eq(sp3, USTRP1(\7, "--xYz--"), 3, 3)); ASSERT(ustrp_cmp_suffix_cstr_eq(sp3, "yz")); ASSERT(ustrp_cmp_suffix_subustrp_eq(sp3, sp2, 3, 2)); ASSERT(ustrp_cmp_suffix_subustrp_eq(sp3, USTRP1(\6, "--yz--"), 3, 2)); ASSERT(ustrp_cmp_case_suffix_subustrp_eq(sp3, USTRP1(\6, "--Yz--"), 3, 2)); ASSERT(ustrp_cmp_suffix_cstr_eq(sp3, "z")); ASSERT(ustrp_cmp_suffix_subustrp_eq(sp3, sp2, 4, 1)); ASSERT(ustrp_cmp_suffix_subustrp_eq(sp3, USTRP1(\6, "---z--"), 4, 1)); ASSERT(ustrp_cmp_case_suffix_subustrp_eq(sp3, USTRP1(\6, "---Z--"), 4, 1)); ASSERT(!ustrp_cmp_suffix_cstr_eq(sp3, "a")); ASSERT(!ustrp_cmp_suffix_subustrp_eq(sp3, sp1, 1, 1)); ASSERT(!ustrp_cmp_suffix_subustrp_eq(sp3, sp1, 4, 1)); ASSERT(!ustr_cmp_prefix_cstr_eq(s1, "a")); ASSERT( ustr_cmp_prefix_cstr_eq(s1, "")); ASSERT(!ustr_cmp_suffix_cstr_eq(s1, "a")); ASSERT( ustr_cmp_suffix_cstr_eq(s1, "")); ASSERT(!ustr_cmp_prefix_cstr_eq(s2, "z")); ASSERT( ustr_cmp_prefix_cstr_eq(s2, "")); ASSERT( ustr_cmp_prefix_cstr_eq(s2, "s")); ASSERT( ustr_cmp_prefix_cstr_eq(s2, "s2")); ASSERT(!ustr_cmp_prefix_cstr_eq(s2, "s22")); ASSERT(!ustr_cmp_prefix_cstr_eq(s2, "ss2")); ASSERT( ustr_cmp_suffix_cstr_eq(s2, "s2")); ASSERT( ustr_cmp_suffix_cstr_eq(s2, "2")); ASSERT( ustr_cmp_suffix_cstr_eq(s2, "")); ASSERT(!ustr_cmp_suffix_cstr_eq(s2, "z")); ASSERT(!ustr_cmp_prefix_eq(s1, s2)); ASSERT( ustr_cmp_prefix_eq(s2, s1)); ASSERT(!ustr_cmp_suffix_eq(s1, s2)); ASSERT( ustr_cmp_suffix_eq(s2, s1)); ASSERT(ustrp_cmp(sp3, sp1) == 1); ASSERT(ustrp_cmp(sp1, sp3) == -1); if (!USTR_DEBUG) ASSERT(ustrp_cmp_subustrp(sp3, sp1, 1, 8) == 1); if (!USTR_DEBUG) ASSERT(ustrp_cmp_fast_subustrp(sp3, sp1, 1, 8) == 1); if (!USTR_DEBUG) ASSERT(ustrp_cmp_prefix_subustrp_eq(sp3, sp1, 1, 8) == 1); if (!USTR_DEBUG) ASSERT(ustrp_cmp_suffix_subustrp_eq(sp3, sp1, 1, 8) == 1); ASSERT(ustrp_cmp_subustrp_eq(sp1, sp3, 1, 4)); /* caseless comparison */ sp1 = USTRP1(\x4, "aBcd"); sp2 = USTRP1(\x4, ".xyZ"); sp3 = USTRP1(\x8, "AbCd.Xyz"); ASSERT(!ustrp_cmp_case_cstr(sp1, "abcd")); ASSERT( ustrp_cmp_case_cstr_eq(sp1, "abcd")); ASSERT( ustrp_cmp_case_eq(sp1, USTRP1(\4, "aBCd"))); ASSERT( ustrp_cmp_case_cstr(sp2, "abcd") < 0); ASSERT( ustrp_cmp_case_cstr(sp3, "abcd") > 0); ASSERT( ustrp_cmp_case_cstr(sp1, ".xyz") > 0); ASSERT(!ustrp_cmp_case_cstr(sp2, ".xyz")); ASSERT( ustrp_cmp_case_cstr_eq(sp2, ".xyz")); ASSERT( ustrp_cmp_case_eq(sp2, USTRP1(\4, ".xYz"))); ASSERT( ustrp_cmp_case_cstr(sp3, ".xyz") > 0); ASSERT( ustrp_cmp_case_cstr(sp1, "abcd.xyz") < 0); ASSERT( ustrp_cmp_case_cstr(sp2, "abcd.xyz") < 0); ASSERT(!ustrp_cmp_case_cstr(sp3, "abcd.xyz")); ASSERT( ustrp_cmp_case_cstr_eq(sp3, "abcd.xyz")); ASSERT( ustrp_cmp_case_eq(sp3, USTRP1(\x8, "abcd.xyz"))); ASSERT(!ustr_cmp_case_cstr(&sp1->s, "abcd")); ASSERT( ustr_cmp_case_cstr_eq(&sp1->s, "aBcD")); ASSERT( ustr_cmp_case_eq(&sp1->s, USTR1(\4, "aBCD"))); ASSERT( ustr_cmp_case_cstr(&sp2->s, "abcD") < 0); ASSERT( ustr_cmp_case_cstr(&sp3->s, "Abcd") > 0); ASSERT( ustr_cmp_case_cstr(&sp1->s, ".xyz") > 0); ASSERT(!ustr_cmp_case_cstr(&sp2->s, ".xyz")); ASSERT( ustr_cmp_case_cstr_eq(&sp2->s, ".XYZ")); ASSERT( ustr_cmp_case_eq(&sp2->s, USTR1(\4, ".XyZ"))); ASSERT( ustr_cmp_case_cstr(&sp3->s, ".xyz") > 0); ASSERT( ustr_cmp_case_cstr(&sp1->s, "abcd.xyz") < 0); ASSERT( ustr_cmp_case_cstr(&sp2->s, "abcd.xyz") < 0); ASSERT(!ustr_cmp_case_cstr(&sp3->s, "abcd.xyz")); ASSERT( ustr_cmp_case_cstr_eq(&sp3->s, "abcd.xyz")); ASSERT( ustr_cmp_case_eq(&sp3->s, USTR1(\x8, "abcd.xyz"))); ASSERT(ustrp_cmp_case_buf_eq(sp1, "abcd.xyz", 4)); ASSERT(ustrp_cmp_case_cstr_eq(sp1, ustrp_cstr(USTRP1(\x4, "abcd")))); ASSERT(ustrp_cmp_case_cstr_eq(sp1, ustrp_sc_wstr(pool, &sp1))); ASSERT(ustrp_cmp_case_cstr_eq(sp1, "abcd")); ASSERT(ustrp_cmp_case_cstr_eq(sp2, ".xyz")); ASSERT(ustrp_cmp_case_cstr_eq(sp3, "abcd.xyz")); ASSERT(!ustrp_cmp_case_cstr(sp1, "abcd")); ASSERT(!ustrp_cmp_case_cstr(sp2, ".xyz")); ASSERT(!ustrp_cmp_case_cstr(sp3, "abcd.xyz")); ASSERT(!ustr_cmp_case_cstr(&sp1->s, "abcd")); ASSERT(!ustr_cmp_case_cstr(&sp2->s, ".xyz")); ASSERT(!ustr_cmp_case_cstr(&sp3->s, "abcd.xyz")); ASSERT(!ustrp_cmp_case(sp1, sp1)); ASSERT(!ustrp_cmp_case(sp2, sp2)); ASSERT(!ustrp_cmp_case(sp3, sp3)); ASSERT(ustrp_cmp_case_eq(sp1, sp1)); ASSERT(ustrp_cmp_case_eq(sp2, sp2)); ASSERT(ustrp_cmp_case_eq(sp3, sp3)); ASSERT(ustrp_cmp_case_prefix_eq(sp3, sp3)); ASSERT(ustrp_cmp_case_prefix_eq(sp3, sp1)); ASSERT(ustrp_cmp_case_suffix_eq(sp3, sp2)); ASSERT(ustrp_cmp_case_suffix_eq(sp3, sp3)); ASSERT(!ustrp_cmp_case_prefix_cstr_eq(sp3, "z")); ASSERT(ustrp_cmp_case_prefix_cstr_eq(sp3, "a")); ASSERT(ustrp_cmp_case_prefix_cstr_eq(sp3, "ab")); ASSERT(ustrp_cmp_case_prefix_cstr_eq(sp3, "abc")); ASSERT(ustrp_cmp_case_prefix_cstr_eq(sp3, "abcd")); ASSERT(ustrp_cmp_case_prefix_cstr_eq(sp3, "abcd.")); ASSERT(ustrp_cmp_case_prefix_cstr_eq(sp3, "abcd.x")); ASSERT(ustrp_cmp_case_prefix_cstr_eq(sp3, "abcd.xy")); ASSERT(ustrp_cmp_case_prefix_cstr_eq(sp3, "abcd.xyz")); ASSERT(!ustrp_cmp_case_prefix_cstr_eq(sp3, "abcd.xyzz")); ASSERT(!ustrp_cmp_case_prefix_cstr_eq(sp3, "aabcd.xyz")); ASSERT(ustrp_cmp_case_suffix_cstr_eq(sp3, "abcd.xyz")); ASSERT(ustrp_cmp_case_suffix_cstr_eq(sp3, "bcd.xyz")); ASSERT(ustrp_cmp_case_suffix_cstr_eq(sp3, "cd.xyz")); ASSERT(ustrp_cmp_case_suffix_cstr_eq(sp3, "d.xyz")); ASSERT(ustrp_cmp_case_suffix_cstr_eq(sp3, ".xyz")); ASSERT(ustrp_cmp_case_suffix_cstr_eq(sp3, "xyz")); ASSERT(ustrp_cmp_case_suffix_cstr_eq(sp3, "yz")); ASSERT(ustrp_cmp_case_suffix_cstr_eq(sp3, "z")); ASSERT(!ustrp_cmp_case_suffix_cstr_eq(sp3, "a")); ASSERT(!ustr_cmp_case_prefix_cstr_eq(s1, "A")); ASSERT( ustr_cmp_case_prefix_cstr_eq(s1, "")); ASSERT(!ustr_cmp_case_suffix_cstr_eq(s1, "A")); ASSERT( ustr_cmp_case_suffix_cstr_eq(s1, "")); ASSERT(!ustr_cmp_case_prefix_cstr_eq(s2, "Z")); ASSERT( ustr_cmp_case_prefix_cstr_eq(s2, "")); ASSERT( ustr_cmp_case_prefix_cstr_eq(s2, "S")); ASSERT( ustr_cmp_case_prefix_cstr_eq(s2, "S2")); ASSERT(!ustr_cmp_case_prefix_cstr_eq(s2, "S22")); ASSERT(!ustr_cmp_case_prefix_cstr_eq(s2, "SS2")); ASSERT( ustr_cmp_case_suffix_cstr_eq(s2, "S2")); ASSERT( ustr_cmp_case_suffix_cstr_eq(s2, "2")); ASSERT( ustr_cmp_case_suffix_cstr_eq(s2, "")); ASSERT(!ustr_cmp_case_suffix_cstr_eq(s2, "Z")); ASSERT(!ustr_cmp_case_prefix_eq(s1, s2)); ASSERT( ustr_cmp_case_prefix_eq(s2, s1)); ASSERT(!ustr_cmp_case_suffix_eq(s1, s2)); ASSERT( ustr_cmp_case_suffix_eq(s2, s1)); ASSERT(ustrp_cmp_case(sp3, sp1) == 1); ASSERT(ustrp_cmp_case(sp1, sp3) == -1); if (!USTR_DEBUG) ASSERT(ustrp_cmp_case_subustrp(sp3, sp1, 1, 8) == 1); if (!USTR_DEBUG) ASSERT(ustrp_cmp_case_prefix_subustrp_eq(sp3, sp1, 1, 8) == 1); if (!USTR_DEBUG) ASSERT(ustrp_cmp_case_suffix_subustrp_eq(sp3, sp1, 1, 8) == 1); ASSERT(ustrp_cmp_case_subustrp_eq(sp1, sp3, 1, 4)); ustr_pool_free(pool); return (EXIT_SUCCESS); } ustr-1.0.4/T/tst_99_enomem.c0000644000076400007640000000007210634106155014543 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 0 ustr-1.0.4/T/tst_1_basic.c0000644000076400007640000000513110675027344014253 0ustar jamesjames#define USTR_CONF_COMPILE_TYPEDEF 0 #define USTR_CONF_REF_BYTES 4 #include "tst.h" static const char *rf = __FILE__; int tst(void) { unsigned int num = 65539; unsigned int i; struct Ustr *tmp = NULL; ASSERT(ustr_len(s1) == 0); ASSERT( ustr_cmp_eq(s1, s1)); ASSERT( ustr_cmp_eq(s2, s2)); ASSERT(!ustr_cmp_eq(s1, s2)); ASSERT( ustr_cmp_cstr_eq(s1, "")); ASSERT( ustr_cmp_cstr_eq(s2, "s2")); ASSERT( ustr_cmp_eq(s2, USTR1(\x02, "s2"))); ASSERT(!ustr_cmp( s2, USTR1(\x02, "s2"))); ASSERT(!ustr_cmp_cstr_eq(s1, "s2")); ASSERT(!ustr_cmp_cstr_eq(s2, "")); ASSERT(!ustr_cmp_cstr_eq(s2, "s3")); ASSERT(!ustr_cmp_cstr_eq(s2, "s2x")); ASSERT(!ustr_cmp_buf_eq(s2, "s2", 1)); ASSERT( ustr_cmp_buf_eq(s2, "s2", 2)); ASSERT(!ustr_cmp_buf_eq(s2, "s2", 3)); ASSERT( ustr_cmp(s1, s1) == 0); ASSERT( ustr_cmp(s2, s2) == 0); ASSERT( ustr_cmp(s1, s2) < 0); ASSERT( ustr_cmp_fast(s1, s2) < 0); ASSERT( ustr_cmp(s2, s1) > 0); ASSERT( ustr_cmp_fast(s2, s1) > 0); ASSERT( ustr_cmp_cstr(s2, "s2") == 0); ASSERT( ustr_cmp_buf(s2, "s2", 2) == 0); ASSERT( ustr_srch_fwd(s1, 0, s1) == 0); ASSERT( ustr_srch_fwd(s1, 0, s2) == 0); ASSERT( ustr_srch_fwd(s2, 0, s1) == 1); ASSERT( ustr_srch_fwd(s2, 0, s2) == 1); ASSERT( ustr_srch_rev(s1, 0, s1) == 0); ASSERT( ustr_srch_rev(s1, 0, s2) == 0); ASSERT( ustr_srch_rev(s2, 0, s1) == 2); ASSERT( ustr_srch_rev(s2, 0, s2) == 1); ASSERT(!ustr_srch_cstr_fwd(s1, 0, "x")); ASSERT(!ustr_srch_cstr_fwd(s2, 0, "x")); ASSERT(!ustr_srch_cstr_fwd(s2, 0, "x")); ASSERT( ustr_srch_cstr_fwd(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_fwd(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_fwd(s2, 0, "s2") == 1); ASSERT( ustr_srch_cstr_fwd(s2, 0, "s") == 1); ASSERT( ustr_srch_cstr_fwd(s2, 0, "2") == 2); ASSERT(!ustr_srch_cstr_rev(s1, 0, "x")); ASSERT(!ustr_srch_cstr_rev(s2, 0, "x")); ASSERT(!ustr_srch_cstr_rev(s2, 0, "x")); ASSERT( ustr_srch_cstr_rev(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_rev(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_rev(s2, 0, "s2") == 1); ASSERT( ustr_srch_cstr_rev(s2, 0, "s") == 1); ASSERT( ustr_srch_cstr_rev(s2, 0, "2") == 2); for (i = 0; i < num; ++i) { tmp = ustr_dup(s1); ASSERT(tmp == s1); tmp = ustr_dup(s2); ASSERT(tmp == s2); } for (i = 0; i < num; ++i) { ustr_free(s1); ustr_free(s1); ustr_free(s2); } ustr_sc_free(&s2); { struct Ustr *s4 = ustr_dup_cstr("x"); ASSERT(ustr_len(s4) == 1); /* ASSERT(ustr_size(s4) == 1); */ ustr_sc_free(&s4); } return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_5_shrink.c0000644000076400007640000000563310630111754014634 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { struct Ustr *s3 = NULL; struct Ustr *s4 = NULL; assert(!USTR_CONF_USE_DYNAMIC_CONF || ustr_cntl_opt(USTR_CNTL_OPT_SET_REF_BYTES, 1)); /* move to the new "default" conf */ ustr_sc_free2(&s2, ustr_dup_buf(ustr_cstr(s2), ustr_len(s2))); ASSERT(s2); s3 = ustr_dup_cstr("s3 abcd s2"); s4 = ustr_dup_rep_chr('x', 40); ASSERT(s3); ASSERT(s4); ASSERT(ustr_len(s1) == 0); ASSERT(ustr_len(s2) == 2); ASSERT(ustr_len(s3) == 10); ASSERT(ustr_len(s4) == 40); ASSERT(ustr_size(s1) == 0); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s2) == 2); /* ustr__ns(1 + 1 + 1 + 2 + 1) - * 1 + 1 + 1 + 1 */ if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s3) == 12); /* ustr__ns(1 + 1 + 1 + 10 + 1) - * 1 + 1 + 1 + 1 */ if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s4) == 44); ASSERT(ustr_add_rep_chr(&s4, '-', 8)); ASSERT(ustr_len(s4) == 48); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s4) == 60); ASSERT(ustr_del(&s4, 4)); ASSERT(ustr_len(s4) == 44); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s4) == 44); ASSERT(ustr_del(&s4, 20)); ASSERT(ustr_len(s4) == 24); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s4) == 28); ustr_sc_free(&s3); ASSERT((s3 = ustr_dup(s4))); ASSERT(ustr_len(s3) == 24); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s3) == 28); ASSERT(ustr_len(s4) == 24); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s4) == 28); ASSERT(ustr_del(&s4, 15)); ASSERT(ustr_len(s3) == 24); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s3) == 28); ASSERT(ustr_len(s4) == 9); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s4) == 12); ASSERT(ustr_cmp_cstr_eq(s3, "xxxxxxxxxxxxxxxxxxxxxxxx")); ASSERT(!strcmp(ustr_cstr(s3), "xxxxxxxxxxxxxxxxxxxxxxxx")); ASSERT(ustr_cmp_cstr_eq(s4, "xxxxxxxxx")); ASSERT(!strcmp(ustr_cstr(s4), "xxxxxxxxx")); ASSERT(!ustr_del(&s4, 15)); ASSERT(ustr_del(&s4, 8)); ASSERT(ustr_len(s4) == 1); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s4) == 2); ASSERT(ustr_cmp_cstr_eq(s4, "x")); ASSERT(!strcmp(ustr_cstr(s4), "x")); ASSERT(ustr_add_rep_chr(&s4, '-', 8)); ASSERT(ustr_len(s4) == 9); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s4) == 12); ASSERT(ustr_cmp_cstr_eq(s4, "x--------")); ASSERT(!strcmp(ustr_cstr(s4), "x--------")); ASSERT(ustr_set_cstr(&s4, "x12345678")); ustr_sc_free2(&s3, s4); ASSERT(ustr_cmp_cstr_eq(s4, "x12345678")); ASSERT( ustr_owner(s4)); ASSERT(!ustr_shared(s4)); ASSERT(s3 == s4); ASSERT( ustr_setf_share(s4)); ASSERT(!ustr_owner(s4)); ASSERT(ustr_del_subustr(&s4, 4, 4)); ASSERT(ustr_cmp_cstr_eq(s3, "x12345678")); ASSERT(ustr_cmp_cstr_eq(s4, "x1278")); ustr_sc_free_shared(&s3); ustr_sc_free(&s4); return (EXIT_SUCCESS); } ustr-1.0.4/T/tst_8_spn.c0000644000076400007640000000007210630111754013766 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 4 ustr-1.0.4/T/ctst_1_basic.c0000644000076400007640000000000010630111754014372 0ustar jamesjamesustr-1.0.4/T/ctst_4_grow.c0000644000076400007640000001623410674652633014330 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { struct Ustr *s3 = NULL; struct Ustr *s4 = NULL; int num = -1; assert(!USTR_CONF_USE_DYNAMIC_CONF || ustr_cntl_opt(USTR_CNTL_OPT_SET_REF_BYTES, 1)); /* move to the new "default" conf */ ustr_sc_free2(&s2, ustr_dup_buf(ustr_cstr(s2), ustr_len(s2))); s3 = ustr_dup_cstr("s3 abcd s2"); s4 = ustr_dup_empty(); /* always allocs */ ASSERT(s2); ASSERT(s3); ASSERT(s4); ASSERT(ustr_cmp_eq(s1, s4)); ASSERT(ustr_len(s1) == 0); ASSERT(ustr_len(s2) == 2); ASSERT(ustr_len(s3) == 10); ASSERT(ustr_len(s4) == 0); ASSERT(ustr_size(s1) == 0); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s2) == 2); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s3) == 12); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s4) == 0); ASSERT(ustr_srch_fwd(s3, 0, s2) == 9); ASSERT(ustr_srch_rev(s3, 0, s2) == 9); ASSERT(ustr_srch_fwd(s2, 0, s3) == 0); ASSERT(ustr_srch_rev(s2, 0, s3) == 0); ASSERT(ustr_add_cstr(&s2, "x")); ASSERT(ustr_len(s2) == 3); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s2) == 4); ASSERT(ustr_add_cstr(&s2, "y")); ASSERT(ustr_len(s2) == 4); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s2) == 4); ASSERT(ustr_add_cstr(&s2, "z")); ASSERT(ustr_len(s2) == 5); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s2) == 8); ASSERT(ustr_add_rep_chr(&s2, '-', 11)); ASSERT(ustr_len(s2) == 16); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s2) == 20); ASSERT(ustr_cmp_cstr_eq(s2, "s2xyz-----------")); ASSERT(!strcmp(ustr_cstr(s2), "s2xyz-----------")); ASSERT(ustr_srch_fwd(s3, 0, s2) == 0); ASSERT(ustr_srch_rev(s3, 0, s2) == 0); ASSERT(ustr_srch_fwd(s2, 0, s3) == 0); ASSERT(ustr_srch_rev(s2, 0, s3) == 0); /* NOTE: Using system *printf, so can't use %zu as Solaris is retarded */ ASSERT(ustr_add_fmt(&s1, "%s abcd %13.100s %d %c %lu%n", "------abc------", "", 42, 0, (unsigned long)ustr_len(s3), &num) != -1); ASSERT((unsigned)num == ustr_len(s1)); ASSERT(42 == num); if (!USTR_CONF_USE_EOS_MARK) ASSERT(44 == ustr_size(s1)); ASSERT(ustr_add_fmt(&s4, "%2$d%1$u", 2, 4)); ASSERT(ustr_srch_cstr_fwd(s1, 0, "abcd") == 17); ASSERT(ustr_srch_cstr_rev(s1, 0, "abcd") == 17); ASSERT(ustr_srch_cstr_fwd(s1, 0, "abc") == 7); ASSERT(ustr_srch_cstr_rev(s1, 0, "abc") == 17); ASSERT(ustr_srch_cstr_fwd(s1, 0, "10") == 41); ASSERT(ustr_srch_cstr_rev(s1, 0, "10") == 41); ASSERT(ustr_srch_chr_fwd(s1, 0, 0) == 39); ASSERT(ustr_srch_chr_rev(s1, 0, 0) == 39); ASSERT(ustr_srch_fwd(s1, 0, s4) == 36); ASSERT(ustr_srch_cstr_fwd(s1, 1, "abcd") == 17); ASSERT(ustr_srch_cstr_rev(s1, 1, "abcd") == 17); ASSERT(ustr_srch_cstr_fwd(s1, 10, "abcd") == 17); ASSERT(ustr_srch_cstr_rev(s1, 10, "abcd") == 17); ASSERT(ustr_srch_cstr_fwd(s1, 0, " ") == 16); ASSERT(ustr_srch_cstr_fwd(s1, 10, " ") == 16); ASSERT(ustr_srch_cstr_fwd(s1, 16, " ") == 21); ASSERT(ustr_srch_cstr_fwd(s1, 20, " ") == 21); ASSERT(ustr_srch_cstr_fwd(s1, 21, " ") == 22); ASSERT(ustr_srch_rep_chr_fwd(s1, 21, ' ', 1) == 22); ASSERT(ustr_srch_cstr_fwd(s1, 21, " ") == 22); ASSERT(ustr_srch_rep_chr_fwd(s1, 21, ' ', 2) == 22); ASSERT(ustr_srch_cstr_fwd(s1, 21, " ") == 22); ASSERT(ustr_srch_rep_chr_fwd(s1, 21, ' ', 3) == 22); ASSERT(ustr_srch_cstr_fwd(s1, 21, " ") == 22); ASSERT(ustr_srch_rep_chr_fwd(s1, 21, ' ', 4) == 22); ASSERT(ustr_srch_cstr_fwd(s1, 21, " ") == 22); ASSERT(ustr_srch_rep_chr_fwd(s1, 21, ' ', 5) == 22); ASSERT(ustr_srch_cstr_fwd(s1, 0, "a") == 7); ASSERT(ustr_srch_cstr_fwd(s1, 6, "a") == 7); ASSERT(ustr_srch_cstr_fwd(s1, 7, "a") == 17); ASSERT(ustr_srch_cstr_fwd(s1, 16, "a") == 17); ASSERT(ustr_srch_cstr_fwd(s1, 17, "a") == 0); ASSERT(ustr_srch_cstr_rev(s1, 0, "a") == 17); ASSERT(ustr_srch_cstr_rev(s1, ustr_len(s1) - 17, "a") == 17); ASSERT(ustr_srch_cstr_rev(s1, ustr_len(s1) - 16, "a") == 7); ASSERT(ustr_srch_cstr_rev(s1, ustr_len(s1) - 7, "a") == 7); ASSERT(ustr_srch_cstr_rev(s1, ustr_len(s1) - 6, "a") == 0); ASSERT(ustr_srch_cstr_rev(s1, ustr_len(s1) - 1, "a") == 0); /* srch_case */ ASSERT(ustr_srch_case_cstr_fwd(s1, 0, " ") == 16); ASSERT(ustr_srch_case_cstr_fwd(s1, 10, " ") == 16); ASSERT(ustr_srch_case_cstr_fwd(s1, 16, " ") == 21); ASSERT(ustr_srch_case_cstr_fwd(s1, 20, " ") == 21); ASSERT(ustr_srch_case_cstr_fwd(s1, 21, " ") == 22); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 21, ' ', 1) == 22); ASSERT(ustr_srch_case_cstr_fwd(s1, 21, " ") == 22); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 21, ' ', 2) == 22); ASSERT(ustr_srch_case_cstr_fwd(s1, 21, " ") == 22); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 21, ' ', 3) == 22); ASSERT(ustr_srch_case_cstr_fwd(s1, 21, " ") == 22); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 21, ' ', 4) == 22); ASSERT(ustr_srch_case_cstr_fwd(s1, 21, " ") == 22); ASSERT(ustr_srch_case_rep_chr_fwd(s1, 21, ' ', 5) == 22); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "a") == 7); ASSERT(ustr_srch_case_cstr_fwd(s1, 6, "a") == 7); ASSERT(ustr_srch_case_cstr_fwd(s1, 7, "a") == 17); ASSERT(ustr_srch_case_cstr_fwd(s1, 16, "a") == 17); ASSERT(ustr_srch_case_cstr_fwd(s1, 17, "a") == 0); ASSERT(ustr_srch_case_cstr_fwd(s1, 0, "A") == 7); ASSERT(ustr_srch_case_cstr_fwd(s1, 6, "A") == 7); ASSERT(ustr_srch_case_cstr_fwd(s1, 7, "A") == 17); ASSERT(ustr_srch_case_cstr_fwd(s1, 16, "A") == 17); ASSERT(ustr_srch_case_cstr_fwd(s1, 17, "A") == 0); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "a") == 17); ASSERT(ustr_srch_case_cstr_rev(s1, ustr_len(s1) - 17, "a") == 17); ASSERT(ustr_srch_case_cstr_rev(s1, ustr_len(s1) - 16, "a") == 7); ASSERT(ustr_srch_case_cstr_rev(s1, ustr_len(s1) - 7, "a") == 7); ASSERT(ustr_srch_case_cstr_rev(s1, ustr_len(s1) - 6, "a") == 0); ASSERT(ustr_srch_case_cstr_rev(s1, ustr_len(s1) - 1, "a") == 0); ASSERT(ustr_srch_case_cstr_rev(s1, 0, "A") == 17); ASSERT(ustr_srch_case_cstr_rev(s1, ustr_len(s1) - 17, "A") == 17); ASSERT(ustr_srch_case_cstr_rev(s1, ustr_len(s1) - 16, "A") == 7); ASSERT(ustr_srch_case_cstr_rev(s1, ustr_len(s1) - 7, "A") == 7); ASSERT(ustr_srch_case_cstr_rev(s1, ustr_len(s1) - 6, "A") == 0); ASSERT(ustr_srch_case_cstr_rev(s1, ustr_len(s1) - 1, "A") == 0); if (!USTR_DEBUG) ASSERT(ustr_srch_cstr_fwd(s1, ustr_len(s1), "a") == 0); if (!USTR_DEBUG) ASSERT(ustr_srch_cstr_rev(s1, ustr_len(s1), "a") == 0); /* puts(ustr_cstr(s4)); */ ustr_sc_free(&s3); ASSERT((s3 = ustr_dup(s4))); ASSERT(ustr_add_fmt(&s4, "x")); ustr_sc_free(&s4); ustr_sc_free(&s3); /* ASSERT(!ustr_assert_valid(USTR1(\x000F, "123456789 123456"))); ASSERT(!ustr_assert_valid(USTR1(\x000F, "123456789 1234\0xxx"))); */ ASSERT( ustr_assert_valid(USTR1(\x000F, "123456789 12345"))); /* ASSERT(!ustr_assert_valid(USTR1(\x000F, "123456789 12345\0xxx"))); */ s3 = ustr_dupx(0, 2, 0, 1, USTR1(\x000F, "123456789 12345")); ASSERT(ustr_cmp_cstr_eq(s3, "123456789 12345")); ASSERT(ustr_cmp_eq(s3, USTR1(\x000F, "123456789 12345"))); ASSERT(!ustr_ro(s3)); if (!USTR_CONF_USE_EOS_MARK) ASSERT(ustr_size(s3) == 19); ustr_sc_free(&s3); return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_12_fmt.c0000644000076400007640000001252710726332614014210 0ustar jamesjames#if defined(USTR_CONF_INCLUDE_CODEONLY_HEADERS) && \ USTR_CONF_INCLUDE_CODEONLY_HEADERS #define _GNU_SOURCE 1 #include #include #include #include # define USTR_CONF_VSNPRINTF_BEG tst_12_fmt_beg # define USTR_CONF_VSNPRINTF_END tst_12_fmt_end static int tst_12_fmt_beg(char *buf, size_t len, const char *fmt, va_list ap); static int tst_12_fmt_end(char *buf, size_t len, const char *fmt, va_list ap); #endif #include "tst.h" static const char *rf = __FILE__; static unsigned int tst__12_fmt_beg_count = 0; static int tst_12_fmt_beg(char *buf, size_t len, const char *fmt, va_list ap) { ++tst__12_fmt_beg_count; return vsnprintf(buf, len, fmt, ap); } static unsigned int tst__12_fmt_end_count = 0; static int tst_12_fmt_end(char *buf, size_t len, const char *fmt, va_list ap) { ++tst__12_fmt_end_count; return vsnprintf(buf, len, fmt, ap); } int tst(void) { Ustr_pool *pool = ustr_pool_ll_make(); Ustrp *sp1 = USTRP(""); Ustr *s3 = ustr_dupx_empty(0, 1, 0, 0); Ustr *s4 = USTR(""); Ustrp *sp3 = ustrp_dupx_empty(pool, 0, 1, 0, 0); Ustrp *sp4 = USTRP(""); #if !USTR_CONF_INCLUDE_CODEONLY_HEADERS Ustr_cntl_fmt ofmt; Ustr_cntl_fmt nfmt = {tst_12_fmt_beg, tst_12_fmt_end}; assert(ustr_cntl_opt(USTR_CNTL_OPT_GET_FMT, &ofmt) && ofmt.sys_vsnprintf_beg == vsnprintf && ofmt.sys_vsnprintf_end == vsnprintf); #endif ASSERT(pool); ASSERT(s3); ASSERT(ustr_set_rep_chr(&s4, '0', 1024)); ASSERT(ustrp_set_rep_chr(pool, &sp4, '0', 1024)); ustr_sc_free2(&s1, ustr_dup(s3)); ustr_sc_free2(&s1, ustr_dup(s3)); ustr_sc_free2(&s1, ustr_dup(s3)); ustr_sc_free2(&s1, ustr_dup(s3)); ustrp_sc_free2(pool, &sp1, ustrp_dup(pool, sp3)); ustrp_sc_free2(pool, &sp1, ustrp_dup(pool, sp3)); ustrp_sc_free2(pool, &sp1, ustrp_dup(pool, sp3)); ustrp_sc_free2(pool, &sp1, ustrp_dup(pool, sp3)); ASSERT(ustr_add_fmt_lim(&s1, 1, "%s", "12")); ASSERT_EQ(s1, USTR1(\x1, "1")); ASSERT(ustrp_add_fmt_lim(pool, &sp1, 1024, "%.2000d", 0)); ASSERT_PEQ(sp1, sp4); ustrp_sc_free2(pool, &sp1, ustrp_dup(pool, sp3)); ASSERT(ustrp_add_fmt(pool, &sp1, "%.1024d", 0)); ASSERT_PEQ(sp1, sp4); ustr_sc_free(&s1); ASSERT((s1 = ustr_dupx_fmt_lim(1, 1, 1, 0, 4, "%s", "12345678"))); ASSERT_EQ(s1, USTR1(\x4, "1234")); ustrp_sc_free(pool, &sp1); ASSERT((sp1 = ustrp_dupx_fmt_lim(pool, 1, 1, 1, 0, 4, "%s", "12345678"))); ASSERT_PEQ(sp1, USTRP1(\x4, "1234")); ustr_sc_free(&s1); ASSERT((s1 = ustr_dupx_fmt(1, 1, 1, 0, "%s", "12345678"))); ASSERT_EQ(s1, USTR1(\x8, "12345678")); ustrp_sc_free(pool, &sp1); ASSERT((sp1 = ustrp_dupx_fmt(pool, 1, 1, 1, 0, "%s", "12345678"))); ASSERT_PEQ(sp1, USTRP1(\x8, "12345678")); ustr_sc_free(&s1); ASSERT((s1 = ustr_dup_fmt_lim(4, "%s", "12345678"))); ASSERT_EQ(s1, USTR1(\x4, "1234")); ustrp_sc_free(pool, &sp1); ASSERT((sp1 = ustrp_dup_fmt_lim(pool, 4, "%s", "12345678"))); ASSERT_PEQ(sp1, USTRP1(\x4, "1234")); ustr_sc_free(&s1); ASSERT((s1 = ustr_dup_fmt("%s", "12345678"))); ASSERT_EQ(s1, USTR1(\x8, "12345678")); ustrp_sc_free(pool, &sp1); ASSERT((sp1 = ustrp_dup_fmt(pool, "%s", "12345678"))); ASSERT_PEQ(sp1, USTRP1(\x8, "12345678")); ASSERT(ustr_set_undef(&s1, 400)); ASSERT(ustrp_set_undef(pool, &sp1, 400)); ASSERT(ustr_set_fmt(&s1, "%s", "12345678")); ASSERT_EQ(s1, USTR1(\x8, "12345678")); ASSERT(ustrp_set_fmt(pool, &sp1, "%s", "12345678")); ASSERT_PEQ(sp1, USTRP1(\x8, "12345678")); ASSERT(ustr_set_fmt_lim(&s1, 2, "%s", "12345678")); ASSERT_EQ(s1, USTR1(\x2, "12")); ASSERT(ustrp_set_fmt_lim(pool, &sp1, 2, "%s", "12345678")); ASSERT_PEQ(sp1, USTRP1(\x2, "12")); ASSERT(ustr_set_fmt_lim(&s1, 4, "%s", "12345678")); ASSERT_EQ(s1, USTR1(\x4, "1234")); ASSERT(ustrp_set_fmt_lim(pool, &sp1, 4, "%s", "12345678")); ASSERT_PEQ(sp1, USTRP1(\x4, "1234")); ASSERT(ustr_set_empty(&s1)); ASSERT(ustrp_set_empty(pool, &sp1)); ASSERT(ustrp_set_cstr(pool, &sp1, "abcd")); ASSERT_PEQ(sp1, USTRP1(\x4, "abcd")); ASSERT(ustrp_set(pool, &sp1, USTRP1(\x3, "xyz"))); ASSERT_PEQ(sp1, USTRP1(\x3, "xyz")); ustr_sc_free2(&s1, USTR1(\x3, "xyz")); ASSERT(ustr_set_subustr(&s1, s1, 2, 1)); ASSERT_EQ(s1, USTR1(\x1, "y")); ASSERT(ustrp_set_subustrp(pool, &sp1, sp1, 2, 1)); ASSERT_PEQ(sp1, USTRP1(\x1, "y")); ustr_pool_free(pool); ustr_sc_free(&s3); ustr_sc_free(&s4); ASSERT(ustr_set_fmt(&s1, "%s%d%*s%d%s", "a", 4, 128, "b", 8, "c")); ASSERT(ustr_set_fmt(&s2, "%s%d%s%d%s", "a", 4, "b", 8, "c")); #if USTR_CONF_INCLUDE_CODEONLY_HEADERS ASSERT(tst__12_fmt_beg_count && tst__12_fmt_end_count); #else ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_SET_FMT, &nfmt)); assert(ustr_cntl_opt(USTR_CNTL_OPT_GET_FMT, &ofmt) && ofmt.sys_vsnprintf_beg == nfmt.sys_vsnprintf_beg && ofmt.sys_vsnprintf_end == nfmt.sys_vsnprintf_end); ASSERT(!tst__12_fmt_beg_count && !tst__12_fmt_end_count); #endif tst__12_fmt_beg_count = 0; tst__12_fmt_end_count = 0; ASSERT((s3 = ustr_dup_fmt("%s%d%*s%d%s", "a", 4, 128, "b", 8, "c"))); ASSERT(tst__12_fmt_beg_count == 1); ASSERT(tst__12_fmt_end_count == 1); ASSERT_EQ(s1, s3); ASSERT((s4 = ustr_dup_fmt("%s%d%s%d%s", "a", 4, "b", 8, "c"))); ASSERT(tst__12_fmt_beg_count == 2); ASSERT(tst__12_fmt_end_count == 1); ASSERT_EQ(s2, s4); ustr_sc_free(&s3); ustr_sc_free(&s4); return (EXIT_SUCCESS); } ustr-1.0.4/T/octst_10_b.c0000644000076400007640000000472410630111754014012 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { Ustr_pool *pool = ustr_pool_make(); Ustrp *sp1 = USTRP(""); unsigned int u16[9] = { 0, 1, 2, 3, 0x00FF, 0x0F0F, 0xF0F0, 0xFF00, 0xFFFF}; unsigned int u32[9] = { 0x12345678U, 0x87654321U, 0x01234567U, 0x76543210U, 0xFF00FF00U, 0xF0F0F0F0U, 0x0F0F0F0FU, 0x00FF00FFU, 0xFFFFFFFFU }; unsigned long long u64[7] = { 0x0123456789abcdefULL, 0xfedcba9876543210ULL, 0x00FF00FF00FF00FFULL, 0xFF00FF00FF00FF00ULL, 0x0F0F0F0F0F0F0F0FULL, 0xF0F0F0F0F0F0F0F0ULL, 0xFFFFFFFFFFFFFFFFULL }; size_t num = 0; size_t off = 0; num = 0; while (num < 9) { ustr_add_b_uint16(&s1, u16[num]); ustrp_add_b_uint16(pool, &sp1, u16[num]); ustr_add_b_uint32(&s1, u16[num]); ustrp_add_b_uint32(pool, &sp1, u16[num]); ustr_add_b_uint64(&s1, u16[num]); ustrp_add_b_uint64(pool, &sp1, u16[num]); ++num; } num = 0; while (num < 9) { ustr_add_b_uint32(&s1, u32[num]); ustrp_add_b_uint32(pool, &sp1, u32[num]); ustr_add_b_uint64(&s1, u32[num]); ustrp_add_b_uint64(pool, &sp1, u32[num]); ++num; } num = 0; while (num < 7) { ustr_add_b_uint64(&s1, u64[num]); ustrp_add_b_uint64(pool, &sp1, u64[num]); ++num; } ASSERT(!ustr_enomem(s1)); ASSERT(!ustrp_enomem(sp1)); /* parse the numbers out again ... */ num = 0; off = 1; while (num < 9) { ASSERT(u16[num] == ustr_parse_b_uint16(s1, off)); ASSERT(u16[num] == ustrp_parse_b_uint16(sp1, off)); off += 2; ASSERT(u16[num] == ustr_parse_b_uint32(s1, off)); ASSERT(u16[num] == ustrp_parse_b_uint32(sp1, off)); off += 4; ASSERT(u16[num] == ustr_parse_b_uint64(s1, off)); ASSERT(u16[num] == ustrp_parse_b_uint64(sp1, off)); off += 8; ++num; } num = 0; while (num < 9) { ASSERT(u32[num] == ustr_parse_b_uint32(s1, off)); ASSERT(u32[num] == ustrp_parse_b_uint32(sp1, off)); off += 4; ASSERT(u32[num] == ustr_parse_b_uint64(s1, off)); ASSERT(u32[num] == ustrp_parse_b_uint64(sp1, off)); off += 8; ++num; } num = 0; while (num < 7) { ASSERT(u64[num] == ustr_parse_b_uint64(s1, off)); ASSERT(u64[num] == ustrp_parse_b_uint64(sp1, off)); off += 8; ++num; } ustr_pool_free(pool); return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_19_concat.c0000644000076400007640000000362510755653303014702 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { Ustr_pool *pool = ustr_pool_ll_make(); Ustr *tmp = ustr_sc_concat(USTR(""), USTR(""), USTR(""), USTR_NULL); Ustrp *ptmp = ustrp_sc_concat(pool, USTRP(""),USTRP(""),USTRP(""),USTRP_NULL); ASSERT(tmp); ASSERT(!ustr_len(tmp)); ASSERT( ustr_ro(tmp)); ASSERT(ptmp); ASSERT(!ustrp_len(ptmp)); ASSERT( ustrp_ro(ptmp)); ASSERT((ptmp = ustrp_sc_concatx(pool, 1,1,1,1, USTRP(""), USTRP(""), USTRP(""), USTRP_NULL))); ASSERT(!ustrp_len(ptmp)); ASSERT(!ustrp_ro(ptmp)); tmp = ustr_sc_concat(USTR1(\4, "abcd"),USTR1(\4, "/xyz"),USTR(""), USTR_NULL); ASSERT(tmp); ASSERT_EQ(tmp, USTR1(\x8, "abcd/xyz")); ustr_free(tmp); tmp = ustr_sc_concat(USTR1(\4, "abcd"), USTR1(\4, "/xyz"), USTR(""), USTR1(\4, " ---"), USTR(""),USTR1(\4, "- 12"),USTR_NULL); ASSERT(tmp); ASSERT_EQ(tmp, USTR1(\x10, "abcd/xyz ---- 12")); ustr_free(tmp); tmp = ustr_sc_concatx(1, 1, 1, 1, USTR1(\4, "abcd"),USTR1(\4, "/xyz"),USTR(""),USTR_NULL); ASSERT(tmp); ASSERT(ustr_enomem(tmp)); ASSERT_EQ(tmp, USTR1(\x8, "abcd/xyz")); ustr_free(tmp); ptmp = ustrp_sc_concat(pool, USTRP(""), USTRP1(\4, "abcd"), USTRP1(\4, "/xyz"), USTRP_NULL); ASSERT(ptmp); ASSERT_PEQ(ptmp, USTRP1(\x8, "abcd/xyz")); ptmp = ustrp_sc_concat(pool, USTRP(""), USTRP1(\4, "abcd"), USTRP1(\4, "/xyz"), USTRP1(\4, " ---"), USTRP(""),USTRP1(\4, "- 12"), USTRP_NULL); ASSERT_PEQ(ptmp, USTRP1(\x10, "abcd/xyz ---- 12")); ptmp = ustrp_sc_concatx(pool, 1, 1, 1, 1, USTRP(""), USTRP1(\4, "abcd"), USTRP1(\4, "/xyz"), USTRP_NULL); ASSERT(ptmp); ASSERT(ustrp_enomem(ptmp)); ASSERT_PEQ(ptmp, USTRP1(\x8, "abcd/xyz")); ustr_pool_free(pool); return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_6_tiny.c0000644000076400007640000000000010630111754014301 0ustar jamesjamesustr-1.0.4/T/tst_5_shrink.c0000644000076400007640000000021510630111754014460 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 1 #define USTR_CONF_USE_EOS_MARK 0 #define ustr_cntl_opt(x, y) 0 /* return FALSE */ ustr-1.0.4/T/tst_17_sub.c0000644000076400007640000000000010646056563014043 0ustar jamesjamesustr-1.0.4/T/tst_14_cmp.c0000644000076400007640000000007210631117176014027 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 0 ustr-1.0.4/T/tst_12_fmt.c0000644000076400007640000000007210630111754014027 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 0 ustr-1.0.4/T/tst_0_nothing.c0000644000076400007640000000000010630111754014613 0ustar jamesjamesustr-1.0.4/T/ctst_11_io.c0000644000076400007640000002314210737776357014045 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; /* 1234567 */ static const Ustr *line1 = USTR1(\x11, "#include \"tst.h\"\n"); static const Ustr *line2 = USTR1(\x1, "\n"); static const Ustr *line3 = USTR1(\x22, "static const char *rf = __FILE__;\n"); static const Ustr *line4 = USTR1(\x1, "\n"); static const Ustr *line5 = USTR1(\xE, "/* 1234567 */\n"); static const Ustr *line999 = USTR1(\xa0, /* 160 */ "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 " "123456789 "); static void tst_getline(FILE *fp, int use_delim) { ustr_sc_del(&s1); ASSERT(!ustr_len(s1)); if (!use_delim) ASSERT(ustr_io_getline(&s1, fp)); else { ASSERT(ustr_io_getdelim(&s1, fp, '"')); ASSERT(ustr_cmp_cstr_eq(s1, "#include \"")); ASSERT(ustr_io_getdelim(&s1, fp, '"')); ASSERT(ustr_cmp_cstr_eq(s1, "#include \"tst.h\"")); ASSERT(ustr_io_getdelim(&s1, fp, '\n')); } ASSERT_EQ(s1, line1); ustr_sc_del(&s1); ASSERT(!ustr_len(s1)); ASSERT(ustr_io_getline(&s1, fp)); ASSERT_EQ(s1, line2); ustr_sc_del(&s1); ASSERT(!ustr_len(s1)); if (!use_delim) ASSERT(ustr_io_getline(&s1, fp)); else { ASSERT(ustr_io_getdelim(&s1, fp, ' ')); ASSERT(ustr_cmp_cstr_eq(s1, "static ")); ASSERT(ustr_io_getdelim(&s1, fp, ' ')); ASSERT(ustr_cmp_cstr_eq(s1, "static const ")); ASSERT(ustr_io_getdelim(&s1, fp, ' ')); ASSERT(ustr_cmp_cstr_eq(s1, "static const char ")); ASSERT(ustr_io_getdelim(&s1, fp, '=')); ASSERT(ustr_cmp_cstr_eq(s1, "static const char *rf =")); ASSERT(ustr_io_getdelim(&s1, fp, ' ')); ASSERT(ustr_cmp_cstr_eq(s1, "static const char *rf = ")); ASSERT(ustr_io_getdelim(&s1, fp, ';')); ASSERT(ustr_cmp_cstr_eq(s1, "static const char *rf = __FILE__;")); ASSERT(ustr_io_getdelim(&s1, fp, '\n')); } ASSERT_EQ(s1, line3); ustr_sc_del(&s1); ASSERT(!ustr_len(s1)); ASSERT(ustr_io_getline(&s1, fp)); ASSERT_EQ(s1, line4); ustr_sc_del(&s1); ASSERT(!ustr_len(s1)); if (!use_delim) ASSERT(ustr_io_getline(&s1, fp)); else { ASSERT(ustr_io_getdelim(&s1, fp, '/')); ASSERT(ustr_cmp_cstr_eq(s1, "/")); ASSERT(ustr_io_getdelim(&s1, fp, '/')); ASSERT(ustr_cmp_cstr_eq(s1, "/* 1234567 */")); ASSERT(ustr_io_getdelim(&s1, fp, '\n')); } ASSERT_EQ(s1, line5); ustr_sc_del(&s1); ASSERT(!ustr_len(s1)); } #include int tst(void) { Ustr_pool *pool = ustr_pool_ll_make(); Ustrp *sp1 = USTRP(""); FILE *fp = fopen("T/ctst_11_io.c", "rb"); size_t got = 1; int ret = EXIT_SUCCESS; ASSERT(pool); ASSERT(fp); ASSERT(!ustr_len(s1)); ASSERT(ustr_io_get(&s1, fp, 0, &got)); ASSERT(!got); ASSERT(!ustr_len(s1)); ASSERT(ustr_io_get(&s1, fp, 11, &got)); ASSERT(ustr_len(s1) == 11); ASSERT(got == 11); ASSERT(ustr_io_get(&s1, fp, 20, &got)); ASSERT(ustr_len(s1) == 31); ASSERT(got == 20); ASSERT(ustr_io_get(&s1, fp, 40, &got)); ASSERT(ustr_len(s1) == 71); ASSERT(got == 40); ASSERT(71 >= (ustr_len(line1) + ustr_len(line2) + ustr_len(line3) + ustr_len(line4) + ustr_len(line5))); ASSERT(ustr_cmp_subustr_eq(line1, s1, 1, ustr_len(line1))); ASSERT(ustr_del_subustr(&s1, 1, ustr_len(line1))); ASSERT(ustr_cmp_subustr_eq(line2, s1, 1, ustr_len(line2))); ASSERT(ustr_del_subustr(&s1, 1, ustr_len(line2))); ASSERT(ustr_cmp_subustr_eq(line3, s1, 1, ustr_len(line3))); ASSERT(ustr_del_subustr(&s1, 1, ustr_len(line3))); ASSERT(ustr_cmp_subustr_eq(line4, s1, 1, ustr_len(line4))); ASSERT(ustr_del_subustr(&s1, 1, ustr_len(line4))); ASSERT(ustr_cmp_subustr_eq(line5, s1, 1, ustr_len(line5))); ASSERT(ustr_del_subustr(&s1, 1, ustr_len(line5))); rewind(fp); ustr_sc_del(&s1); ASSERT(!ustr_len(s1)); ASSERT(ustr_io_getfilename(&s1, "T/ctst_11_io.c")); ASSERT(ustr_len(s1) >= 71); /* delete line3 first... */ ASSERT(ustr_cmp_subustr_eq(line3, s1, 1 + ustr_len(line1) + ustr_len(line2), ustr_len(line3))); ASSERT(ustr_del_subustr(&s1, 1 + ustr_len(line1) + ustr_len(line2), ustr_len(line3))); ASSERT(ustr_cmp_subustr_eq(line1, s1, 1, ustr_len(line1))); ASSERT(ustr_del_subustr(&s1, 1, ustr_len(line1))); ASSERT(ustr_cmp_subustr_eq(line2, s1, 1, ustr_len(line2))); ASSERT(ustr_del_subustr(&s1, 1, ustr_len(line2))); /* line 3 already gone */ ASSERT(ustr_cmp_subustr_eq(line4, s1, 1, ustr_len(line4))); ASSERT(ustr_del_subustr(&s1, 1, ustr_len(line4))); ASSERT(ustr_cmp_subustr_eq(line5, s1, 1, ustr_len(line5))); ASSERT(ustr_del_subustr(&s1, 1, ustr_len(line5))); rewind(fp); tst_getline(fp, USTR_FALSE); rewind(fp); tst_getline(fp, USTR_TRUE); ASSERT(ustr_io_getfile(&s1, fp)); ASSERT( ustr_len(s1)); ustr_sc_del(&s1); fclose(fp); ASSERT(ustr_set_fmt(&s2, "%s.out-tst-tmp", rf)); fp = fopen(ustr_cstr(s2), "w+b"); ASSERT(fp); ASSERT(ustr_set(&s1, line1)); ASSERT(ustr_io_put(&s1, fp, 1)); ASSERT(!ustr_cmp_subustr(s1, line1, 2, ustr_len(line1) - 1)); ASSERT(ustr_io_put(&s1, fp, 1)); ASSERT(ustr_cmp_subustr_eq(s1, line1, 3, ustr_len(line1) - 2)); ASSERT(ustr_io_putfile(&s1, fp)); ASSERT(!ustr_len(s1)); ustr_sc_free2(&s1, (Ustr *)line2); /* remove const, hackish */ ASSERT(ustr_io_putfile(&s1, fp)); ASSERT(!ustr_len(s1)); ASSERT(ustr_set(&s1, line3)); ASSERT(ustr_add(&s1, line4)); ASSERT(ustr_add(&s1, line5)); ASSERT(ustr_del(&s1, 1)); /* remove \n */ ASSERT( ustr_len(s1)); ASSERT(ustr_io_putfileline(&s1, fp)); ASSERT(!ustr_len(s1)); ASSERT((sp1 = ustrp_dup_empty(pool))); ASSERT(!ustrp_len(sp1)); ASSERT(ustrp_add(pool, &sp1, USTRP(line999))); ASSERT_PEQ(sp1, USTRP(line999)); ASSERT( ustrp_len(sp1)); ASSERT(ustrp_io_putfileline(pool, &sp1, fp)); ASSERT(!ustrp_len(sp1)); ASSERT(ustrp_io_putfile(pool, &sp1, fp)); rewind(fp); tst_getline(fp, USTR_FALSE); rewind(fp); tst_getline(fp, USTR_TRUE); ASSERT(ustr_io_getline(&s1, fp)); ASSERT(ustr_del(&s1, 1)); /* remove \n */ ASSERT_EQ(s1, line999); ustr_sc_del(&s1); ASSERT(ustr_io_getfile(&s1, fp)); ASSERT(!ustr_len(s1)); ASSERT(ustr_io_getfile(&s1, fp)); rewind(fp); ASSERT(ustr_set(&s1, line1)); ASSERT(ustr_add(&s1, line2)); ASSERT(ustr_add(&s1, line3)); ASSERT(ustr_add(&s1, line4)); ASSERT(ustr_add(&s1, line5)); ASSERT(ustr_add(&s1, line999)); ASSERT(ustr_add_cstr(&s1, "\n")); ASSERT(ustr_io_putfilename(&s1, ustr_cstr(s2), "wb")); rewind(fp); tst_getline(fp, USTR_FALSE); rewind(fp); tst_getline(fp, USTR_TRUE); ASSERT(ustr_io_getline(&s1, fp)); ASSERT(ustr_del(&s1, 1)); /* remove \n */ ASSERT_EQ(s1, line999); ASSERT(!ustr_io_getline(&s1, fp)); ASSERT_EQ(s1, line999); ustr_sc_del(&s1); ASSERT(!ustr_io_get(&s1, fp, 1, NULL)); ASSERT(ustr_io_getfile(&s1, fp)); ASSERT(!ustr_len(s1)); rewind(fp); ASSERT(ustrp_io_getline(pool, &sp1, fp)); ASSERT_EQ(&sp1->s, line1); ustrp_sc_del(pool, &sp1); ASSERT(ustrp_io_getdelim(pool, &sp1, fp, '\n')); ASSERT_EQ(&sp1->s, line2); ustrp_sc_del(pool, &sp1); ASSERT(ustrp_io_getline(pool, &sp1, fp)); ASSERT_EQ(&sp1->s, line3); ustrp_sc_del(pool, &sp1); ASSERT(ustrp_io_getline(pool, &sp1, fp)); ASSERT_EQ(&sp1->s, line4); ustrp_sc_del(pool, &sp1); ASSERT(ustrp_io_getline(pool, &sp1, fp)); ASSERT_EQ(&sp1->s, line5); ustrp_sc_del(pool, &sp1); ASSERT(ustrp_io_getfile(pool, &sp1, fp)); ASSERT(ustrp_del(pool, &sp1, 1)); /* remove \n */ ASSERT_EQ(&sp1->s, line999); ustrp_sc_del(pool, &sp1); ASSERT(!ustrp_io_get(pool, &sp1, fp, 1, NULL)); ASSERT(!ustrp_len(sp1)); ASSERT(ustrp_io_getfile(pool, &sp1, fp)); ASSERT(!ustrp_len(sp1)); fclose(fp); remove(ustr_cstr(s2)); ASSERT(!ustrp_io_getfilename(pool, &sp1, ustr_cstr(s2))); ustrp_sc_free2(pool, &sp1, USTRP("")); ASSERT(!ustrp_len(sp1)); ASSERT(ustrp_io_putfilename(pool, &sp1, ustr_cstr(s2), "wb")); ASSERT(!ustrp_len(sp1)); ASSERT(ustrp_io_getfilename(pool, &sp1, ustr_cstr(s2))); ASSERT(!ustrp_len(sp1)); remove(ustr_cstr(s2)); ASSERT(ustr_add_rep_chr(&s1, '-', 80 * 1000)); ASSERT(ustr_io_putfilename(&s1, ustr_cstr(s2), "wb")); ASSERT(!ustr_len(s1)); ASSERT(ustr_io_getfilename(&s1, ustr_cstr(s2))); ASSERT(ustr_len(s1) == (80 * 1000)); ASSERT(ustr_spn_cstr_fwd(s1, 0, "-") == (80 * 1000)); remove(ustr_cstr(s2)); ASSERT((sp1 = ustrp_dup_buf(pool, ustr_cstr(s2), ustr_len(s2)))); ASSERT(ustr_cmp_buf_eq(s2, ustrp_cstr(sp1), ustrp_len(sp1))); errno = 0; ASSERT(!ustr_io_putfilename(&s2, "doesn't exist.txt", "rb")); #ifdef __linux__ ASSERT(errno == ENOENT); #endif errno = 0; ASSERT(!ustr_io_putfilename(&s2, "./doesn't exist/foo.txt", "rb")); #ifdef __linux__ ASSERT(errno == ENOENT); #endif ASSERT(ustr_cmp_buf_eq(s2, ustrp_cstr(sp1), ustrp_len(sp1))); #ifdef ENOSPC do { FILE *filechk = fopen("/dev/full", "wb"); if (!filechk) /* some versions of mock didn't have it */ { ret = EXIT_FAILED_OK; break; } fclose(filechk); ASSERT(!ustr_io_putfilename(&s2, "/dev/full", "wb")); ASSERT(errno == ENOSPC); ASSERT(ustr_cmp_buf_eq(s2, ustrp_cstr(sp1), ustrp_len(sp1)) || !ustr_len(s2)); ASSERT(ustrp_add(pool, &sp1, sp1)); ASSERT(ustrp_add(pool, &sp1, sp1)); ASSERT(ustrp_add(pool, &sp1, sp1)); ASSERT(ustrp_add(pool, &sp1, sp1)); ASSERT(ustrp_add(pool, &sp1, sp1)); ASSERT(ustrp_add(pool, &sp1, sp1)); ASSERT(ustrp_add(pool, &sp1, sp1)); ASSERT(ustrp_add(pool, &sp1, sp1)); ASSERT(!ustrp_io_putfilename(pool, &sp1, "/dev/full", "wb")); ASSERT(errno == ENOSPC); } while (FALSE); #else ret = EXIT_FAILED_OK; #endif ustr_pool_free(pool); return (ret); } ustr-1.0.4/T/tst_3_medium.c0000644000076400007640000000022310630111754014437 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 2 #define USTR_CONF_USE_CONSTx_EOS_MARK 0 #define ustr_cntl_opt(x, y) 0 /* return FALSE */ ustr-1.0.4/T/ctst_7_auto.c0000644000076400007640000000755710653472524014331 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { char buf_s3[1024]; Ustr *s3 = USTR(buf_s3); char buf_s4[USTR_SIZE_FIXED(15)] = USTR_BEG_FIXED2 "abcd"; Ustr *s4 = USTR_SC_INIT_AUTO(buf_s4, USTR_TRUE, 4); memset(buf_s3, 'x', sizeof(buf_s3)); ASSERT(!ustr_init_size(1, 0, 0, USTR__SIZE_MAX)); if (USTR_CONF_HAVE_64bit_SIZE_MAX) ASSERT( ustr_init_size(0, 8, 1, 0)); ASSERT(!ustr_init_fixed(buf_s3, 1, USTR_TRUE, 0)); ASSERT(!ustr_init_fixed(buf_s3, 2, USTR_TRUE, 0)); ASSERT(!ustr_init_fixed(buf_s3, 4, USTR_TRUE, 0)); ASSERT(!ustr_init_fixed(buf_s3, 7, USTR_TRUE, 0)); if (sizeof(USTR_END_FIXEDx) == 1) ASSERT(s3 == ustr_init_fixed(buf_s3, 8, USTR_TRUE, 0)); memset(buf_s3, 'x', sizeof(buf_s3)); ASSERT(s3 == ustr_init_fixed(buf_s3, sizeof(buf_s3), USTR_FALSE, 0)); ASSERT(s4 == USTR(buf_s4)); ASSERT(!ustr_limited(s3)); ASSERT( ustr_limited(s4)); ASSERT(ustr_size(s3) == (sizeof(buf_s3) - ustr_size_overhead(s3))); ASSERT(ustr_size(s4) == (sizeof(buf_s4) - ustr_size_overhead(s4))); ASSERT(ustr_size(s4) == 15); ASSERT(ustr_size_alloc(s4) == sizeof(buf_s4)); ASSERT(ustr_len(s3) == 0); ASSERT(ustr_len(s4) == 4); ASSERT(ustr_cmp_eq(s3, USTR1(\x0, ""))); ASSERT(ustr_cmp_eq(s4, USTR1(\x4, "abcd"))); ustr_del(&s4, 4); ASSERT(ustr_add(&s4, USTR1(\x4, "abcd"))); ASSERT(!ustr_add_rep_chr(&s4, 'Z', 32)); ASSERT( ustr_enomem(s4)); ASSERT( ustr_add(&s4, s2)); ASSERT(s4 == USTR(buf_s4)); ASSERT(ustr_len(s4) == 6); ASSERT(ustr_cmp_eq(s4, USTR1(\x6, "abcds2"))); ASSERT( ustr_add(&s3, s2)); ASSERT(s3 == USTR(buf_s3)); ASSERT(ustr_len(s3) == 2); ASSERT(ustr_cmp_eq(s3, s2)); ASSERT( ustr_set(&s3, s2)); ASSERT(s3 == USTR(buf_s3)); ASSERT(ustr_len(s3) == 2); ASSERT(ustr_cmp_eq(s3, s2)); ASSERT(s4 == USTR(buf_s4)); ustr_free(s3); /* does nothing */ ustr_free(s3); ustr_free(s3); ustr_free(s3); /* don't bother free'ing s4 */ ASSERT((s3 = ustr_dup(s3))); ASSERT(s3 != USTR(buf_s3)); ASSERT(ustr_alloc(s3)); ASSERT_EQ(s3, USTR(buf_s3)); ustr_free(s3); ASSERT((s4 = ustr_dup(s4))); ASSERT(s4 != USTR(buf_s4)); ASSERT(ustr_alloc(s4)); ASSERT_EQ(s4, USTR(buf_s4)); ustr_free(s4); strcpy(buf_s4, USTR_BEG_FIXED2 "abcd"); ASSERT((s3 = ustr_init_fixed(buf_s3, USTR_SIZE_FIXED(15), USTR_FALSE, 0))); ASSERT((s4 = USTR_SC_INIT_AUTO(buf_s4, USTR_TRUE, 4))); ASSERT_EQ(s3, USTR("")); ASSERT_EQ(s4, USTR1(\4, "abcd")); ASSERT(ustr_add_cstr(&s3, "abcd")); ASSERT_EQ(s3, USTR1(\4, "abcd")); ASSERT(!ustr_replace_cstr(&s4, "bc", "xxxxxxxxxxxxxxxx", 0)); ASSERT( ustr_replace_cstr(&s4, "bc", "xxxx", 0)); ASSERT_EQ(s4, USTR1(\6, "axxxxd")); ASSERT(!ustr_replace_rep_chr(&s4, 'x', 4, 'y', 32, 0)); ASSERT( ustr_replace_rep_chr(&s4, 'x', 4, 'y', 2, 0)); ASSERT_EQ(s4, USTR1(\4, "ayyd")); ASSERT( ustr_replace_rep_chr(&s4, 'y', 2, 'z', 2, 0)); ASSERT_EQ(s4, USTR1(\4, "azzd")); ustr_free(s4); ustr_free(s4); ASSERT(!ustr_alloc(s3)); ASSERT( ustr_fixed(s3)); ASSERT( ustr_replace_cstr(&s3, "bc", "xxxxxxxxxxxxxxxx", 0)); ASSERT( ustr_alloc(s3)); ASSERT(!ustr_fixed(s3)); ASSERT_EQ(s3, USTR1(\x12, "axxxxxxxxxxxxxxxxd")); ustr_free(s3); ASSERT((s3 = ustr_init_fixed(buf_s3, USTR_SIZE_FIXED(15), USTR_FALSE, 0))); ASSERT(!ustr_alloc(s3)); ASSERT( ustr_fixed(s3)); ASSERT(ustr_set_cstr(&s3, "xxxx")); ASSERT(!ustr_alloc(s3)); ASSERT( ustr_fixed(s3)); ASSERT_EQ(s3, USTR1(\4, "xxxx")); ASSERT( ustr_replace_cstr(&s3, "x", "yy", 0)); ASSERT(!ustr_alloc(s3)); ASSERT( ustr_fixed(s3)); ASSERT_EQ(s3, USTR1(\x8, "yyyyyyyy")); ASSERT(ustr_set_cstr(&s3, "xxxx")); ASSERT(!ustr_alloc(s3)); ASSERT( ustr_fixed(s3)); ASSERT_EQ(s3, USTR1(\4, "xxxx")); ASSERT( ustr_replace_rep_chr(&s3, 'x', 1, 'y', 2, 0)); ASSERT(!ustr_alloc(s3)); ASSERT( ustr_fixed(s3)); ASSERT_EQ(s3, USTR1(\x8, "yyyyyyyy")); return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_0_cntl.c0000644000076400007640000001000410710714464014263 0ustar jamesjames#include "ustr-debug.h" #define ASSERT(x) do { \ if (x) {} else { \ fprintf(stderr, " -=> ASSERT (%s) failed in (%s) from %d %s.\n", \ #x , __func__, __LINE__, __FILE__); \ abort(); } \ } while (0) static void my_mem_free(void *x) { free(x); } int main(void) { size_t rbytes = 0; int has_sz = -1; int exact_bytes = -1; int scrub = -1; Ustr_cntl_mem mymem_tst = {0,0,0}; Ustr_cntl_mem mymem = {0,0,0}; Ustr *s1 = USTR(""); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_REF_BYTES, &rbytes)); ASSERT(rbytes == 1); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_HAS_SIZE, &has_sz)); ASSERT(has_sz == 0); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_SET_HAS_SIZE, 1)); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_HAS_SIZE, &has_sz)); ASSERT(has_sz == 1); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_EXACT_BYTES, &exact_bytes)); ASSERT(exact_bytes == 0); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_SET_EXACT_BYTES, 1)); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_EXACT_BYTES, &exact_bytes)); ASSERT(exact_bytes == 1); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_M_SCRUB, &scrub)); ASSERT(scrub == 0); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_SET_MC_M_SCRUB, 1)); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_M_SCRUB, &scrub)); ASSERT(scrub == 1); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_F_SCRUB, &scrub)); ASSERT(scrub == 0); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_SET_MC_F_SCRUB, 1)); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_F_SCRUB, &scrub)); ASSERT(scrub == 1); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_R_SCRUB, &scrub)); ASSERT(scrub == 0); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_SET_MC_R_SCRUB, 1)); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_R_SCRUB, &scrub)); ASSERT(scrub == 1); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MEM, &mymem_tst)); ASSERT(mymem_tst.sys_malloc != malloc); ASSERT(mymem_tst.sys_realloc == realloc); ASSERT(mymem_tst.sys_free == free); if (USTR_CONF_USE_ASSERT) ASSERT(!setenv("USTR_CNTL_MC", "no", USTR_TRUE)); else ASSERT(!setenv("USTR_CNTL_MC", "foobar", USTR_TRUE)); ASSERT(ustr_sc_ensure_owner(&s1)); /* env testing done */ ustr_sc_free2(&s1, USTR("")); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_M_SCRUB, &scrub)); ASSERT(scrub == 1); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_F_SCRUB, &scrub)); ASSERT(scrub == 1); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_R_SCRUB, &scrub)); ASSERT(scrub == 1); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MEM, &mymem)); ASSERT(mymem.sys_malloc == malloc); ASSERT(mymem.sys_realloc == realloc); ASSERT(mymem.sys_free == free); mymem.sys_free = my_mem_free; ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_SET_MEM, &mymem)); mymem.sys_malloc = 0; mymem.sys_realloc = 0; mymem.sys_free = 0; ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MEM, &mymem)); ASSERT(mymem.sys_malloc == malloc); ASSERT(mymem.sys_realloc == realloc); ASSERT(mymem.sys_free == my_mem_free); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_SET_MEM, &mymem_tst)); ASSERT(!setenv("USTR_CNTL_MC", "yes", USTR_TRUE)); ASSERT(!setenv("USTR_CNTL_MC_M_SCRUB", "no", USTR_TRUE)); ASSERT(!setenv("USTR_CNTL_MC_F_SCRUB", "no", USTR_TRUE)); ASSERT(!setenv("USTR_CNTL_MC_R_SCRUB", "no", USTR_TRUE)); ASSERT(ustr_sc_ensure_owner(&s1)); /* env testing done, again */ ustr_sc_free2(&s1, USTR("")); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_M_SCRUB, &scrub)); ASSERT(scrub == 0); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_F_SCRUB, &scrub)); ASSERT(scrub == 0); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MC_R_SCRUB, &scrub)); ASSERT(scrub == 0); ASSERT(ustr_cntl_opt(USTR_CNTL_OPT_GET_MEM, &mymem)); ASSERT(mymem.sys_malloc != malloc); ASSERT(mymem.sys_realloc != realloc); ASSERT(mymem.sys_free != free); if (!USTR_DEBUG) ASSERT(!ustr_cntl_opt(-1, &mymem)); ustr_free(s1); USTR_CNTL_MALLOC_CHECK_END(); return 0; } ustr-1.0.4/T/ctst_99_64bit.c0000644000076400007640000000736210760666456014406 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; #ifdef __linux__ #include #include #include #endif static int big_tst(size_t fsz, size_t usz, int hack, int tst_add) { #ifdef __linux__ int fd = -1; void *ptr = NULL; Ustr *s3 = NULL; ASSERT(ustr_set_cstr(&s2, "/tmp/ustr-build-tst-XXXXXX")); if ((fd = mkstemp(ustr_wstr(s2))) == -1) goto fail_mkstemp; unlink(ustr_cstr(s2)); usz /= 2; usz += 60; ASSERT(usz); if (!fsz) fsz = usz; if (ftruncate(fd, fsz) == -1) goto fail_ftrunc; ptr = mmap(0, fsz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) goto fail_mmap; memset(ptr, '-', ((fsz < 32) ? fsz : 32)); if (hack) { if (USTR_DEBUG) goto fail_init; #if ! USTR_CONF_INCLUDE_INTERNAL_HEADERS goto fail_init; #else /* massive hack, ustr_assert_valid() fails here, as we aren't terminating */ s3 = ptr; s3->data[0] = USTR__BIT_ALLOCD | USTR__BIT_HAS_SZ | USTR__BIT_NEXACT; if (!USTR_CONF_HAVE_64bit_SIZE_MAX) s3->data[0] |= (1 << 2) | 1; else s3->data[0] |= (2 << 2) | 2; ustr__sz_set(s3, usz); ustr__len_set(s3, usz - 59); ustr__ref_set(s3, 1); #endif } else { if (!(s3 = ustr_init_alloc(ptr, usz, 0, 0, 0, 0, usz - 59))) goto fail_init; } ASSERT(ustr_sized(s3)); if (tst_add) { ASSERT(!ustr_add(&s3, s3)); ASSERT(!ustr_replace(&s3, USTR1(\1, "-"), s3, 0)); ASSERT(!ustr_replace_rep_chr(&s3, '-', 1, 'x', usz, 0)); } munmap(ptr, fsz); close(fd); /* ignore it because it wasn't actually allocated from the system */ return (EXIT_SUCCESS); fail_init: fail_mmap: fail_ftrunc: close(fd); fail_mkstemp: return (EXIT_FAILED_OK); #endif } int tst(void) { size_t end = USTR__SIZE_MAX; size_t large = 1; size_t small = 4096; size_t num = 0; Ustr *s3 = USTR1(\3, "124"); ASSERT((s1 = ustr_dupx_empty(0, 0, 0, 0))); ASSERT(ustr_size_alloc(s1) > 0); /* max 32bit overhead */ while (num < (1 + 4 + sizeof(USTR_END_ALOCDx))) { ASSERT(!ustr_add_undef(&s1, end - num)); ASSERT(!ustr_dup_undef( end - num)); ASSERT(!ustr_ins_undef(&s3, 1, end - num)); ASSERT(!ustr_set_undef(&s1, end - num)); ++num; } while (num < (1 + 4 + sizeof(USTR_END_ALOCDx) + ustr_len(s3))) { ASSERT(!ustr_ins_undef(&s3, 1, end - num)); ++num; } num = (1 + 4 + sizeof(USTR_END_ALOCDx)); if (!USTR_CONF_HAVE_64bit_SIZE_MAX) { big_tst(small, end, USTR_TRUE, USTR_TRUE); big_tst( 0, end, USTR_TRUE, USTR_TRUE); return (EXIT_FAILED_OK); } /* max 64bit overhead */ while (num < (1 + 2 + 8 + 8 + sizeof(USTR_END_ALOCDx))) { ASSERT(!ustr_add_undef(&s1, end - num)); ASSERT(!ustr_dup_undef( end - num)); ASSERT(!ustr_ins_undef(&s3, 1, end - num)); ASSERT(!ustr_set_undef(&s1, end - num)); ++num; } while (num < (1 + 2 + 8 + 8 + sizeof(USTR_END_ALOCDx) + ustr_len(s3))) { ASSERT(!ustr_ins_undef(&s3, 1, end - num)); ++num; } ustr_free(s1); if (USTR_CONF_USE_DYNAMIC_CONF) { assert(ustr_cntl_opt(USTR_CNTL_OPT_SET_REF_BYTES, 8)); assert(ustr_cntl_opt(USTR_CNTL_OPT_SET_HAS_SIZE, 0)); ASSERT((s1 = ustr_dupx_undef(0, 8, 0, 0, 0))); ASSERT(ustr_ro(s1)); ASSERT((s1 = ustr_dupx_undef(1, 8, 0, 0, 0))); ASSERT(ustr_ro(s1)); } ASSERT((s1 = ustr_dupx_empty(0, 8, USTR_FALSE, USTR_FALSE))); ASSERT(ustr_sized(s1)); ASSERT(ustr_size_alloc(s1) >= 14); ASSERT(ustr_size_overhead(s1) >= 14); ustr_free(ustr_dup(s1)); big_tst(small, end, USTR_TRUE, USTR_TRUE); big_tst( 0, end, USTR_TRUE, USTR_TRUE); large *= 1024; large *= 1024; large *= 1024; large *= 9; return (big_tst(0, large, USTR_FALSE, USTR_FALSE)); } ustr-1.0.4/T/ctst_8_spn.c0000644000076400007640000001217110755352447014152 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { Ustr *s3 = ustr_dup_cstr("abcdefg xxxx xxxx xxxx xxxx1234yyyy yyyy yyyy zzz"); Ustr *s4 = NULL; Ustr *s5 = NULL; ASSERT(s3); ASSERT(ustr_spn_cstr_fwd(s3, 0, "abcd") == 4); ASSERT(ustr_spn_cstr_fwd(s3, 0, "abcdefg ") == 8); ASSERT(ustr_spn_cstr_fwd(s3, 0, "abcdefg x") == 27); ASSERT(ustr_cspn_cstr_fwd(s3, 0, "x") == 8); ASSERT(ustr_cspn_cstr_fwd(s3, 0, "21") == 27); ASSERT(ustr_spn_cstr_rev(s3, 0, "z") == 3); ASSERT(ustr_spn_cstr_rev(s3, 0, "az") == 3); ASSERT(ustr_spn_cstr_rev(s3, 0, "ayz") == 3); ASSERT(ustr_spn_cstr_rev(s3, 0, "ayz ") == 18); ASSERT(ustr_cspn_cstr_rev(s3, 0, "34") == 18); ASSERT(ustr_cspn_cstr_rev(s3, 0, " ") == 3); ASSERT(ustr_cspn_cstr_rev(s3, 0, "x") == 22); ASSERT(ustr_spn_cstr_fwd(s3, 0, " xayzafg1234bcde ") == ustr_len(s3)); ASSERT(ustr_spn_cstr_rev(s3, 0, "1234abcdefg xayz ") == ustr_len(s3)); ASSERT(ustr_cspn_cstr_fwd(s3, 0, "!") == ustr_len(s3)); ASSERT(ustr_cspn_cstr_rev(s3, 0, "!") == ustr_len(s3)); ASSERT(ustr_cspn_cstr_fwd(s3, 0, "!@#") == ustr_len(s3)); ASSERT(ustr_cspn_cstr_rev(s3, 0, "!@#") == ustr_len(s3)); ASSERT((s4 = ustr_dup_subustr(s3, 1, ustr_spn_cstr_fwd(s3, 0, "abcdefg ")))); ASSERT(ustr_del_subustr(&s3, 1, ustr_len(s4))); ASSERT((s5 = ustr_dup(s4))); ASSERT((s5 = ustr_dup(s4))); ASSERT(ustr_set_subustr(&s5, s3, 1, ustr_spn_cstr_fwd(s3, 0, "x "))); ASSERT(ustr_del_subustr(&s3, 1, ustr_len(s5))); ASSERT(ustr_spn_cstr_fwd(s4, 0, "abcd") == 4); ASSERT(ustr_spn_cstr_fwd(s4, 0, "abcdefg ") == 8); ASSERT(ustr_spn_cstr_fwd(s4, 1, "abcdefg ") == 7); ASSERT(ustr_spn_cstr_fwd(s4, 2, "abcdefg ") == 6); ASSERT(ustr_spn_cstr_fwd(s4, 3, "abcdefg ") == 5); ASSERT(ustr_spn_cstr_fwd(s4, 4, "abcdefg ") == 4); ASSERT(ustr_spn_cstr_fwd(s4, 5, "abcdefg ") == 3); ASSERT(ustr_spn_cstr_fwd(s4, 6, "abcdefg ") == 2); ASSERT(ustr_spn_cstr_fwd(s4, 7, "abcdefg ") == 1); ASSERT(ustr_spn_cstr_fwd(s4, 8, "abcdefg ") == 0); ASSERT(ustr_spn_cstr_rev(s3, 0, "z") == 3); ASSERT(ustr_spn_cstr_rev(s3, 4, "y") == 4); ASSERT(ustr_spn_cstr_rev(s3, 0, "az") == 3); ASSERT(ustr_spn_cstr_rev(s3, 0, "ayz") == 3); ASSERT(ustr_spn_cstr_rev(s3, 0, "ayz ") == 18); ASSERT(ustr_spn_cstr_rev(s3, 0, "y ") == 0); ASSERT(ustr_spn_cstr_rev(s3, 1, "y ") == 0); ASSERT(ustr_spn_cstr_rev(s3, 2, "y ") == 0); ASSERT(ustr_spn_cstr_rev(s3, 3, "y ") == 15); ASSERT(ustr_spn_cstr_rev(s3, 4, "y ") == 14); ASSERT(ustr_spn_cstr_rev(s3, 5, "y ") == 13); ASSERT(ustr_spn_cstr_rev(s3, 6, "y ") == 12); ASSERT(ustr_spn_cstr_rev(s3, 7, "y ") == 11); ASSERT(ustr_spn_cstr_rev(s3, 8, "y ") == 10); ASSERT(ustr_spn_cstr_rev(s3, 9, "y ") == 9); ASSERT(ustr_cspn_cstr_fwd(s4, 0, "e") == 4); ASSERT(ustr_cspn_cstr_fwd(s4, 0, "!-") == 8); ASSERT(ustr_cspn_cstr_fwd(s4, 1, "!-") == 7); ASSERT(ustr_cspn_cstr_fwd(s4, 2, "!-") == 6); ASSERT(ustr_cspn_cstr_fwd(s4, 3, "!-") == 5); ASSERT(ustr_cspn_cstr_fwd(s4, 4, "!-") == 4); ASSERT(ustr_cspn_cstr_fwd(s4, 5, "!-") == 3); ASSERT(ustr_cspn_cstr_fwd(s4, 6, "!-") == 2); ASSERT(ustr_cspn_cstr_fwd(s4, 7, "!-") == 1); ASSERT(ustr_cspn_cstr_fwd(s4, 8, "!-") == 0); ASSERT(ustr_cspn_cstr_fwd(s4, 0, "!") == 8); ASSERT(ustr_cspn_cstr_fwd(s4, 1, "!") == 7); ASSERT(ustr_cspn_cstr_fwd(s4, 2, "!") == 6); ASSERT(ustr_cspn_cstr_fwd(s4, 3, "!") == 5); ASSERT(ustr_cspn_cstr_fwd(s4, 4, "!") == 4); ASSERT(ustr_cspn_cstr_fwd(s4, 5, "!") == 3); ASSERT(ustr_cspn_cstr_fwd(s4, 6, "!") == 2); ASSERT(ustr_cspn_cstr_fwd(s4, 7, "!") == 1); ASSERT(ustr_cspn_cstr_fwd(s4, 8, "!") == 0); ASSERT(ustr_cspn_cstr_rev(s4, 0, "e") == 3); ASSERT(ustr_cspn_cstr_rev(s4, 0, "!-") == 8); ASSERT(ustr_cspn_cstr_rev(s4, 1, "!-") == 7); ASSERT(ustr_cspn_cstr_rev(s4, 2, "!-") == 6); ASSERT(ustr_cspn_cstr_rev(s4, 3, "!-") == 5); ASSERT(ustr_cspn_cstr_rev(s4, 4, "!-") == 4); ASSERT(ustr_cspn_cstr_rev(s4, 5, "!-") == 3); ASSERT(ustr_cspn_cstr_rev(s4, 6, "!-") == 2); ASSERT(ustr_cspn_cstr_rev(s4, 7, "!-") == 1); ASSERT(ustr_cspn_cstr_rev(s4, 8, "!-") == 0); ASSERT(ustr_cspn_cstr_rev(s4, 0, "!") == 8); ASSERT(ustr_cspn_cstr_rev(s4, 1, "!") == 7); ASSERT(ustr_cspn_cstr_rev(s4, 2, "!") == 6); ASSERT(ustr_cspn_cstr_rev(s4, 3, "!") == 5); ASSERT(ustr_cspn_cstr_rev(s4, 4, "!") == 4); ASSERT(ustr_cspn_cstr_rev(s4, 5, "!") == 3); ASSERT(ustr_cspn_cstr_rev(s4, 6, "!") == 2); ASSERT(ustr_cspn_cstr_rev(s4, 7, "!") == 1); ASSERT(ustr_cspn_cstr_rev(s4, 8, "!") == 0); ASSERT(ustr_cspn_cstr_rev(s3, 0, "34") == 18); ASSERT(ustr_cspn_cstr_rev(s3, 0, " ") == 3); ASSERT(ustr_cspn_cstr_rev(s3, 0, "x") == 22); ASSERT(ustr_spn_cstr_fwd(s3, 0, "1") == 1); ASSERT(ustr_spn_cstr_fwd(s3, 0, "12") == 2); ASSERT(ustr_spn_cstr_fwd(s3, 0, "123") == 3); ASSERT(ustr_spn_cstr_fwd(s3, 0, "1234") == 4); ASSERT(ustr_spn_cstr_fwd(s3, 0, "1234y") == 8); ASSERT(ustr_del_subustr(&s3, 4, 4)); ASSERT(ustr_spn_cstr_fwd(s3, 0, "1234y") == 4); ustr_free(s3); ustr_free(s4); /* leaked, see above */ ustr_free(s4); ustr_free(s5); return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_9_ins.c0000644000076400007640000001013010760724463014132 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { ASSERT(ustr_ins_fmt(&s1, 0, "abcd %.4d xyz", 4)); ASSERT_EQ(s1, USTR1(\xd, "abcd 0004 xyz")); ASSERT(ustr_ins_fmt(&s2, 1, "abcd %.4d xyz", 4)); ASSERT_EQ(s2, USTR1(\xf, "sabcd 0004 xyz2")); ASSERT(ustr_ins_rep_chr(&s1, 4, '-', 2)); ASSERT_EQ(s1, USTR1(\xf, "abcd-- 0004 xyz")); ASSERT(ustr_ins_cstr(&s1, 5, "==")); ASSERT_EQ(s1, USTR1(\x11, "abcd-==- 0004 xyz")); ASSERT(ustr_ins(&s2, 5, USTR1(\2, "--"))); ASSERT_EQ(s2, USTR1(\x11, "sabcd-- 0004 xyz2")); ASSERT(ustr_ins_subustr(&s2, 6, USTR1(\5, "x-==-"), 3, 2)); ASSERT_EQ(s2, USTR1(\x13, "sabcd-==- 0004 xyz2")); ustr_sc_free2(&s1, USTR1(\4, "1234")); ASSERT(ustr_ins_fmt_lim(&s1, 2, 150, "%75s%-75sXYZ", "|", "|")); ASSERT(ustr_cmp_cstr_eq(s1, "12 || 34")); ASSERT(ustr_ins_fmt_lim(&s1, 75, 2, "%s%s", "", "")); ASSERT(ustr_ins_fmt_lim(&s1, 75, 1, "%s%s", "", "")); ASSERT(ustr_ins_fmt_lim(&s1, 75, 0, "%s%s", "", "")); ASSERT(ustr_cmp_cstr_eq(s1, "12 || 34")); ASSERT(ustr_len(s1) == 154); ASSERT(ustr_ins_undef(&s1, 2, 2)); ASSERT(ustr_len(s1) == 156); ASSERT(ustr_cmp_prefix_cstr_eq(s1, "12")); ASSERT(ustr_cmp_suffix_cstr_eq(s1, " || 34")); if (!USTR_DEBUG) ASSERT(!ustr_ins_subustr(&s1, 2, USTR1(\4, "1248"), 4, 2)); if (!USTR_DEBUG) ASSERT(!ustr_ins_subustr(&s1, 2, USTR1(\4, "1248"), 5, 1)); ustr_sc_free2(&s1, USTR1(\4, "abcd")); ASSERT(ustr_ins_subustr(&s1, 1, s1, 2, 2)); ASSERT_EQ(s1, USTR1(\6, "abcbcd")); ASSERT(ustr_ins_subustr(&s1, 3, s1, 1, 1)); ASSERT_EQ(s1, USTR1(\7, "abcabcd")); ASSERT(ustr_ins_subustr(&s1, 7, s1, 3, 1)); ASSERT_EQ(s1, USTR1(\x8, "abcabcdc")); ASSERT(ustr_ins_subustr(&s1, 7, s1, 4, 1)); ASSERT_EQ(s1, USTR1(\x9, "abcabcdac")); ASSERT(ustr_ins_subustr(&s1, 5, s1, 2, 8)); ASSERT_EQ(s1, USTR1(\x11, "abcabbcabcdaccdac")); ustr_set_cstr(&s1, "123"); ASSERT(ustr_ins(&s1, 0, s1)); ASSERT_EQ(s1, USTR1(\6, "123123")); ustr_set_cstr(&s1, "123"); ASSERT(ustr_ins(&s1, 1, s1)); ASSERT_EQ(s1, USTR1(\6, "112323")); ustr_set_cstr(&s1, "123"); ASSERT(ustr_ins(&s1, 2, s1)); ASSERT_EQ(s1, USTR1(\6, "121233")); ustr_set_cstr(&s1, "123"); ASSERT(ustr_ins(&s1, 3, s1)); ASSERT_EQ(s1, USTR1(\6, "123123")); ustr_set_cstr(&s1, "12"); ASSERT(ustr_ins_subustr(&s1, 0, s1, 1, 2)); ASSERT_EQ(s1, USTR1(\4, "1212")); ustr_set_cstr(&s1, "12"); ASSERT(ustr_ins_subustr(&s1, 1, s1, 1, 2)); ASSERT_EQ(s1, USTR1(\4, "1122")); ustr_set_cstr(&s1, "12"); ASSERT(ustr_ins_subustr(&s1, 2, s1, 1, 2)); ASSERT_EQ(s1, USTR1(\4, "1212")); ustr_set_cstr(&s1, "12"); ASSERT(ustr_ins_subustr(&s1, 0, s1, 1, 1)); ASSERT_EQ(s1, USTR1(\3, "112")); ustr_set_cstr(&s1, "12"); ASSERT(ustr_ins_subustr(&s1, 1, s1, 1, 1)); ASSERT_EQ(s1, USTR1(\3, "112")); ustr_set_cstr(&s1, "12"); ASSERT(ustr_ins_subustr(&s1, 2, s1, 1, 1)); ASSERT_EQ(s1, USTR1(\3, "121")); ustr_set_cstr(&s1, "12"); ASSERT(ustr_ins_subustr(&s1, 0, s1, 2, 1)); ASSERT_EQ(s1, USTR1(\3, "212")); ustr_set_cstr(&s1, "12"); ASSERT(ustr_ins_subustr(&s1, 1, s1, 2, 1)); ASSERT_EQ(s1, USTR1(\3, "122")); ustr_set_cstr(&s1, "12"); ASSERT(ustr_ins_subustr(&s1, 2, s1, 2, 1)); ASSERT_EQ(s1, USTR1(\3, "122")); ustr_set_cstr(&s1, "12"); ASSERT(ustr_ins_subustr(&s1, 0, s1, 2, 0)); ASSERT(ustr_ins_subustr(&s1, 1, s1, 2, 0)); ASSERT(ustr_ins_subustr(&s1, 2, s1, 2, 0)); ASSERT_EQ(s1, USTR1(\2, "12")); ustr_set_cstr(&s1, "123456789 "); ASSERT(ustr_ins(&s1, 4, s1)); ASSERT_EQ(s1, USTR1(\x14, "1234123456789 56789 ")); ustr_set_cstr(&s1, "123456789 "); ASSERT(ustr_ins_subustr(&s1, 8, s1, 6, 4)); ASSERT_EQ(s1, USTR1(\xe, "1234567867899 ")); return (EXIT_SUCCESS); } ustr-1.0.4/T/tst_16_parse.c0000644000076400007640000000007210636351163014365 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 0 ustr-1.0.4/T/tst_15_trim.c0000644000076400007640000000007010725544524014227 0ustar jamesjames#undef USTR_CONF_HAS_SIZE #define USTR_CONF_HAS_SIZE 1 ustr-1.0.4/T/ctst_98_pool.c0000644000076400007640000012146010711021354014374 0ustar jamesjames#define USTR_CONF_HAVE_ATTR_DEPRECATED 0 /* so we don't have warnings */ #include "tst.h" static const char *rf = __FILE__; static void *fail_malloc(size_t len) { (void)len; return NULL; } int tst(void) { Ustr_pool *pool = ustr_pool_ll_make(); Ustr_pool *p1 = NULL; Ustr_pool *p2 = NULL; Ustr_pool *p3 = NULL; Ustrp *sp1 = ustrp_dup_empty(pool); Ustrp *sp2 = USTRP1(\x2, "s2"); char buf_spa[1024]; Ustrp *spa = USTRP_SC_INIT_AUTO(buf_spa, USTR_FALSE, 0); size_t off = 0; ustr_pool_free(ustr_pool_make_pool()); /* compat. call */ #if USTR_CONF_INCLUDE_INTERNAL_HEADERS ASSERT( ((struct Ustr__pool_ll_base *)pool)->beg); ASSERT( ((struct Ustr__pool_ll_base *)pool)->beg->ptr == sp1); ASSERT(!((struct Ustr__pool_ll_base *)pool)->beg->next); #endif ASSERT(pool->pool_sys_realloc(pool, NULL, 0, 0)); ASSERT(pool->pool_sys_realloc(pool, NULL, 0, 1)); ASSERT( ustrp_size_alloc(sp1)); ASSERT( ustrp_size_alloc(sp2) >= 4); ASSERT(spa == (void *)buf_spa); ASSERT(!ustrp_alloc(spa)); ASSERT( ustrp_owner(spa)); ASSERT( ustrp_fixed(spa)); ASSERT(!ustrp_limited(spa)); ASSERT(!ustrp_ro(spa)); ASSERT((ustrp_size(spa) + ustrp_size_overhead(spa)) == sizeof(buf_spa)); ASSERT(ustrp_size_alloc(spa) == sizeof(buf_spa)); ASSERT( ustrp_set_rep_chr(pool, &spa, '-', 2000)); ASSERT(!ustrp_enomem(spa)); ASSERT(spa != (void *)buf_spa); ASSERT(ustrp_set_empty(pool, &spa)); ASSERT(ustrp_set(pool, &spa, spa)); ASSERT((spa = USTRP_SC_INIT_AUTO(buf_spa, USTR_TRUE, 0))); ASSERT( ustrp_size_alloc(sp1)); ASSERT( ustrp_size_alloc(sp2) >= 4); ASSERT(spa == (void *)buf_spa); ASSERT(!ustrp_alloc(spa)); ASSERT( ustrp_owner(spa)); ASSERT( ustrp_fixed(spa)); ASSERT( ustrp_limited(spa)); ASSERT(!ustrp_ro(spa)); ASSERT((ustrp_size(spa) + ustrp_size_overhead(spa)) == sizeof(buf_spa)); ASSERT(ustrp_size_alloc(spa) == sizeof(buf_spa)); ASSERT(!ustrp_set_rep_chr(pool, &spa, '-', 2000)); ASSERT( ustrp_enomem(spa)); ASSERT(spa == (void *)buf_spa); ASSERT(ustrp_set_empty(pool, &spa)); ASSERT(ustrp_set(pool, &spa, spa)); ASSERT((spa = ustrp_init_alloc(buf_spa, sizeof(buf_spa), sizeof(buf_spa), 1, 1, 0, 0))); ASSERT(spa == (void *)buf_spa); ASSERT( ustrp_alloc(spa)); /* it _thinks so_ */ ASSERT( ustrp_owner(spa)); ASSERT(!ustrp_fixed(spa)); ASSERT(!ustrp_limited(spa)); ASSERT(!ustrp_ro(spa)); ASSERT((ustrp_size(spa) + ustrp_size_overhead(spa)) == sizeof(buf_spa)); ASSERT(ustrp_size_alloc(spa) == sizeof(buf_spa)); ASSERT((spa = ustrp_dup_rep_chr(pool, '-', 2000))); ASSERT(!ustrp_enomem(spa)); ASSERT(spa != (void *)buf_spa); ASSERT(ustrp_set_empty(pool, &spa)); ASSERT(ustrp_set(pool, &spa, spa)); ASSERT((spa = ustrp_dup_undef(pool, 0))); ASSERT(!ustrp_alloc(spa)); ASSERT(!ustrp_owner(spa)); ASSERT( ustrp_ro(spa)); ASSERT(ustrp_set_empty(pool, &spa)); ASSERT(ustrp_set(pool, &spa, spa)); ASSERT((spa = ustrp_dup_undef(pool, 0))); ASSERT(!ustrp_alloc(spa)); ASSERT(!ustrp_owner(spa)); ASSERT( ustrp_ro(spa)); ASSERT(ustrp_set(pool, &spa, spa)); if (!USTR_DEBUG) ASSERT(!ustrp_set_subustrp(pool, &spa, USTRP1(\x4, "abcd"), 1, 8)); ASSERT(ustrp_set_subustrp(pool, &spa, USTRP1(\x4, "abcd"), 1, 4)); ASSERT((spa = ustrp_dupx_empty(pool, 0, 1, 0, 0))); { size_t esz; size_t ref; int exact; size_t lenn; size_t refc; ustrp_conf(spa, NULL,NULL,NULL, NULL,NULL); ustrp_conf(spa, &esz,&ref,&exact, &lenn,&refc); ASSERT(!esz); ASSERT(ref == 1); ASSERT(!exact); ASSERT(lenn == 1); ASSERT(refc == 1); } assert(USTR_CNTL_MALLOC_CHECK_MEM_USTRP(spa)); ASSERT(ustrp_dup(pool, spa)); { size_t esz; size_t ref; int exact; size_t lenn; size_t refc; ustrp_conf(spa, NULL,NULL,NULL, NULL,NULL); ustrp_conf(spa, &esz,&ref,&exact, &lenn,&refc); ASSERT(!esz); ASSERT(ref == 1); ASSERT(!exact); ASSERT(lenn == 1); ASSERT(refc == 2); } ASSERT(ustrp_set(pool, &spa, USTRP1(\x4, "abcd"))); assert(USTR_CNTL_MALLOC_CHECK_MEM_USTRP(spa)); ASSERT(pool); ASSERT(!ustrp_ro(sp1)); ASSERT(ustrp_len(sp1) == 0); ASSERT((sp1 = ustrp_dup_fmt_lim(pool, 4000, "%.5000x", 0xdeadbeef))); ASSERT(!ustrp_ro(sp1)); ASSERT(ustrp_len(sp1) == 4000); ASSERT((sp1 = ustrp_dup_fmt(pool, "%.5000x", 0xdeadbeef))); ASSERT(ustrp_len(sp1) == 5000); ustrp_sc_del(pool, &sp1); ustr_pool_clear(pool); ASSERT(ustrp_len(sp1) == 0); ASSERT(ustrp_len(sp2) == 2); ASSERT(ustrp_assert_valid_subustrp(sp2, 1, 1)); ASSERT(ustrp_assert_valid_subustrp(sp2, 1, 2)); ASSERT(ustrp_assert_valid_subustrp(sp2, 2, 1)); ASSERT( ustrp_add_subustrp(pool, &sp1, sp2, 1, 1)); ASSERT(ustrp_len(sp1) == 1); if (!USTR_DEBUG) ASSERT(!ustrp_add_subustrp(pool, &sp1, sp2, 3, 1)); ASSERT(ustrp_len(sp1) == 1); if (!USTR_DEBUG) ASSERT(!ustrp_add_subustrp(pool, &sp1, sp2, 1, 3)); ASSERT(ustrp_len(sp1) == 1); ASSERT(ustrp_add_subustrp(pool, &sp1, sp2, 1, 2)); ASSERT(ustrp_len(sp1) == 3); ASSERT(ustrp_add_subustrp(pool, &sp1, sp1, 1, 3)); ASSERT(ustrp_len(sp1) == 6); ASSERT(ustrp_add_subustrp(pool, &sp1, sp1, 1, 3)); ASSERT(ustrp_len(sp1) == 9); ASSERT((sp1 = ustrp_dupx_subustrp(pool, 0, 0, 0, 0, sp2, 1, 0))); ASSERT(ustrp_len(sp1) == 0); { size_t esz; size_t ref; int exact; size_t lenn; size_t refc; ustrp_conf(sp1, NULL,NULL,NULL, NULL,NULL); ustrp_conf(sp1, &esz,&ref,&exact, &lenn,&refc); ASSERT(!esz); ASSERT(!ref); ASSERT(!exact); ASSERT(lenn == 1); ASSERT(refc == 0); } ASSERT((sp1 = ustrp_dupx_subustrp(pool, 1, 1, 1, 1, sp2, 1, 0))); ASSERT(ustrp_len(sp1) == 0); { size_t esz; size_t ref; int exact; size_t lenn; size_t refc; ustrp_conf(sp1, NULL,NULL,NULL, NULL,NULL); ustrp_conf(sp1, &esz,&ref,&exact, &lenn,&refc); ASSERT(esz == ustrp_size_alloc(sp1)); ASSERT(ref == 2); ASSERT(exact); ASSERT(lenn == 2); ASSERT(refc == 1); } ASSERT((sp1 = ustrp_dupx_subustrp(pool, 0, 0, 0, 0, sp2, 1, 2))); ASSERT(ustrp_len(sp1) == 2); ASSERT((sp1 = ustrp_dupx_subustrp(pool, 1, 1, 1, 1, sp2, 1, 2))); ASSERT(ustrp_len(sp1) == 2); ASSERT((sp1 = ustrp_dupx_subustrp(pool, 0, 0, 0, 0, sp2, 2, 1))); ASSERT(ustrp_len(sp1) == 1); ASSERT((sp1 = ustrp_dupx_subustrp(pool, 1, 1, 1, 1, sp2, 2, 1))); ASSERT(ustrp_len(sp1) == 1); if (!USTR_DEBUG) { ASSERT(!(sp1 = ustrp_dupx_subustrp(pool, 0, 0, 0, 0, sp2, 3, 1))); ASSERT(!(sp1 = ustrp_dupx_subustrp(pool, 1, 1, 1, 1, sp2, 3, 1))); ASSERT(!(sp1 = ustrp_dupx_subustrp(pool, 0, 0, 0, 0, sp2, 1, 3))); ASSERT(!(sp1 = ustrp_dupx_subustrp(pool, 1, 1, 1, 1, sp2, 1, 3))); ASSERT(!(sp1 = ustrp_dupx_subustrp(pool, 0, 0, 0, 0, sp2, 2, 2))); ASSERT(!(sp1 = ustrp_dupx_subustrp(pool, 1, 1, 1, 1, sp2, 2, 2))); } ustrp_sc_free2(pool, &sp1, USTRP("")); if (!USTR_DEBUG) { ASSERT(!ustrp_add_subustrp(pool, &sp1, sp2, 1, 3)); ASSERT(!ustrp_add_subustrp(pool, &sp1, sp2, 3, 1)); ASSERT(!ustrp_add_subustrp(pool, &sp1, sp2, 2, 2)); } ASSERT( ustrp_add_subustrp(pool, &sp1, sp2, 2, 1)); ASSERT_PEQ(sp1, USTRP1(\x1, "2")); ASSERT( ustrp_add_subustrp(pool, &sp1, sp2, 2, 1)); ASSERT_PEQ(sp1, USTRP1(\x2, "22")); ASSERT( ustrp_add_rep_chr(pool, &sp1, 'x', 18)); ASSERT_PEQ(sp1, USTRP1(\x14, "22xxxxxxxxxxxxxxxxxx")); /* throw away a Ustrp, so sp1 isn't the last */ ASSERT(ustrp_dupx_subustrp(pool, 1, 1, 1, 1, sp2, 2, 1)); ASSERT(ustrp_del(pool, &sp1, 15)); ASSERT_PEQ(sp1, USTRP1(\x5, "22xxx")); ASSERT( ustrp_add_rep_chr(pool, &sp1, 'y', 13)); ASSERT_PEQ(sp1, USTRP1(\x12, "22xxxyyyyyyyyyyyyy")); /* copy and paste between here and tst_2_small.c */ /* test some of the data ... */ /* spn */ ASSERT_PEQ(sp1, USTRP1(\x12, "22xxxyyyyyyyyyyyyy")); ASSERT(ustrp_spn_chr_fwd(sp1, 0, 'x') == 0); ASSERT(ustrp_spn_chr_fwd(sp1, 0, '2') == 2); ASSERT(ustrp_spn_cstr_fwd(sp1, 0, "2") == 2); ASSERT(ustrp_spn_cstr_fwd(sp1, 0, "22") == 2); ASSERT(ustrp_spn_cstr_fwd(sp1, 0, "2x") == 5); ASSERT(ustrp_spn_cstr_fwd(sp1, 0, "x2") == 5); ASSERT(ustrp_spn_cstr_fwd(sp1, 0, "x2y") == 18); ASSERT(ustrp_spn_fwd(sp1, 0, USTRP1(\x2, "22")) == 2); ASSERT(ustrp_spn_fwd(sp1, 0, USTRP1(\x2, "2x")) == 5); ASSERT(ustrp_spn_fwd(sp1, 0, USTRP1(\x2, "x2")) == 5); ASSERT(ustrp_spn_fwd(sp1, 0, USTRP1(\x3, "x2y")) == 18); ASSERT(ustrp_spn_cstr_rev(sp1, 0, "x2") == 0); ASSERT(ustrp_spn_cstr_rev(sp1, 0, "x2y") == 18); ASSERT(ustrp_spn_cstr_rev(sp1, 0, "2y") == 13); ASSERT(ustrp_spn_cstr_rev(sp1, 0, "y") == 13); ASSERT(ustrp_spn_rev(sp1, 0, USTRP1(\x2, "x2")) == 0); ASSERT(ustrp_spn_rev(sp1, 0, USTRP1(\x3, "x2y")) == 18); ASSERT(ustrp_spn_rev(sp1, 0, USTRP1(\x2, "2y")) == 13); ASSERT(ustrp_spn_rev(sp1, 0, USTRP1(\x1, "y")) == 13); ASSERT(ustrp_spn_chr_rev(sp1, 0, 'x') == 0); ASSERT(ustrp_spn_chr_rev(sp1, 0, 'y') == 13); ASSERT(ustrp_spn_cstr_rev(sp1, 0, "yx") == 16); ASSERT(ustrp_spn_cstr_rev(sp1, 0, "xy") == 16); /* cspn */ ASSERT_PEQ(sp1, USTRP1(\x12, "22xxxyyyyyyyyyyyyy")); ASSERT(ustrp_cspn_chr_fwd(sp1, 0, 'y') == 5); ASSERT(ustrp_cspn_chr_fwd(sp1, 0, 'x') == 2); ASSERT(ustrp_cspn_chr_fwd(sp1, 0, '2') == 0); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "2") == 0); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "y") == 5); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "22") == 0); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "x") == 2); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "xx") == 2); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "yx") == 2); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "xy") == 2); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "yz") == 5); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "zy") == 5); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x1, "2")) == 0); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x1, "y")) == 5); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x2, "22")) == 0); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x1, "x")) == 2); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x2, "xx")) == 2); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x2, "yx")) == 2); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x2, "xy")) == 2); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x2, "yz")) == 5); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x2, "zy")) == 5); ASSERT(ustrp_cspn_cstr_rev(sp1, 0, "2x") == 13); ASSERT(ustrp_cspn_cstr_rev(sp1, 0, "x2") == 13); ASSERT(ustrp_cspn_chr_rev(sp1, 0, '2') == 16); ASSERT(ustrp_cspn_cstr_rev(sp1, 0, "2") == 16); ASSERT(ustrp_cspn_cstr_rev(sp1, 0, "2a") == 16); ASSERT(ustrp_cspn_rev(sp1, 0, USTRP1(\x2, "2x")) == 13); ASSERT(ustrp_cspn_rev(sp1, 0, USTRP1(\x2, "x2")) == 13); ASSERT(ustrp_cspn_rev(sp1, 0, USTRP1(\x1, "2")) == 16); ASSERT(ustrp_cspn_rev(sp1, 0, USTRP1(\x2, "2a")) == 16); ASSERT(ustrp_cspn_chr_fwd(sp1, 0, 'a') == 18); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "a") == 18); ASSERT(ustrp_cspn_cstr_rev(sp1, 0, "a") == 18); ASSERT(ustrp_cspn_chr_rev(sp1, 0, 'a') == 18); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x1, "a")) == 18); ASSERT(ustrp_cspn_rev(sp1, 0, USTRP1(\x1, "a")) == 18); ASSERT(ustrp_cspn_cstr_fwd(sp1, 0, "abc") == 18); ASSERT(ustrp_cspn_cstr_rev(sp1, 0, "abc") == 18); ASSERT(ustrp_cspn_fwd(sp1, 0, USTRP1(\x3, "abc")) == 18); ASSERT(ustrp_cspn_rev(sp1, 0, USTRP1(\x3, "abc")) == 18); /* srch */ ASSERT_PEQ(sp1, USTRP1(\x12, "22xxxyyyyyyyyyyyyy")); ASSERT(ustrp_srch_cstr_fwd(sp1, 0, "xy") == 5); ASSERT(ustrp_srch_cstr_rev(sp1, 0, "xy") == 5); ASSERT(ustrp_srch_fwd(sp1, 0, USTRP1(\x2, "xy")) == 5); ASSERT(ustrp_srch_rev(sp1, 0, USTRP1(\x2, "xy")) == 5); ASSERT(ustrp_srch_subustrp_fwd(sp1, 0, USTRP1(\x2, "xy"), 1, 2) == 5); ASSERT(ustrp_srch_subustrp_rev(sp1, 0, USTRP1(\x2, "xy"), 1, 2) == 5); ASSERT(ustrp_srch_subustrp_fwd(sp1, 0, USTRP1(\x2, "xy"), 1, 1) == 3); ASSERT(ustrp_srch_subustrp_rev(sp1, 0, USTRP1(\x2, "xy"), 1, 1) == 5); ASSERT(ustrp_srch_subustrp_fwd(sp1, 0, USTRP1(\x2, "xy"), 2, 1) == 6); ASSERT(ustrp_srch_subustrp_rev(sp1, 0, USTRP1(\x2, "xy"), 2, 1) == 18); ASSERT(ustrp_srch_chr_fwd(sp1, 0, 'x') == 3); ASSERT(ustrp_srch_chr_rev(sp1, 0, 'x') == 5); ASSERT(ustrp_srch_chr_fwd(sp1, 0, 'y') == 6); ASSERT(ustrp_srch_chr_rev(sp1, 0, 'y') == 18); /* srch_case */ ASSERT_PEQ(sp1, USTRP1(\x12, "22xxxyyyyyyyyyyyyy")); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "Xy") == 5); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "xY") == 5); ASSERT(ustrp_srch_case_fwd(sp1, 0, USTRP1(\x2, "xY")) == 5); ASSERT(ustrp_srch_case_rev(sp1, 0, USTRP1(\x2, "Xy")) == 5); ASSERT(ustrp_srch_case_subustrp_fwd(sp1, 0, USTRP1(\x2, "Xy"), 1, 2) == 5); ASSERT(ustrp_srch_case_subustrp_rev(sp1, 0, USTRP1(\x2, "xY"), 1, 2) == 5); ASSERT(ustrp_srch_case_subustrp_fwd(sp1, 0, USTRP1(\x2, "Xy"), 1, 1) == 3); ASSERT(ustrp_srch_case_subustrp_rev(sp1, 0, USTRP1(\x2, "xY"), 1, 1) == 5); ASSERT(ustrp_srch_case_subustrp_fwd(sp1, 0, USTRP1(\x2, "XY"), 2, 1) == 6); ASSERT(ustrp_srch_case_subustrp_rev(sp1, 0, USTRP1(\x2, "XY"), 2, 1) == 18); if (!USTR_DEBUG) ASSERT(ustrp_srch_case_subustrp_fwd(sp1, 2, USTRP1(\4, "1248"), 4, 2) == 3); if (!USTR_DEBUG) ASSERT(ustrp_srch_case_subustrp_rev(sp1, 2, USTRP1(\4, "yyyy"), 4, 2) == 16); if (!USTR_DEBUG) ASSERT(ustrp_srch_case_subustrp_fwd(sp1, 0, USTRP1(\4, "1248"), 5, 1) == 1); if (!USTR_DEBUG) ASSERT(ustrp_srch_case_subustrp_rev(sp1, 0, USTRP1(\4, "YYYY"), 5, 1) == 18); ASSERT(ustrp_srch_case_chr_fwd(sp1, 0, 'x') == 3); ASSERT(ustrp_srch_case_chr_rev(sp1, 0, 'x') == 5); ASSERT(ustrp_srch_case_chr_fwd(sp1, 0, 'y') == 6); ASSERT(ustrp_srch_case_chr_rev(sp1, 0, 'y') == 18); ASSERT(ustrp_srch_case_chr_fwd(sp1, 0, 'X') == 3); ASSERT(ustrp_srch_case_chr_rev(sp1, 0, 'X') == 5); ASSERT(ustrp_srch_case_chr_fwd(sp1, 0, 'Y') == 6); ASSERT(ustrp_srch_case_chr_rev(sp1, 0, 'Y') == 18); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'x', 1) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'x', 1) == 5); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 1) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 1) == 18); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'X', 1) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'X', 1) == 5); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 1) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 1) == 18); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'z', 1) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'z', 1) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Z', 1) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Z', 1) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'z', 2) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'z', 2) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Z', 2) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Z', 2) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Z', 0) == 1); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Z', 0) == 18); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 1, 'Z', 0) == 2); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 1, 'Z', 0) == 17); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'x', 2) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'x', 2) == 4); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'x', 3) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'x', 3) == 3); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'x', 4) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'x', 4) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'X', 2) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'X', 2) == 4); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'X', 3) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'X', 3) == 3); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'X', 4) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'X', 4) == 0); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "xx") == 3); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "xx") == 4); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "xxx") == 3); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "xxx") == 3); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "xxxx") == 0); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "xxxx") == 0); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "XX") == 3); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "XX") == 4); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "XXX") == 3); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "XXX") == 3); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "XXXX") == 0); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "XXXX") == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 2) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 2) == 17); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 3) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 3) == 16); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 4) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 4) == 15); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 13) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 13) == 6); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 14) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 14) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 2) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 2) == 17); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 3) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 3) == 16); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 4) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 4) == 15); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 13) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 13) == 6); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 14) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 14) == 0); /* try srch_case with other case */ ustrp_sc_free2(pool, &sp1, USTRP1(\x12, "22XXXYYYYYYYYYYYYY")); ASSERT_PEQ(sp1, USTRP1(\x12, "22XXXYYYYYYYYYYYYY")); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "Xy") == 5); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "xY") == 5); ASSERT(ustrp_srch_case_fwd(sp1, 0, USTRP1(\x2, "xY")) == 5); ASSERT(ustrp_srch_case_rev(sp1, 0, USTRP1(\x2, "Xy")) == 5); ASSERT(ustrp_srch_case_subustrp_fwd(sp1, 0, USTRP1(\x2, "Xy"), 1, 2) == 5); ASSERT(ustrp_srch_case_subustrp_rev(sp1, 0, USTRP1(\x2, "xY"), 1, 2) == 5); ASSERT(ustrp_srch_case_subustrp_fwd(sp1, 0, USTRP1(\x2, "Xy"), 1, 1) == 3); ASSERT(ustrp_srch_case_subustrp_rev(sp1, 0, USTRP1(\x2, "xY"), 1, 1) == 5); ASSERT(ustrp_srch_case_subustrp_fwd(sp1, 0, USTRP1(\x2, "XY"), 2, 1) == 6); ASSERT(ustrp_srch_case_subustrp_rev(sp1, 0, USTRP1(\x2, "XY"), 2, 1) == 18); ASSERT(ustrp_srch_case_chr_fwd(sp1, 0, 'x') == 3); ASSERT(ustrp_srch_case_chr_rev(sp1, 0, 'x') == 5); ASSERT(ustrp_srch_case_chr_fwd(sp1, 0, 'y') == 6); ASSERT(ustrp_srch_case_chr_rev(sp1, 0, 'y') == 18); ASSERT(ustrp_srch_case_chr_fwd(sp1, 0, 'X') == 3); ASSERT(ustrp_srch_case_chr_rev(sp1, 0, 'X') == 5); ASSERT(ustrp_srch_case_chr_fwd(sp1, 0, 'Y') == 6); ASSERT(ustrp_srch_case_chr_rev(sp1, 0, 'Y') == 18); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'x', 1) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'x', 1) == 5); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 1) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 1) == 18); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'X', 1) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'X', 1) == 5); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 1) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 1) == 18); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'z', 1) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'z', 1) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Z', 1) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Z', 1) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'z', 2) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'z', 2) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Z', 2) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Z', 2) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Z', 0) == 1); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Z', 0) == 18); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 1, 'Z', 0) == 2); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 1, 'Z', 0) == 17); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'x', 2) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'x', 2) == 4); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'x', 3) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'x', 3) == 3); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'x', 4) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'x', 4) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'X', 2) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'X', 2) == 4); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'X', 3) == 3); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'X', 3) == 3); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'X', 4) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'X', 4) == 0); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "xx") == 3); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "xx") == 4); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "xxx") == 3); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "xxx") == 3); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "xxxx") == 0); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "xxxx") == 0); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "XX") == 3); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "XX") == 4); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "XXX") == 3); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "XXX") == 3); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "XXXX") == 0); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "XXXX") == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 2) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 2) == 17); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 3) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 3) == 16); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 4) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 4) == 15); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 13) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 13) == 6); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'y', 14) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'y', 14) == 0); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 2) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 2) == 17); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 3) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 3) == 16); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 4) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 4) == 15); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 13) == 6); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 13) == 6); ASSERT(ustrp_srch_case_rep_chr_fwd(sp1, 0, 'Y', 14) == 0); ASSERT(ustrp_srch_case_rep_chr_rev(sp1, 0, 'Y', 14) == 0); /* show srch still works this way */ ASSERT(ustrp_srch_cstr_fwd(sp1, 0, "XY") == 5); ASSERT(ustrp_srch_cstr_rev(sp1, 0, "XY") == 5); ASSERT(ustrp_srch_fwd(sp1, 0, USTRP1(\x2, "XY")) == 5); ASSERT(ustrp_srch_rev(sp1, 0, USTRP1(\x2, "XY")) == 5); ASSERT(ustrp_srch_subustrp_fwd(sp1, 0, USTRP1(\x2, "XY"), 1, 2) == 5); ASSERT(ustrp_srch_subustrp_rev(sp1, 0, USTRP1(\x2, "XY"), 1, 2) == 5); ASSERT(ustrp_srch_subustrp_fwd(sp1, 0, USTRP1(\x2, "XY"), 1, 1) == 3); ASSERT(ustrp_srch_subustrp_rev(sp1, 0, USTRP1(\x2, "XY"), 1, 1) == 5); ASSERT(ustrp_srch_subustrp_fwd(sp1, 0, USTRP1(\x2, "XY"), 2, 1) == 6); ASSERT(ustrp_srch_subustrp_rev(sp1, 0, USTRP1(\x2, "XY"), 2, 1) == 18); ASSERT(ustrp_srch_chr_fwd(sp1, 0, 'X') == 3); ASSERT(ustrp_srch_chr_rev(sp1, 0, 'X') == 5); ASSERT(ustrp_srch_chr_fwd(sp1, 0, 'Y') == 6); ASSERT(ustrp_srch_chr_rev(sp1, 0, 'Y') == 18); ASSERT(ustrp_srch_cstr_fwd(sp1, 0, "") == 1); ASSERT(ustrp_srch_cstr_rev(sp1, 0, "") == ustrp_len(sp1)); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 0, "") == 1); ASSERT(ustrp_srch_case_cstr_rev(sp1, 0, "") == ustrp_len(sp1)); ASSERT(ustrp_srch_cstr_fwd(sp1, 2, "") == 3); ASSERT(ustrp_srch_cstr_rev(sp1, 2, "") == ustrp_len(sp1) - 2); ASSERT(ustrp_srch_case_cstr_fwd(sp1, 2, "") == 3); ASSERT(ustrp_srch_case_cstr_rev(sp1, 2, "") == ustrp_len(sp1) - 2); /* do some more stuff... */ ustrp_free(pool, sp1); sp1 = USTRP1(\x1, "c"); ASSERT( ustrp_add_subustrp(pool, &sp1, sp2, 1, 1)); ASSERT_PEQ(sp1, USTRP1(\x2, "cs")); ASSERT(ustrp_setf_share(sp1)); ASSERT( ustrp_add_subustrp(pool, &sp1, sp2, 2, 1)); ASSERT_PEQ(sp1, USTRP1(\x3, "cs2")); ustrp_sc_free2(pool, &sp1, ustrp_dupx(pool, 1, 1, 1, 1, USTRP(""))); #if 0 #define DBG(x) \ printf("DBG(%s): %x:%zu:%s\n", #x , \ *(char*)sp1, ustrp_len(sp1), ustrp_cstr(sp1)); \ fflush(NULL) #else #define DBG(x) /* do nothing */ #endif DBG(0a); ASSERT_PEQ(sp1, USTRP("")); DBG(0b); ASSERT(ustrp_setf_share(sp1)); DBG(0c); ASSERT(!ustrp_owner(sp1)); DBG(0d); ASSERT( ustrp_shared(sp1)); DBG(1); ASSERT( ustrp_enomem(sp1)); DBG(2); ASSERT(!ustrp_realloc(pool, &sp1, 0)); DBG(0e); ASSERT( ustrp_add_subustrp(pool, &sp1, sp2, 2, 1)); DBG(3); ASSERT( ustrp_add_subustrp(pool, &sp1, sp2, 2, 1)); ASSERT( ustrp_owner(sp1)); ASSERT(!ustrp_shared(sp1)); DBG(4); ASSERT( ustrp_enomem(sp1)); DBG(5); ASSERT(!ustrp_realloc(pool, &sp1, 1)); ASSERT( ustrp_realloc(pool, &sp1, 2)); ASSERT( ustrp_realloc(pool, &sp1, 2)); ASSERT_PEQ(sp1, USTRP1(\x2, "22")); ustrp_sc_free2(pool, &sp1, USTRP("")); /* test subpool API */ #if USTR_CONF_INCLUDE_INTERNAL_HEADERS ASSERT(!((struct Ustr__pool_ll_base *)pool)->sbeg); ASSERT(!((struct Ustr__pool_ll_base *)pool)->next); ASSERT(!((struct Ustr__pool_ll_base *)pool)->prev); ASSERT(!((struct Ustr__pool_ll_base *)pool)->base); #endif ASSERT((p1 = ustr_pool_make_subpool(pool))); ASSERT((p2 = ustr_pool_make_subpool(pool))); ASSERT((p3 = ustr_pool_make_subpool(pool))); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS ASSERT(&((struct Ustr__pool_ll_base *)pool)->sbeg->cbs == p3); ASSERT(!((struct Ustr__pool_ll_base *)pool)->next); ASSERT(!((struct Ustr__pool_ll_base *)pool)->prev); ASSERT(!((struct Ustr__pool_ll_base *)pool)->base); ASSERT(!((struct Ustr__pool_ll_base *)p3)->sbeg); ASSERT(&((struct Ustr__pool_ll_base *)p3)->next->cbs == p2); ASSERT(!((struct Ustr__pool_ll_base *)p3)->prev); ASSERT(&((struct Ustr__pool_ll_base *)p3)->base->cbs == pool); ASSERT(!((struct Ustr__pool_ll_base *)p2)->sbeg); ASSERT(&((struct Ustr__pool_ll_base *)p2)->next->cbs == p1); ASSERT(&((struct Ustr__pool_ll_base *)p2)->prev->cbs == p3); ASSERT(&((struct Ustr__pool_ll_base *)p2)->base->cbs == pool); ASSERT(!((struct Ustr__pool_ll_base *)p1)->sbeg); ASSERT(!((struct Ustr__pool_ll_base *)p1)->next); ASSERT(&((struct Ustr__pool_ll_base *)p1)->prev->cbs == p2); ASSERT(&((struct Ustr__pool_ll_base *)p1)->base->cbs == pool); #endif ustr_pool_clear(p2); ustr_pool_clear(p1); ustr_pool_clear(p3); ASSERT(ustrp_dup_undef(p1, 2)); ASSERT(ustrp_dup_undef(p1, 2)); ASSERT(ustrp_dup_undef(p2, 4)); ASSERT(ustrp_dup_undef(p2, 4)); ASSERT(ustrp_dup_undef(p2, 4)); ASSERT(ustrp_dup_undef(p2, 4)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS ASSERT( ((struct Ustr__pool_ll_base *)p1)->beg); ASSERT( ((struct Ustr__pool_ll_base *)p2)->beg); ASSERT( ((struct Ustr__pool_ll_base *)p3)->beg); #endif ustr_pool_clear(p2); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS ASSERT( ((struct Ustr__pool_ll_base *)p1)->beg); ASSERT(!((struct Ustr__pool_ll_base *)p2)->beg); ASSERT( ((struct Ustr__pool_ll_base *)p3)->beg); #endif ustr_pool_free(p3); ASSERT((p3 = ustr_pool_make_subpool(p2))); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS ASSERT(!((struct Ustr__pool_ll_base *)p1)->next); ASSERT(&((struct Ustr__pool_ll_base *)p1)->prev->cbs == p2); ASSERT(&((struct Ustr__pool_ll_base *)p2)->next->cbs == p1); ASSERT(!((struct Ustr__pool_ll_base *)p2)->prev); ASSERT(&((struct Ustr__pool_ll_base *)p2)->sbeg->cbs == p3); ASSERT(!((struct Ustr__pool_ll_base *)p3)->next); ASSERT(!((struct Ustr__pool_ll_base *)p3)->prev); ASSERT(&((struct Ustr__pool_ll_base *)p3)->base->cbs == p2); #endif ASSERT(ustrp_dup_undef(p3, 2)); ASSERT(ustrp_dup_undef(p3, 2)); ASSERT(ustrp_dup_undef(p3, 4)); ASSERT(ustrp_dup_undef(p3, 4)); ASSERT(ustrp_dup_undef(p3, 4)); ASSERT(ustrp_dup_undef(p3, 4)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT((p3 = ustr_pool_make_subpool(pool))); ustr_pool_free(p2); ASSERT((p1 = ustr_pool_make_subpool(p3))); ASSERT((p2 = ustr_pool_make_subpool(p3))); ASSERT((p3 = ustr_pool_make_subpool(p3))); ASSERT(ustrp_dup_undef(p1, 2)); ASSERT(ustrp_dup_undef(p1, 2)); ASSERT(ustrp_dup_undef(p2, 4)); ASSERT(ustrp_dup_undef(p2, 4)); ASSERT(ustrp_dup_undef(p2, 4)); ASSERT(ustrp_dup_undef(p2, 4)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); ASSERT(ustrp_dup_undef(p3, 8)); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS ASSERT(p1 && ((struct Ustr__pool_ll_base *)p1)->beg && ((struct Ustr__pool_ll_base *)p1)->beg->ptr); ASSERT(p2 && ((struct Ustr__pool_ll_base *)p2)->beg && ((struct Ustr__pool_ll_base *)p2)->beg->ptr); ASSERT(p3 && ((struct Ustr__pool_ll_base *)p3)->beg && ((struct Ustr__pool_ll_base *)p3)->beg->ptr); #endif ustr_pool_clear(pool); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS ASSERT(p1 && !((struct Ustr__pool_ll_base *)p1)->beg); ASSERT(p2 && !((struct Ustr__pool_ll_base *)p2)->beg); ASSERT(p3 && !((struct Ustr__pool_ll_base *)p3)->beg); #endif ASSERT_PEQ(USTRP1(\x8, "1234567z"), ustrp_dup_cstr(pool, "1234567z")); ASSERT(ustrp_assert_valid(sp1)); ASSERT((sp1 = ustrp_dupx_cstr(pool, 0, 0, USTR_TRUE, USTR_TRUE, "1234567z"))); ASSERT_PEQ(USTRP1(\x8, "1234567z"), sp1); ASSERT(!ustrp_sized(sp1)); ASSERT(!ustrp_setf_share(sp1)); ASSERT( ustrp_setf_owner(sp1)); ASSERT(ustrp_exact(sp1)); ASSERT(ustrp_size(sp1) == ustrp_len(sp1)); ASSERT(ustrp_size_alloc(sp1) == ustrp_len(sp1) + ustrp_size_overhead(sp1)); ASSERT( ustrp_enomem(sp1)); ASSERT( ustrp_setf_enomem_clr(sp1)); ASSERT(!ustrp_enomem(sp1)); ASSERT( ustrp_setf_enomem_err(sp1)); ASSERT( ustrp_enomem(sp1)); ASSERT(ustrp_add_cstr(pool, &sp1, "abcd")); ASSERT_PEQ(USTRP1(\xc, "1234567zabcd"), sp1); ustrp_sc_free2(pool, &sp1, ustrp_dupx_cstr(pool, 1, 1, 1, 1, "1234abcd")); ASSERT_PEQ(sp1, USTRP1(\x8, "1234abcd")); ASSERT(ustrp_enomem(sp1)); ASSERT(ustrp_sized(sp1)); ASSERT(ustrp_exact(sp1)); ASSERT(ustrp_setf_enomem_clr(sp1)); ASSERT(ustrp_sc_toupper(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\x8, "1234ABCD")); ASSERT(ustrp_sc_tolower(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\x8, "1234abcd")); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\x8, "dcba4321")); ASSERT(ustrp_del(pool, &sp1, 1)); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\x7, "234abcd")); ASSERT(ustrp_del(pool, &sp1, 1)); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\x6, "cba432")); ASSERT(ustrp_del(pool, &sp1, 1)); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\x5, "34abc")); ASSERT(ustrp_del(pool, &sp1, 1)); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\x4, "ba43")); ASSERT(ustrp_del(pool, &sp1, 1)); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\x3, "4ab")); ASSERT(ustrp_del(pool, &sp1, 1)); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\x2, "a4")); ASSERT(ustrp_del(pool, &sp1, 1)); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT_PEQ(sp1, USTRP1(\x1, "a")); ASSERT(ustrp_del(pool, &sp1, 1)); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT_PEQ(sp1, USTRP("")); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT(ustrp_sc_reverse(pool, &sp1)); ASSERT_PEQ(sp1, USTRP("")); ustr_pool_clear(pool); sp1 = USTRP(""); ASSERT_PEQ(sp1, USTRP("")); ASSERT(ustrp_ins(pool, &sp1, 0, USTRP(""))); ASSERT(ustrp_ins(pool, &sp1, 0, USTRP(""))); ASSERT_PEQ(sp1, USTRP("")); ASSERT(ustrp_ins(pool, &sp1, 0, USTRP1(\4, "abcd"))); ASSERT_PEQ(sp1, USTRP1(\4, "abcd")); ASSERT(ustrp_ins(pool, &sp1, 2, USTRP1(\1, "x"))); ASSERT_PEQ(sp1, USTRP1(\5, "abxcd")); ASSERT(ustrp_ins_cstr(pool, &sp1, 2, "y")); ASSERT_PEQ(sp1, USTRP1(\6, "abyxcd")); ASSERT(ustrp_ins_buf(pool, &sp1, 1, "Zabcd", 1)); ASSERT_PEQ(sp1, USTRP1(\7, "aZbyxcd")); ASSERT(ustrp_ins_rep_chr(pool, &sp1, 0, '-', 2)); ASSERT_PEQ(sp1, USTRP1(\x9, "--aZbyxcd")); ASSERT(ustrp_sc_sub_rep_chr(pool, &sp1, 1, 4, '=', 2)); ASSERT_PEQ(sp1, USTRP1(\7, "==byxcd")); ASSERT(ustrp_sc_sub_cstr(pool, &sp1, 6, 2, "___")); ASSERT_PEQ(sp1, USTRP1(\x8, "==byx___")); ASSERT(ustrp_sc_sub_buf(pool, &sp1, 1, 2, "___", 1)); ASSERT_PEQ(sp1, USTRP1(\7, "_byx___")); ASSERT(ustrp_sc_sub_fmt(pool, &sp1, 2, 6, "%2s%4d%10s", "x", 4, "y")); ASSERT_PEQ(sp1, USTRP1(\x11, "_ x 4 y")); ASSERT(ustrp_sc_sub_fmt_lim(pool, &sp1, 2, 16, 1, "%s%4d%10s", "!", 4, "y")); ASSERT_PEQ(sp1, USTRP1(\2, "_!")); ASSERT(ustrp_ins_fmt(pool, &sp1, 1, "%s%2d%s", "x", 4, "y")); ASSERT_PEQ(sp1, USTRP1(\6, "_x 4y!")); ASSERT(ustrp_ins_fmt_lim(pool, &sp1, 0, 2, "%s%2d%s", "x", 4, "y")); ASSERT_PEQ(sp1, USTRP1(\x8, "x _x 4y!")); ASSERT(ustrp_sub_rep_chr(pool, &sp1, 1, '=', 2)); ASSERT_PEQ(sp1, USTRP1(\x8, "==_x 4y!")); ASSERT(ustrp_sub_cstr(pool, &sp1, 4, "abcd")); ASSERT_PEQ(sp1, USTRP1(\x8, "==_abcd!")); ASSERT(ustrp_sub_buf(pool, &sp1, 2, "___abcd", 3)); ASSERT_PEQ(sp1, USTRP1(\x8, "=___bcd!")); ASSERT(ustrp_sub(pool, &sp1, 1, USTRP1(\3, "---"))); ASSERT_PEQ(sp1, USTRP1(\x8, "---_bcd!")); ASSERT(ustrp_sc_sub(pool, &sp1, 2, 4, USTRP1(\3, "==="))); ASSERT_PEQ(sp1, USTRP1(\7, "-===cd!")); ASSERT(ustrp_sub_fmt(pool, &sp1, 5, "%s", "xyz")); ASSERT_PEQ(sp1, USTRP1(\7, "-===xyz")); ASSERT(ustrp_sub_subustrp(pool, &sp1, 2, USTRP1(\4, "1234"), 2, 2)); ASSERT_PEQ(sp1, USTRP1(\7, "-23=xyz")); ASSERT(ustrp_sc_sub_subustrp(pool, &sp1, 2, 4, USTRP1(\4, "12*&"), 3, 2)); ASSERT_PEQ(sp1, USTRP1(\5, "-*&yz")); ASSERT(ustrp_sub_fmt_lim(pool, &sp1, 5, 2, "%s", "123456789")); ASSERT_PEQ(sp1, USTRP1(\6, "-*&y12")); ustrp_sc_free2(pool, &sp1, USTRP1(\x10, "123456789 123456")); ASSERT(!ustrp_replace(pool, &sp1, USTRP1(\1, "!"), USTRP1(\4, "abcd"), 0)); ASSERT(!ustrp_replace_buf(pool, &sp1, "1", 2, "abcd", 4, 0)); ASSERT_PEQ(sp1, USTRP1(\x10, "123456789 123456")); ASSERT(ustrp_replace_cstr(pool, &sp1, "123", "xyz", 1)); ASSERT_PEQ(sp1, USTRP1(\x10, "xyz456789 123456")); ASSERT(ustrp_replace_cstr(pool, &sp1, "123", "xyz", 1)); ASSERT_PEQ(sp1, USTRP1(\x10, "xyz456789 xyz456")); ASSERT(!ustrp_replace_cstr(pool, &sp1, "123", "xyz", 1)); ASSERT_PEQ(sp1, USTRP1(\x10, "xyz456789 xyz456")); off = 0; ASSERT_PEQ(ustrp_split_cstr(pool, sp1, &off,"xyz",0,0),USTRP1(\7, "456789 ")); ASSERT_PEQ(ustrp_split_cstr(pool, sp1, &off,"xyz",0,0),USTRP1(\3, "456")); ASSERT(!ustrp_split_cstr(pool, sp1, &off, "xyz", NULL, 0)); ASSERT(!ustrp_split_cstr(pool, sp1, &off, "xyz", NULL, 0)); off = 0; ASSERT_PEQ(ustrp_split(pool, sp1, &off, USTRP1(\3, "xyz"), NULL, 0), USTRP1(\7, "456789 ")); ASSERT_PEQ(ustrp_split(pool, sp1, &off, USTRP1(\3, "xyz"), NULL, 0), USTRP1(\3, "456")); ASSERT(!ustrp_split(pool, sp1, &off, USTRP1(\3, "xyz"), NULL, 0)); ASSERT(!ustrp_split(pool, sp1, &off, USTRP1(\3, "xyz"), NULL, 0)); ASSERT(ustrp_len(sp1) == 16); ASSERT(ustrp_ins_undef(pool, &sp1, 1, 2)); ASSERT(ustrp_len(sp1) == 18); ASSERT(ustrp_sub_undef(pool, &sp1, 3, 2)); ASSERT(ustrp_len(sp1) == 18); ASSERT(ustrp_sc_sub_undef(pool, &sp1, 1, 2, 2)); ASSERT(ustrp_len(sp1) == 18); if (!USTR_DEBUG) ASSERT(!ustrp_ins_subustrp(pool, &sp1, 2, USTRP1(\4, "1248"), 4, 2)); if (!USTR_DEBUG) ASSERT(!ustrp_ins_subustrp(pool, &sp1, 2, USTRP1(\4, "1248"), 5, 1)); ustrp_sc_free2(pool, &sp1, USTRP1(\x10, "xyz456789 xyz456")); ASSERT_PEQ(sp1, USTRP1(\x10, "xyz456789 xyz456")); ASSERT(ustrp_replace_rep_chr(pool, &sp1, 'x', 1, 'y', 1, 0) == 2); ASSERT_PEQ(sp1, USTRP1(\x10, "yyz456789 yyz456")); ASSERT(ustrp_replace_rep_chr(pool, &sp1, 'y', 1, 'z', 1, 0) == 4); ASSERT_PEQ(sp1, USTRP1(\x10, "zzz456789 zzz456")); ASSERT(ustrp_replace_rep_chr(pool, &sp1, 'z', 3, 'x', 3, 0) == 2); ASSERT_PEQ(sp1, USTRP1(\x10, "xxx456789 xxx456")); ASSERT(!ustrp_srch_rep_chr_fwd(sp1, 0, 'x', 4)); ASSERT(!ustrp_srch_rep_chr_rev(sp1, 0, 'x', 4)); ASSERT(ustrp_srch_rep_chr_fwd(sp1, 0, 'x', 3) == 1); ASSERT(ustrp_srch_rep_chr_rev(sp1, 0, 'x', 3) == 11); ASSERT(ustrp_srch_rep_chr_fwd(sp1, 0, 'x', 2) == 1); ASSERT(ustrp_srch_rep_chr_rev(sp1, 0, 'x', 2) == 12); ASSERT(ustrp_srch_rep_chr_fwd(sp1, 0, 'x', 1) == 1); ASSERT(ustrp_srch_rep_chr_rev(sp1, 0, 'x', 1) == 13); ASSERT(ustrp_srch_rep_chr_fwd(sp1, 0, 'x', 0) == 1); ASSERT(ustrp_srch_rep_chr_rev(sp1, 0, 'x', 0) == 16); ASSERT(ustrp_replace_rep_chr(pool, &sp1, 'x', 3, '!', 3, 1) == 1); ASSERT_PEQ(sp1, USTRP1(\x10, "!!!456789 xxx456")); off = 0; ASSERT_PEQ(ustrp_split_spn_cstr(pool, sp1, &off, "xx", NULL, 0), USTRP1(\xa, "!!!456789 ")); ASSERT(off == 13); ASSERT_PEQ(ustrp_split_spn_cstr(pool, sp1, &off, "xx", NULL, 0), USTRP1(\3, "456")); off = 13; ASSERT_PEQ(ustrp_split_spn(pool, sp1, &off, USTRP1(\2, "xx"), NULL, 0), USTRP1(\3, "456")); sp1 = USTRP1(\x14, "123456789912345xxxxx"); { size_t scan = 0x15; char *cstr = ustrp_sc_export(pool, sp1, malloc); ASSERT(cstr); ASSERT(strlen(cstr) == ustrp_len(sp1)); ASSERT(ustrp_cmp_cstr_eq(sp1, cstr)); free(cstr); while (scan--) { cstr = ustrp_sc_export_subustrp(pool, sp1, 1, scan, malloc); ASSERT(cstr); ASSERT(strlen(cstr) == scan); ASSERT(ustrp_cmp_prefix_cstr_eq(sp1, cstr)); free(cstr); } scan = 0x14; while (scan--) { cstr = ustrp_sc_export_subustrp(pool, sp1, scan + 1, ustrp_len(sp1) -scan, malloc); ASSERT(cstr); ASSERT(strlen(cstr) == ustrp_len(sp1) - scan); ASSERT(ustrp_cmp_suffix_cstr_eq(sp1, cstr)); free(cstr); } cstr = ustrp_sc_export_subustrp(pool, sp1, 4, 3, malloc); ASSERT(cstr); ASSERT(strlen(cstr) == 3); ASSERT(ustrp_cmp_cstr_eq(USTRP1(\3, "456"), cstr)); free(cstr); cstr = ustrp_sc_export_subustrp(pool, sp1, 4, 0, malloc); ASSERT(cstr); ASSERT(strlen(cstr) == 0); free(cstr); if (!USTR_DEBUG) ASSERT(!ustrp_sc_export_subustrp(pool, sp1, 1, 0x15, malloc)); if (!USTR_DEBUG) ASSERT(!ustrp_sc_export_subustrp(pool, sp1, 2, 0x14, malloc)); } { size_t scan = 0x15; char *cstr = ustrp_sc_export(pool, sp1, NULL); ASSERT(cstr); ASSERT(strlen(cstr) == ustrp_len(sp1)); ASSERT(ustrp_cmp_cstr_eq(sp1, cstr)); while (scan--) { cstr = ustrp_sc_export_subustrp(pool, sp1, 1, scan, NULL); ASSERT(cstr); ASSERT(strlen(cstr) == scan); ASSERT(ustrp_cmp_prefix_cstr_eq(sp1, cstr)); } scan = 0x14; while (scan--) { cstr = ustrp_sc_export_subustrp(pool, sp1, scan + 1, ustrp_len(sp1) -scan, NULL); ASSERT(cstr); ASSERT(strlen(cstr) == ustrp_len(sp1) - scan); ASSERT(ustrp_cmp_suffix_cstr_eq(sp1, cstr)); } cstr = ustrp_sc_export_subustrp(pool, sp1, 4, 3, NULL); ASSERT(cstr); ASSERT(strlen(cstr) == 3); ASSERT(ustrp_cmp_cstr_eq(USTRP1(\3, "456"), cstr)); cstr = ustrp_sc_export_subustrp(pool, sp1, 4, 0, NULL); ASSERT(cstr); ASSERT(strlen(cstr) == 0); if (!USTR_DEBUG) ASSERT(!ustrp_sc_export_subustrp(pool, sp1, 1, 0x15, NULL)); if (!USTR_DEBUG) ASSERT(!ustrp_sc_export_subustrp(pool, sp1, 2, 0x14, NULL)); } ASSERT(!ustrp_sc_export(pool, sp1, fail_malloc)); ASSERT(!ustrp_sc_export_subustrp(pool, sp1, 1, 4, fail_malloc)); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS ASSERT( ((struct Ustr__pool_ll_base *)pool)->free_num == 2); ASSERT( ((struct Ustr__pool_ll_base *)pool)->call_realloc); #endif { unsigned int num = 0; int tog = 0; ASSERT(ustr_pool_ll_cntl(pool, USTR_POOL_LL_CNTL_GET_FREE_CMP, &num)); ASSERT(num == 2); ASSERT(ustr_pool_ll_cntl(pool, USTR_POOL_LL_CNTL_SET_FREE_CMP, 8)); ASSERT(ustr_pool_ll_cntl(pool, USTR_POOL_LL_CNTL_GET_FREE_CMP, &num)); ASSERT(num == 8); ASSERT(ustr_pool_ll_cntl(pool, USTR_POOL_LL_CNTL_GET_REALLOC, &tog)); ASSERT( tog); ASSERT(ustr_pool_ll_cntl(pool, USTR_POOL_LL_CNTL_SET_REALLOC, USTR_FALSE)); ASSERT(ustr_pool_ll_cntl(pool, USTR_POOL_LL_CNTL_GET_REALLOC, &tog)); ASSERT(!tog); } ustr_pool_free(pool); ustr_pool_free(NULL); return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_16_parse.c0000644000076400007640000002276110642537510014540 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; int tst(void) { unsigned int flg_sep = USTR_FLAG_PARSE_NUM_SEP; unsigned int flg_ovr = USTR_FLAG_PARSE_NUM_OVERFLOW; unsigned int flg_spc = USTR_FLAG_PARSE_NUM_SPACE; unsigned int flg_no0 = USTR_FLAG_PARSE_NUM_NO_BEG_ZERO; unsigned int flg_nopm = USTR_FLAG_PARSE_NUM_NO_BEG_PM; unsigned int flg_noneg = USTR_FLAG_PARSE_NUM_NO_NEGATIVE; unsigned int flg_ext = USTR_FLAG_PARSE_NUM_EXACT; unsigned int flg_sep_spc = flg_sep | flg_spc; unsigned int ern = 0; size_t num_len = 0; ASSERT(4000 == ustr_parse_uint(USTR1(\x5, "4_000"), 0, flg_sep, 0, 0)); ASSERT(0x4000 == ustr_parse_uint(USTR1(\x7, "0x4_000"), 0, flg_sep, 0, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_NONE); ASSERT(0 == ustr_parse_uint(USTR1(\x6, " 4_000"),0, flg_sep, 0, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OOB); ASSERT(0 == ustr_parse_uint(USTR1(\x6, " 4_000"),0, 16 | flg_sep, 0, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OOB); ASSERT(8240 == ustr_parse_uint(USTR1(\x9, " 8_2_4_0"), 0, flg_sep_spc, NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_NONE); ASSERT(0x8421 == ustr_parse_uint(USTR1(\x7, " 84__21"), 0, 16 | flg_sep_spc, NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_NONE); ASSERT(0xFFFFFFFF == ustr_parse_ulong(USTR1(\x8, "FFFFFFFF"), 0, 16, 0,&ern)); /* assume uint == 32bit */ ASSERT(0xFFFFFFFF == ustr_parse_uint(USTR1(\x9, "100000000"), 0, 16, 0,&ern)); ASSERT(!ern); ASSERT(0xFFFFFFFF == ustr_parse_uint(USTR1(\x9, "100000001"), 0, 16, 0,&ern)); ASSERT(!ern); ASSERT(0 == ustr_parse_uint(USTR1(\x9, "100000001"),0, 16 | flg_ovr, 0,&ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OVERFLOW); ASSERT(9 == ustr_parse_ushort(USTR1(\x4, "1001"), 0, 2, NULL, &ern)); ASSERT(!ern); ASSERT(9 == ustr_parse_short(USTR1(\x8, " +0b1001"), 0, flg_spc, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustr_parse_short(USTR1(\x8, "+ 0b1001"), 0, 0, NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OOB); ASSERT(-9 == ustr_parse_short(USTR1(\x7, "-0b1001"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustr_parse_int(USTR1(\x8, "- 0b1001"), 0, 0, NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OOB); ASSERT(2 == ustr_parse_int(USTR1(\x8, " 0b10-01"), 0, flg_spc | flg_ext, NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OOB); ASSERT(2345 == ustr_parse_ulongx(USTR1(\x8, " +2,34,5"), 0, 10 | flg_ovr | flg_sep_spc, 0, 2345, ",", &num_len, &ern)); ASSERT(!ern); ASSERT(num_len == 8); ASSERT(-2345 == (int)ustr_parse_ulongx(USTR1(\x8, " -2,34,5"), 0, 10 | flg_ovr | flg_sep_spc, 2346, 2345, ",", &num_len, &ern)); ASSERT(!ern); ASSERT(num_len == 8); ASSERT(-2346 == (int)ustr_parse_ulongx(USTR1(\x8, " -2,34,6"), 0, 10 | flg_ovr | flg_sep_spc, 2346, 2345, ",", &num_len, &ern)); ASSERT(!ern); ASSERT(num_len == 8); ASSERT(0 == (int)ustr_parse_ulongx(USTR1(\x8, " -4,34,5"), 0, 10 | flg_ovr | flg_sep_spc, 2346, 2345, ",", &num_len, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OVERFLOW); ASSERT(0 == ustr_parse_ulongx(USTR1(\x7, "-4,34,5"), 0, 10 | flg_ovr | flg_sep | flg_noneg, 0, 8345, ",", &num_len, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_NEGATIVE); ASSERT(0 == ustr_parse_ulongx(USTR1(\x8, " -4,34,5"), 0, flg_ovr | flg_sep_spc | flg_nopm, 8346, 8345, ",", &num_len, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OOB); ASSERT(0 == ustr_parse_ulongx(USTR1(\x8, " +4,34,5"), 0, flg_ovr | flg_sep_spc | flg_nopm, 8346, 8345, ",", &num_len, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OOB); ASSERT(4345 == ustr_parse_uintmax(USTR1(\x9, " +04_34_5"), 0, 10 | flg_ovr | flg_sep_spc, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustr_parse_uintmax(USTR1(\x9, " +04_34_5"), 0, 10 | flg_ovr | flg_sep_spc | flg_no0, 0,&ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO); ASSERT(0 == ustrp_parse_int(USTRP1(\x2, " 0"), 0, flg_spc, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_int(USTRP1(\x4, " 0"),0, flg_spc | flg_no0,0,&ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_int(USTRP1(\x2, "+0"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_int(USTRP1(\x3, "0x0"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_short(USTRP1(\x3, "0b0"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_long(USTRP1(\x3, "0o0"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_int(USTRP1(\x2, " 0"), 0, flg_spc | flg_no0, 0,&ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_int(USTRP1(\x4, " 0"),0,flg_spc | flg_no0, 0,&ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_int(USTRP1(\x2, "+0"), 0, flg_no0, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_ulong(USTRP1(\x3, "0x0"), 0, flg_no0, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_ushort(USTRP1(\x3, "0b0"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_uint(USTRP1(\x3, "0o0"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_uintmax(USTRP1(\x4, "0x00"), 0, flg_no0, NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO); ASSERT(0 == ustrp_parse_ulongx(USTRP1(\x1, " "), 0, 37|flg_spc, 0,8, ",", NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_ONLY_S); ASSERT(0 == ustrp_parse_ulongx(USTRP1(\x1, "+"), 0, 1, 0,8, ",", NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_ONLY_SPM); num_len = 0; ASSERT(0 == ustrp_parse_uintmaxx(USTRP1(\x1, "-"), 0, 1, 0,8, ",", &num_len, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_ONLY_SPM); ASSERT(num_len == 0); ASSERT(0 == ustrp_parse_uintmaxx(USTRP1(\x2, "0b"), 0, 0, 0,8, ",", NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX); ASSERT(0 == ustrp_parse_uintmaxx(USTRP1(\x2, "0o"), 0, 0, 0,8, ",", &num_len, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX); ASSERT(0 == ustrp_parse_uintmaxx(USTRP1(\x2, "0x"), 0, 0, 0,8, ",", &num_len, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX); ASSERT( 4 == ustrp_parse_short(USTRP1(\x4, "0o04"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT( 4 == ustrp_parse_int(USTRP1(\x2, "04"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(12 == ustrp_parse_long(USTRP1(\x4, "0o14"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(-12 == ustrp_parse_intmax(USTRP1(\x4, "-014"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT( 20 == ustrp_parse_ushort(USTRP1(\x5, "0O024"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT( 20 == ustrp_parse_uint(USTRP1(\x3, "024"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(140 == ustrp_parse_ulong(USTRP1(\x5, "0O214"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(140 == ustrp_parse_uintmax(USTRP1(\x4, "0214"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(140 == ustrp_parse_uintmax(USTRP1(\x4, "0x8C"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(140 == ustrp_parse_uintmax(USTRP1(\x4, "0X8c"), 0, 0, NULL, &ern)); ASSERT(!ern); ASSERT(140 == ustrp_parse_uintmax(USTRP1(\xb, "0b1000_1100"), 0, flg_sep, NULL, &ern)); ASSERT(!ern); ASSERT(140 == ustrp_parse_uintmax(USTRP1(\xb, "0B1000_1100"), 0, flg_sep, NULL, &ern)); ASSERT(!ern); ASSERT(0xF0FfF0FFf0FfF0ffULL == ustrp_parse_uintmax(USTRP1(\x15, "0xF0FfF0FFf0FfF0ffULL"), 0, flg_ovr, NULL, &ern)); ASSERT(!ern); ASSERT(0 == ustrp_parse_intmax(USTRP1(\x15, "0xF0FfF0FFf0FfF0ffULL"), 0, flg_ovr, NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OVERFLOW); ASSERT(0 == ustrp_parse_uintmax(USTRP1(\x16, "0x1F0FfF0FFf0FfF0ffULL"), 0, flg_ovr, NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OVERFLOW); ASSERT(0 == ustrp_parse_intmax(USTRP1(\x16, "0x1F0FfF0FFf0FfF0ffULL"), 0, flg_ovr, NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OVERFLOW); ASSERT(0 == ustrp_parse_intmax(USTRP1(\x17, "-0x1F0FfF0FFf0FfF0ffULL"), 0, flg_ovr, NULL, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OVERFLOW); ASSERT(0 == ustrp_parse_uintmaxx(USTRP1(\x2, "-8"), 0, flg_ovr, 7,7, "-", &num_len, &ern)); ASSERT(ern == USTR_TYPE_PARSE_NUM_ERR_OVERFLOW); ASSERT(-8 == (int)ustrp_parse_uintmaxx(USTRP1(\x2, "-8"), 0, flg_ovr, 8,7, "-", NULL, &ern)); ASSERT(!ern); ASSERT(num_len == 2); ASSERT(-7 == (int)ustrp_parse_uintmaxx(USTRP1(\x2, "-8"), 0, 0, 7,7, "-", &num_len, &ern)); ASSERT(!ern); ASSERT(num_len == 2); ASSERT(-8 == (int)ustrp_parse_uintmaxx(USTRP1(\x6, "ABCD-8"), 4, 0, 8,7, "-", &num_len, &ern)); ASSERT(!ern); ASSERT(num_len == 2); return (EXIT_SUCCESS); } ustr-1.0.4/T/tst_18_split.c0000644000076400007640000000000010647723521014402 0ustar jamesjamesustr-1.0.4/T/tst_4_grow.c0000644000076400007640000000050410630111754014140 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 1 #define USTR_CONF_USE_EOS_MARK 0 #define ustr_cntl_opt(x, y) 0 /* return FALSE */ # 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) ustr-1.0.4/T/tst_6_tiny.c0000644000076400007640000000537210675027246014172 0ustar jamesjames#undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES 0 #define USTR_CONF_USE_EOS_MARK 0 #include "tst.h" static const char *rf = __FILE__; int tst(void) { struct Ustr *tmp = NULL; ASSERT(ustr_len(s1) == 0); ASSERT(ustr_len(s2) == strlen("s2")); ASSERT(ustr_size(s1) == 0); ASSERT(ustr_size(s2) == 3); /* ustr__ns(1 + 0 + 1 + 2 + 1) - * 1 + 0 + 1 + 1 */ ASSERT( ustr_cmp_eq(s1, s1)); ASSERT( ustr_cmp_eq(s2, s2)); ASSERT(!ustr_cmp_eq(s1, s2)); ASSERT( ustr_cmp_cstr_eq(s1, "")); ASSERT( ustr_cmp_cstr_eq(s2, "s2")); ASSERT( ustr_cmp_eq(s2, USTR1(\x2, "s2"))); ASSERT(!ustr_cmp( s2, USTR1(\x002, "s2"))); ASSERT(!ustr_cmp_cstr_eq(s1, "s2")); ASSERT(!ustr_cmp_cstr_eq(s2, "")); ASSERT(!ustr_cmp_cstr_eq(s2, "s3")); ASSERT(!ustr_cmp_cstr_eq(s2, "s2x")); ASSERT(!ustr_cmp_buf_eq(s2, "s2", 1)); ASSERT( ustr_cmp_buf_eq(s2, "s2", 2)); ASSERT(!ustr_cmp_buf_eq(s2, "s2", 3)); ASSERT( ustr_cmp(s1, s1) == 0); ASSERT( ustr_cmp(s2, s2) == 0); ASSERT( ustr_cmp(s1, s2) < 0); ASSERT( ustr_cmp_fast(s1, s2) < 0); ASSERT( ustr_cmp(s2, s1) > 0); ASSERT( ustr_cmp_fast(s2, s1) > 0); ASSERT( ustr_cmp_cstr(s2, "s2") == 0); ASSERT( ustr_cmp_buf(s2, "s2", 2) == 0); ASSERT( ustr_srch_fwd(s1, 0, s1) == 0); ASSERT( ustr_srch_fwd(s1, 0, s2) == 0); ASSERT( ustr_srch_fwd(s2, 0, s1) == 1); ASSERT( ustr_srch_fwd(s2, 0, s2) == 1); ASSERT( ustr_srch_rev(s1, 0, s1) == 0); ASSERT( ustr_srch_rev(s1, 0, s2) == 0); ASSERT( ustr_srch_rev(s2, 0, s1) == 2); ASSERT( ustr_srch_rev(s2, 0, s2) == 1); ASSERT(!ustr_srch_cstr_fwd(s1, 0, "x")); ASSERT(!ustr_srch_cstr_fwd(s2, 0, "x")); ASSERT(!ustr_srch_cstr_fwd(s2, 0, "x")); ASSERT( ustr_srch_cstr_fwd(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_fwd(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_fwd(s2, 0, "s2") == 1); ASSERT( ustr_srch_cstr_fwd(s2, 0, "s") == 1); ASSERT( ustr_srch_cstr_fwd(s2, 0, "2") == 2); ASSERT(!ustr_srch_cstr_rev(s1, 0, "x")); ASSERT(!ustr_srch_cstr_rev(s2, 0, "x")); ASSERT(!ustr_srch_cstr_rev(s2, 0, "x")); ASSERT( ustr_srch_cstr_rev(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_rev(s1, 0, "") == 0); ASSERT( ustr_srch_cstr_rev(s2, 0, "s2") == 1); ASSERT( ustr_srch_cstr_rev(s2, 0, "s") == 1); ASSERT( ustr_srch_cstr_rev(s2, 0, "2") == 2); tmp = ustr_dup(s1); ASSERT(tmp == s1); tmp = ustr_dup(s2); ASSERT(tmp != s2); ustr_free(tmp); tmp = s2; ASSERT(ustr_sc_dup(&s2)); ASSERT(tmp && (tmp != s2)); ASSERT(ustr_cmp_eq(tmp, s2)); ustr_sc_free(&s2); s2 = tmp; { struct Ustr *s4 = ustr_dup_cstr("x"); ASSERT(ustr_len(s4) == 1); ASSERT(ustr_size(s4) == 1); ustr_sc_free(&s4); } return (EXIT_SUCCESS); } ustr-1.0.4/T/ctst_17_sub.c0000644000076400007640000003265010760720631014215 0ustar jamesjames#include "tst.h" static const char *rf = __FILE__; #if 0 # include # define PRINT_RESULT(x) printf("'%s'\n",ustr_cstr(x)) #else # define PRINT_RESULT(x) /* do nothing */ #endif int tst(void) { const char *str = "the quick brown fox"; Ustr *a = ustr_dup_cstr(str); const char *repl_cstr = "smart"; Ustr *repl = ustr_dup_cstr(repl_cstr); Ustr *c; Ustr *blank; Ustr *same_len_str; Ustr *d; Ustr *needle; const char *newstr; Ustr *ro = USTR1(\x4, "abcd"); Ustr *haystack; size_t num = 0; ASSERT(ustr_sub_fmt(&ro, 2, "%s%c", "x", 'x')); ASSERT(ustr_cmp_cstr_eq(ro, "axxd")); ustr_sc_free2(&ro, USTR1(\x7, "1234567")); ASSERT(ustr_sub_fmt(&ro, 7, "%s%c", "x", 'x')); ASSERT(ustr_cmp_cstr_eq(ro, "123456xx")); ASSERT(ustr_sub_fmt(&ro, 1, "%s%c", "x", 'x')); ASSERT(ustr_cmp_cstr_eq(ro, "xx3456xx")); ustr_sc_free2(&ro, USTR1(\x7, "1234567")); ASSERT(ustr_sub_fmt_lim(&ro, 2, 1, "%s%c", "x", 'x')); ASSERT(ustr_cmp_cstr_eq(ro, "1x34567")); ASSERT(ustr_sub_fmt_lim(&ro, 2, 1, "%s%s", "", "")); ASSERT(ustr_cmp_cstr_eq(ro, "1x34567")); ASSERT(ustr_sub_fmt_lim(&ro, 2, 1, "%s%s", "", "")); ASSERT(ustr_cmp_cstr_eq(ro, "1x34567")); ASSERT(ustr_sub_fmt_lim(&ro, 2, 1, "%s%s", "", "")); ASSERT(ustr_cmp_cstr_eq(ro, "1x34567")); ustr_sc_free2(&ro, USTR1(\x7, "1234567")); ASSERT(ustr_sc_sub_fmt(&ro, 2, 1, "%s%c", "x", 'x')); ASSERT(ustr_cmp_cstr_eq(ro, "1xx34567")); ustr_sc_free2(&ro, USTR1(\x7, "1234567")); ASSERT(ustr_sc_sub_fmt_lim(&ro, 2, 2, 3, "%s%c", "yyyy", 'y')); ASSERT(ustr_cmp_cstr_eq(ro, "1yyy4567")); ASSERT(ustr_sc_sub_fmt_lim(&ro, 2, 1, 1, "%s%s", "", "")); ASSERT(ustr_cmp_cstr_eq(ro, "1yy4567")); ASSERT(ustr_sc_sub_fmt_lim(&ro, 2, 1, 1, "%s%s", "", "")); ASSERT(ustr_cmp_cstr_eq(ro, "1y4567")); ASSERT(ustr_sc_sub_fmt_lim(&ro, 2, 1, 1, "%s%s", "", "")); ASSERT(ustr_cmp_cstr_eq(ro, "14567")); ASSERT(ustr_sc_sub_fmt_lim(&ro, 2, 1, 1, "%s%s", "", "")); ASSERT(ustr_cmp_cstr_eq(ro, "1567")); ASSERT(ustr_sub_rep_chr(&ro, ustr_len(ro), 'y', 3)); ASSERT(ustr_sub_rep_chr(&ro, ustr_len(ro), '3', 2)); ASSERT(ustr_sub_rep_chr(&ro, ustr_len(ro), '4', 1)); ASSERT(ustr_sc_sub_fmt_lim(&ro, 2, ustr_len(ro) - 5, 1, "%sxxx%s", "s", "x")); ASSERT(ustr_cmp_cstr_eq(ro, "1syy34")); ASSERT(ustr_sc_sub_rep_chr(&ro, 3, 1, '2', 0)); ASSERT(ustr_cmp_cstr_eq(ro, "1sy34")); ASSERT(ustr_sc_sub_cstr(&ro, 2, 2, "2x")); ASSERT(ustr_cmp_cstr_eq(ro, "12x34")); ASSERT(ustr_sc_sub_fmt_lim(&ro, 3, 1, 150, "%75s%-75sXYZ", "|", "|")); ASSERT(ustr_cmp_cstr_eq(ro, "12 || 34")); ASSERT(ustr_sc_sub_rep_chr(&ro, 2, 0, 'y', 0)); ASSERT(ustr_sub_rep_chr(&ro, 2, 'y', 0)); ASSERT(ustr_sc_sub_cstr(&ro, 2, 0, "")); ASSERT(ustr_sub_cstr(&ro, 2, "")); ASSERT(ustr_cmp_cstr_eq(ro, "12 || 34")); ASSERT(ustr_sub_fmt(&ro, 1, "%154s", "abcd")); ASSERT(ustr_cmp_cstr_eq(ro, " abcd")); ustr_sc_free2(&ro, USTR1(\x7, "1234567")); ASSERT(ustr_sub_fmt_lim(&ro, 1, 154, "%156s", "abcd")); ASSERT(ustr_cmp_cstr_eq(ro, " ab")); ustr_sc_free2(&ro, USTR1(\x7, "1234567")); ustr_sub_subustr(&ro, 4, USTR1(\x7, "abcdefg"), 3, 4); ASSERT(ustr_cmp_cstr_eq(ro, "123cdef")); ustr_sc_free2(&ro, USTR1(\x7, "1234567")); ustr_sc_sub_subustr(&ro, 4, 2, USTR1(\x7, "abcdefg"), 3, 4); ASSERT(ustr_cmp_cstr_eq(ro, "123cdef67")); ASSERT(ustr_cmp_cstr_eq(a,str)); /* replace will grow the string */ ASSERT(ustr_sub_cstr(&a,17,repl_cstr)); PRINT_RESULT(a); ASSERT(ustr_cmp_cstr_eq(a,"the quick brown smart")); /* sub cstr */ ASSERT(ustr_sub_cstr(&a,5,repl_cstr)); PRINT_RESULT(a); ASSERT(ustr_cmp_cstr_eq(a,"the smart brown smart")); /* sub ustr */ ASSERT(ustr_sub(&a,11,repl)); PRINT_RESULT(a); ASSERT(ustr_cmp_cstr_eq(a,"the smart smart smart")); ustr_sc_free(&repl); str = "this is a test"; c = ustr_dup_cstr(str); repl = ustr_dup_cstr("a real donut"); /* invalid position */ if (!USTR_DEBUG) ASSERT(!ustr_sc_sub(&c,1500,3,repl)); if (!USTR_DEBUG) ASSERT(!ustr_sc_sub(&c,1500,3,c)); PRINT_RESULT(c); ASSERT(ustr_cmp_cstr_eq(c,str)); ASSERT(ustr_sc_sub(&c,9,6,repl)); ASSERT(ustr_cmp_cstr_eq(c,"this is a real donut")); /* use sub as an erase */ blank = ustr_dup_empty(); ASSERT(ustr_sc_sub(&c,1,10,blank)); PRINT_RESULT(c); ASSERT(ustr_cmp_cstr_eq(c,"real donut")); /* replacement string length = old string length */ same_len_str = ustr_dup_cstr("mmmm"); ASSERT(ustr_sc_sub(&c,1,4,same_len_str)); PRINT_RESULT(c); ASSERT(ustr_cmp_cstr_eq(c,"mmmm donut")); ustr_sc_free(&repl); /* replacement expands string */ repl = ustr_dup_cstr("sprinkles"); ASSERT(ustr_sc_sub(&c,6,5,repl)); PRINT_RESULT(c); ASSERT(ustr_cmp_cstr_eq(c,"mmmm sprinkles")); ustr_sc_free(&repl); d = ustr_dup_cstr("aabbccabcabc"); repl = ustr_dup_cstr(" "); needle = ustr_dup_cstr("a"); /* replace -- same len */ ASSERT(ustr_replace(&d,needle,repl,0) == 4); PRINT_RESULT(d); newstr = " bbcc bc bc"; ASSERT(ustr_cmp_cstr_eq(d,newstr)); ustr_sc_free(&repl); ustr_sc_free(&needle); /* limited number of replacements -- same len */ repl = ustr_dup_cstr("."); needle = ustr_dup_cstr("c"); ASSERT(ustr_replace(&d,needle,repl,1) == 1); PRINT_RESULT(d); newstr = " bb.c bc bc"; ASSERT(ustr_cmp_cstr_eq(d,newstr)); ustr_sc_free(&needle); ustr_sc_free(&repl); /* limited number of replacements -- different len */ ustr_sc_free2(&d, USTR1(\x20, "123456789 x123456789 x123456789 ")); ASSERT(ustr_replace(&d, USTR1(\1, "x"), USTR1(\2, "ab"), 1) == 1); ASSERT(ustr_cmp_cstr_eq(d, "123456789 ab123456789 x123456789 ")); /* replacement -- different len */ ustr_sc_free2(&d, USTR1(\x20, "123456789 x123456789 x123456789 ")); ASSERT(ustr_replace_cstr(&d, "x", "ab", 0) == 2); ASSERT(ustr_cmp_cstr_eq(d, "123456789 ab123456789 ab123456789 ")); ASSERT(ustr_replace_cstr(&d, "x", "ab", 0) == 0); ASSERT(ustr_cmp_cstr_eq(d, "123456789 ab123456789 ab123456789 ")); ASSERT(ustr_replace_cstr(&d, "ab1", "!", 0) == 2); ASSERT(ustr_cmp_cstr_eq(d, "123456789 !23456789 !23456789 ")); ASSERT(ustr_replace_cstr(&d, "12", "!Z", 0) == 1); ASSERT(ustr_cmp_cstr_eq(d, "!Z3456789 !23456789 !23456789 ")); ASSERT(ustr_replace(&d, USTR1(\2, "34"), USTR1(\1, "x"), 0) == 3); ASSERT(ustr_cmp_cstr_eq(d, "!Zx56789 !2x56789 !2x56789 ")); ustr_sc_free2(&d, USTR1(\7, "xxxxxxx")); ASSERT(ustr_len(d) == 7); ASSERT(ustr_replace_buf(&d, "x", 1, "y", 0, 0) == 7); ASSERT(!ustr_len(d)); ustr_sc_free2(&d, USTR1(\7, "xxxxxxx")); ASSERT(ustr_replace_buf(&d, "x", 1, "yy", 1, 0) == 7); ASSERT(ustr_cmp_cstr_eq(d, "yyyyyyy")); ustr_sc_free2(&d, USTR1(\7, "xxxxxxx")); ASSERT(ustr_replace_buf(&d, "x", 1, "yy", 2, 0) == 7); ASSERT(ustr_cmp_cstr_eq(d, "yyyyyyyyyyyyyy")); ASSERT(ustr_sub_subustr(&d, 1, USTR1(\2, "aa"), 1, 0)); ASSERT(ustr_cmp_cstr_eq(d, "yyyyyyyyyyyyyy")); ASSERT(ustr_sc_sub_subustr(&d, 1, 0, USTR1(\2, "aa"), 1, 0)); ASSERT(ustr_cmp_cstr_eq(d, "yyyyyyyyyyyyyy")); ASSERT(ustr_sc_sub_subustr(&d, 1, 2, USTR1(\2, "aa"), 1, 2)); ASSERT(ustr_cmp_cstr_eq(d, "aayyyyyyyyyyyy")); ASSERT(ustr_sc_sub_subustr(&d, 1, 2, USTR1(\2, "aa"), 1, 0)); ASSERT(ustr_cmp_cstr_eq(d, "yyyyyyyyyyyy")); ASSERT(ustr_sub_undef(&d, 3, 2)); ASSERT(ustr_sc_sub_undef(&d, 1, 2, 2)); if (!USTR_DEBUG) ASSERT(!ustr_sub_undef(&d, 100, 1)); if (!USTR_DEBUG) ASSERT(!ustr_sub_subustr(&d, 1, USTR1(\4, "abcd"), 4, 2)); if (!USTR_DEBUG) ASSERT(!ustr_sub_subustr(&d, 1, USTR1(\4, "abcd"), 5, 1)); if (!USTR_DEBUG) ASSERT(!ustr_sc_sub_undef(&d, 100, 1, 1)); if (!USTR_DEBUG) ASSERT(!ustr_sc_sub_subustr(&d, 1, 1, USTR1(\4, "abcd"), 4, 2)); if (!USTR_DEBUG) ASSERT(!ustr_sc_sub_subustr(&d, 1, 1, USTR1(\4, "abcd"), 5, 1)); PRINT_RESULT(c); if (!USTR_CONF_HAVE_64bit_SIZE_MAX) /* 10MB is probably enough... */ { ASSERT(ustr_set_rep_chr(&s1, '-', 1000 * 1000 * 10)); ASSERT(!ustr_replace(&s1, USTR1(\1, "-"), s1, 0)); } ustr_sc_free(&a); ustr_sc_free(&c); ustr_sc_free(&d); ustr_sc_free(&needle); ustr_sc_free(&same_len_str); ustr_sc_free(&blank); ustr_sc_free(&ro); /* rep_chr -- shrink string */ haystack = ustr_dup_cstr("xxxBxxCxDxxx"); ASSERT(ustr_replace_rep_chr(&haystack, 'x', 2, 'y', 1, 0) == 3); ASSERT(ustr_cmp_cstr_eq(haystack, "yxByCxDyx")); ustr_sc_free(&haystack); /* rep_chr -- expand string */ haystack = ustr_dup_cstr("yyyyByy"); ASSERT(!ustr_replace_rep_chr(&haystack, 'x', 2, 'a', 2, 0)); ASSERT(ustr_replace_rep_chr(&haystack, 'y', 2, 'a', 3, 0) == 3); ASSERT(ustr_cmp_cstr_eq(haystack, "aaaaaaBaaa")); /* rep_chr -- limited number of searches */ ASSERT(ustr_replace_rep_chr(&haystack, 'a', 2, 'x', 1, 2) == 2); ASSERT(ustr_cmp_cstr_eq(haystack, "xxaaBaaa")); /* rep_chr -- stumble upon nonrepeating character in buffer middle */ ASSERT(ustr_replace_rep_chr(&haystack, 'a', 4, 'x', 1, 2) == 0); ASSERT(ustr_cmp_cstr_eq(haystack, "xxaaBaaa")); /* rep_chr -- shortcut case where end of buffer is not equal to rep_chr */ ASSERT(ustr_replace_rep_chr(&haystack, 'a', 3, 'z', 1, 2) == 1); ASSERT(ustr_cmp_cstr_eq(haystack, "xxaaBz")); ustr_sc_free(&haystack); /* rep_chr -- case where "check the end" succeeds, but multiple characters * interfere in the middle of the buffer */ haystack = ustr_dup_cstr("xxABCDyyEFGyyz"); ASSERT(ustr_replace_rep_chr(&haystack, 'y', 7, 'a', 1, 0) == 0); ASSERT(ustr_cmp_cstr_eq(haystack,"xxABCDyyEFGyyz")); ustr_sc_free(&haystack); /* rep_chr -- case where "check the end" succeeds, has to be skipped * and after the end there is a valid pattern */ haystack = ustr_dup_cstr("xxABCDyyEFGyyyyyyyz"); ASSERT(ustr_replace_rep_chr(&haystack, 'y', 7, 'a', 1, 0) == 1); ASSERT(ustr_cmp_cstr_eq(haystack,"xxABCDyyEFGaz")); ustr_sc_free(&haystack); ustr_sc_free2(&haystack, USTR1(\4, "aaaa")); ASSERT(ustr_replace_rep_chr(&haystack, 'a', 1, 'x', 0, 0) == 4); ASSERT(!ustr_len(haystack)); ASSERT(ustr_ro(haystack)); /* ustr_sc_free2(&s2, USTR("")); ASSERT(ustr_sub(&s2, 1, s2)); ASSERT(ustr_sub_subustr(&s2, 1, s2, 1, 0)); ASSERT(ustr_sc_sub(&s2, 1, 0, s2)); ASSERT(ustr_sc_sub_subustr(&s2, 1, 0, s2, 1, 0)); */ ustr_sc_free2(&s1, USTR1(\1, "x")); ASSERT(ustr_sub(&s1, 1, s1)); ASSERT_EQ(s1, USTR1(\1, "x")); ASSERT(ustr_sub_subustr(&s1, 0, s1, 1, 0)); ASSERT_EQ(s1, USTR1(\1, "x")); ASSERT(ustr_sub_subustr(&s1, 1, s1, 1, 1)); ASSERT_EQ(s1, USTR1(\1, "x")); /* ASSERT(ustr_ro(s1)); */ ustr_sc_free2(&s1, USTR1(\1, "x")); ASSERT(ustr_sc_sub(&s1, 1, 0, s1)); ASSERT_EQ(s1, USTR1(\2, "xx")); ustr_sc_free2(&s1, USTR1(\1, "x")); ASSERT(ustr_sc_sub_subustr(&s1, 1, 0, s1, 1, 0)); ASSERT_EQ(s1, USTR1(\1, "x")); ASSERT(ustr_ro(s1)); num = 0; ustr_sc_free2(&s1, USTR1(\2, "xy")); while (num++ < 6) ASSERT(ustr_sub(&s1, (ustr_len(s1) / 2) + 1, s1)); ASSERT_EQ(s1, USTR1(\x13, "xxxxxxxxxxxxxxxxxxy")); ustr_sc_free2(&s1, USTR1(\2, "xy")); num = 0; while (num++ < 7) { size_t spos = 1; size_t slen = ustr_len(s1); if (slen > 4) { ++spos; --slen; } ASSERT(ustr_sub_subustr(&s1, (ustr_len(s1) / 2) + 1, s1, spos, slen)); } ASSERT_EQ(s1, USTR1(\x15, "xxxxxxxxxxxxxxxxxxxxy")); ustr_sc_free2(&s1, USTR1(\2, "xy")); ASSERT(ustr_sc_sub(&s1, 1, 1, s1)); ASSERT_EQ(s1, USTR1(\3, "xyy")); ASSERT(ustr_sc_sub(&s1, 1, 2, s1)); ASSERT_EQ(s1, USTR1(\4, "xyyy")); ASSERT(ustr_sc_sub(&s1, 4, 1, s1)); ASSERT_EQ(s1, USTR1(\7, "xyyxyyy")); ASSERT(ustr_sc_sub(&s1, 6, 2, s1)); ASSERT_EQ(s1, USTR1(\xC, "xyyxyxyyxyyy")); ASSERT(ustr_sc_sub(&s1, 4, 5, s1)); ASSERT_EQ(s1, USTR1(\x13, "xyyxyyxyxyyxyyyxyyy")); ustr_sc_free2(&s1, USTR1(\5, "1234-")); ASSERT(ustr_sc_sub_subustr(&s1, 1, 1, s1, 1, 2)); ASSERT_EQ(s1, USTR1(\6, "12234-")); ASSERT(ustr_sc_sub_subustr(&s1, 3, 1, s1, 5, 2)); ASSERT_EQ(s1, USTR1(\7, "124-34-")); ASSERT(ustr_sc_sub_subustr(&s1, 3, 2, s1, 4, 1)); ASSERT_EQ(s1, USTR1(\6, "12-34-")); ASSERT(ustr_sc_sub_subustr(&s1, 2, 3, s1, 1, 5)); ASSERT_EQ(s1, USTR1(\x8, "112-344-")); ASSERT(ustr_sc_sub_subustr(&s1, 1, 2, s1, 2, 3)); ASSERT_EQ(s1, USTR1(\x9, "12-2-344-")); ASSERT(ustr_sc_sub_subustr(&s1, 2, 2, s1, 5, 2)); ASSERT_EQ(s1, USTR1(\x9, "1-32-344-")); ASSERT(ustr_sc_sub_subustr(&s1, 3, 3, s1, 4, 2)); ASSERT_EQ(s1, USTR1(\x8, "1-2-344-")); ASSERT(ustr_sc_sub_subustr(&s1, 6, 1, s1, 2, 1)); ASSERT_EQ(s1, USTR1(\x8, "1-2-3-4-")); ASSERT(ustr_sc_sub_subustr(&s1, 1, 8, s1, 1, 7)); ASSERT_EQ(s1, USTR1(\7, "1-2-3-4")); ustr_set_cstr(&s1, "123456789 "); ASSERT(ustr_sub_subustr(&s1, 8, s1, 6, 5)); ASSERT_EQ(s1, USTR1(\xc, "12345676789 ")); ustr_set_cstr(&s1, "123456789 "); ASSERT(ustr_sub_subustr(&s1, 4, s1, 4, 4)); ASSERT_EQ(s1, USTR1(\7, "1234567")); ustr_set_cstr(&s1, "123456789 abcdefghijklmnopqrstuvqxyz"); ASSERT(ustr_sc_sub_subustr(&s1, 4, 8, s1, 6, 12)); ASSERT_EQ(s1, USTR1(\x28, "1236789 abcdefgbcdefghijklmnopqrstuvqxyz")); return (EXIT_SUCCESS); } ustr-1.0.4/examples/0000755000076400007640000000000010763663475013340 5ustar jamesjamesustr-1.0.4/examples/hexdump_data0000644000076400007640000000040010633707147015707 0ustar jamesjames  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿustr-1.0.4/examples/dirname.c0000644000076400007640000000301510755370536015114 0ustar jamesjames#include "ustr.h" /* This is a simple program showing "dirname" */ #include static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); fflush(stderr); exit (EXIT_FAILURE); } /* 1.0.3 is buggy */ size_t u_cspn_chr_rev(const struct Ustr *s1, size_t off, char chr) { size_t f_pos = ustr_srch_chr_rev(s1, off, chr); if (!f_pos) return (ustr_len(s1) - off); return ((ustr_len(s1) - f_pos) - off); } static struct Ustr *u_dirname(const struct Ustr *s2) { size_t off = 0; size_t len = ustr_len(s2); if (!len) return (USTR1(\1, ".")); off = ustr_spn_chr_rev(s2, off, '/'); if (len == off) return (USTR1(\1, "/")); off += u_cspn_chr_rev(s2, off, '/'); if (len == off) return (USTR1(\1, ".")); off += ustr_spn_chr_rev(s2, off, '/'); if (len == off) return (USTR1(\1, "/")); return (ustr_dup_subustr(s2, 1, (len - off))); } int main(int argc, char *argv[]) { const char *prog_name = NULL; Ustr *s1 = USTR_NULL; Ustr *s2 = USTR_NULL; if (!argc) exit (EXIT_FAILURE); if ((prog_name = strrchr(argv[0], '/'))) ++prog_name; else prog_name = argv[0]; if (argc != 2) die(prog_name, "missing operand"); if (!(s1 = ustr_dup_cstr(argv[1]))) die(prog_name, strerror(errno)); if (!(s2 = u_dirname(s1))) die(prog_name, strerror(errno)); ustr_free(s1); if (!ustr_io_putfileline(&s2, stderr)) die(prog_name, strerror(errno)); USTR_CNTL_MALLOC_CHECK_END(); exit (EXIT_SUCCESS); } ustr-1.0.4/examples/mkdir_p.c0000644000076400007640000000534110734753156015126 0ustar jamesjames#include "ustr.h" /* this is a simple program showing how you can make mkdir_p() with Ustr */ #include #include #include static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); exit (EXIT_FAILURE); } static int fu__mkdir_p(const Ustr *s1, int mode, size_t off, int ret) { Ustr *allocd = USTR_NULL; char *ptr = NULL; if (mkdir(ustr_cstr(s1), mode) != -1) return (ret + 1); switch (errno) { case EEXIST: return (ret); case ENOENT: break; default: return (-1); } if ((off = ustr_srch_chr_rev(s1, off, '/')) <= 1) { errno = EINVAL; return (-1); } --off; /* NOTE: offset moves from beg. to end */ if (!ustr_owner(s1)) { /* do it this way, so we can pass constant Ustr's to this function * and don't use ustr_sc_ensure_owner() so that we don't release a * reference */ if (!(allocd = ustr_dup_buf(ustr_cstr(s1), ustr_len(s1)))) return (-1); /* errno == ENOMEM, done by ustr */ s1 = allocd; } ptr = ustr_wstr((Ustr *)s1); ptr[off] = 0; if ((ret = fu__mkdir_p(s1, mode, ustr_len(s1) - off, ret + 1)) != -1) { ptr[off] = '/'; if (mkdir(ustr_cstr(s1), mode) == -1) ret = -1; } ustr_free(allocd); return (ret); } /* This returns -1, on error, or the number of directories created. */ static int mkdir_p(const Ustr *s1, int mode) { return (fu__mkdir_p(s1, mode, 0, 0)); } int main(int argc, char *argv[]) { const char *prog_name = NULL; int scan = 1; Ustr *s1 = USTR(""); USTR_CNTL_MALLOC_CHECK_BEG(USTR_DEBUG); if (!argc) exit (EXIT_FAILURE); if ((prog_name = strrchr(argv[0], '/'))) ++prog_name; else prog_name = argv[0]; #ifdef TST mkdir_p(USTR1(\x24, "/tmp/abcd/1/2/3/4/5/6/7/8/9/10/11/12"), 0700, prog_name); #endif if (argc == 1) die(prog_name, "No arguments given"); while (scan < argc) { int num = 0; if (!ustr_set_cstr(&s1, argv[scan++])) die(prog_name, strerror(ENOMEM)); if ((num = mkdir_p(s1, 0700)) == -1) { int sve_err = errno; /* leaking memory, but we don't care */ die(ustr_cstr(ustr_dup_fmt("%s: mkdir(\"%s\")", prog_name, ustr_cstr(s1))), strerror(sve_err)); } if (num) { Ustr *msg = ustr_dup_fmt(" Created %d leaves of: ", num); if (!msg) die(prog_name, strerror(ENOMEM)); if (!ustr_io_putfile(&msg, stdout)) die(prog_name, strerror(errno)); if (!ustr_io_putfileline(&s1, stdout)) die(prog_name, strerror(errno)); ustr_free(msg); } } ustr_free(s1); USTR_CNTL_MALLOC_CHECK_END(); return (EXIT_SUCCESS); } ustr-1.0.4/examples/Makefile0000644000076400007640000000746010755370605014776 0ustar jamesjames CC = cc AR = ar RANLIB = ranlib WARNS = -W -Wall -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Wno-format-zero-length -Wformat-nonliteral -Wformat-security # -Wfloat-equal -- no floats # DEF_CFLAGS = -Os -g DEF_CFLAGS = -O2 -g # $(WARNS) CFLG_LFS = -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 CFLAGS = $(DEF_CFLAGS) $(CFLG_LFS) CFLG_LIB_OPT = $(CFLAGS) -DUSTR_DEBUG=0 -DNDEBUG CFLG_LIB_DBG = $(CFLAGS) # Compile "normal" using /ustr/include/ustr*.h and /usr/lib/libustr.so PCFLAGS = $(CFLAGS) LDFLAGS = -lustr DEPS = ## Compile "debug" using /ustr/include/ustr*.h and /usr/lib/libustr-debug.so #PCFLAGS = $(CFLAGS) $(WARNS) -DUSTR_DEBUG=1 #LDFLAGS = -lustr-debug #DEPS = ## Compile "inline" using parent dir. #PCFLAGS = $(CFLAGS) -DUSTR_CONF_INCLUDE_CODEONLY_HEADERS=1 -I.. #LDFLAGS = ## Compile "static" using parent dir. #PCFLAGS = $(CFLAGS) -I.. #LDFLAGS = ../libustr.a #PCFLAGS = $(CFLAGS) $(WARNS) -I.. -DUSTR_DEBUG=1 #LDFLAGS = ../libustr-debug.a ## Compile "inline" using ustr-import output # - do nothing ## Compile "inline" using /ustr/include/ustr*.h / ustr-import -c #PCFLAGS = $(CFLAGS) -DUSTR_CONF_INCLUDE_CODEONLY_HEADERS=1 #LDFLAGS = ## Compile "static" opt using ustr-import #PCFLAGS = $(CFLAGS) #DEPS = libustr.a #LDFLAGS = libustr.a ## Compile "static" dbg using ustr-import #PCFLAGS = $(CFLAGS) $(WARNS) #DEPS = libustr-debug.a #LDFLAGS = libustr-debug.a # This is a simple makefile for example programs... ALL = hello_world netstr hexdump nums mkdir_p fgrep txt2html custr \ linecat_buf linecat_sized basename dirname DBG_LIB_STATIC = libustr-debug.a OPT_LIB_STATIC = libustr.a LIB_STATIC = $(DBG_LIB_STATIC) $(OPT_LIB_STATIC) LIB_STATIC_DBG = \ ustr-b-code-a-dbg.o \ ustr-cmp-code-a-dbg.o \ ustr-fmt-code-a-dbg.o \ ustr-io-code-a-dbg.o \ ustr-ins-code-a-dbg.o \ ustr-main-code-a-dbg.o \ ustr-parse-code-a-dbg.o \ ustr-pool-code-a-dbg.o \ ustr-sc-code-a-dbg.o \ ustr-set-code-a-dbg.o \ ustr-spn-code-a-dbg.o \ ustr-srch-code-a-dbg.o \ ustr-utf8-code-a-dbg.o LIB_STATIC_OPT = \ ustr-b-code-a-opt.o \ ustr-cmp-code-a-opt.o \ ustr-fmt-code-a-opt.o \ ustr-io-code-a-opt.o \ ustr-ins-code-a-opt.o \ ustr-main-code-a-opt.o \ ustr-parse-code-a-opt.o \ ustr-pool-code-a-opt.o \ ustr-sc-code-a-opt.o \ ustr-set-code-a-opt.o \ ustr-spn-code-a-opt.o \ ustr-srch-code-a-opt.o \ ustr-utf8-code-a-opt.o all: $(DEPS) $(ALL) libustr.a: $(LIB_STATIC_OPT) @echo Linking A OPT lib: $@ @$(AR) ru $@ $^ @$(RANLIB) $@ libustr-debug.a: $(LIB_STATIC_DBG) @echo Linking A DBG lib: $@ @$(AR) ru $@ $^ @$(RANLIB) $@ %-code-a-opt.o: %-opt-code.c %-code.h %.h @echo Compiling for A OPT lib: $< @$(CC) $(CFLG_LIB_OPT) -o $@ -c $< %-code-a-dbg.o: %-dbg-code.c %-code.h %.h @echo Compiling for A DBG lib: $< @$(CC) $(CFLG_LIB_DBG) -o $@ -c $< hello_world: hello_world.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) netstr: netstr.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) hexdump: hexdump.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) nums: nums.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) mkdir_p: mkdir_p.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) fgrep: fgrep.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) txt2html: txt2html.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) custr: custr.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) linecat_buf: linecat.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) -DCAT_TYPE=1 linecat_sized: linecat.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) -DCAT_TYPE=2 basename: basename.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) dirname: dirname.c $(CC) $(PCFLAGS) -o $@ $< $(LDFLAGS) strip: $(ALL) @for i in $(ALL); do \ echo "Creating: $$i-s"; cp $$i $$i-s; strip $$i-s; \ done clean: rm -f *.o $(ALL) $(LIB_STATIC) *-s ustr-1.0.4/examples/txt2html.c0000644000076400007640000001476510734753156015301 0ustar jamesjames#include "ustr.h" /* This is a simple program showing how you can do the perl code: #!/usr/bin/perl -p # tchrist@perl.com # Sunday, December 19th, 1999 BEGIN { print "\n" } # and the spirit of awk... # first kill all the tabs 1 while s{ \t + } { " " x (length($&)*8 - length($`)%8) }ex; # then the four standard naughty bits s/&/&/g; # must remember to do this one first! s//>/g; # don't close too early s/"/"/g; # only in embedded tags, i guess # make lines break where they should s/^\s*$/

/ || s/$/
/; # make sure spaces aren't squishticated so we # can do indentation and properly align comments s/( {2,})/' ' x length($1)/ge; END { print "
\n" } # ...shall be with us always */ #include #include #include #include #include #include /* -r */ #ifndef _D_EXACT_NAMLEN # define _D_EXACT_NAMLEN(d) strlen((d)->d_name) #endif static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); exit (EXIT_FAILURE); } static void usage(int xcode, const char *prog_name) { fprintf((xcode == EXIT_SUCCESS) ? stdout : stderr, "\ Format: %s [-hV] [filename]...\n\ -h = Print help.\n\ -V = Print version.\n\ ", prog_name); exit (xcode); } static void txt2html(const char *prog_name, Ustr **pline) { Ustr *line = *pline; size_t tab_pos = 0; size_t tab_off = 0; int has_ret = 0; /* convert tabs to spaces */ while ((tab_pos = ustr_srch_chr_fwd(line, tab_off, '\t'))) { size_t tabs_len = ustr_spn_chr_fwd(line, tab_pos - 1, '\t'); size_t spcs_len = (tabs_len * 8) - ((tab_pos - 1) % 8); ustr_sc_sub_rep_chr(&line, tab_pos, tabs_len, ' ', spcs_len); tab_off = tab_pos + spcs_len - 1; } if (ustr_cstr(line)[ustr_len(line) - 1] == '\n') has_ret = 1; if (ustr_spn_chr_fwd(line, 0, ' ') == (ustr_len(line) - has_ret)) ustr_set(&line, USTR1(\3, "

")); /* blank lines start new paragraph */ else { size_t spcs_off = 0; size_t spcs_pos = 0; char buf_rep[USTR_SIZE_FIXED(40 * 6)] = USTR_BEG_FIXED2 " "; Ustr *rep_nbsp = USTR_SC_INIT_AUTO_OSTR(buf_rep, USTR_FALSE, " "); ustr_replace_cstr(&line, "&", "&", 0); ustr_replace_cstr(&line, "<", "<", 0); ustr_replace_cstr(&line, ">", ">", 0); ustr_replace_cstr(&line, "\"", """, 0); ustr_del(&line, has_ret); ustr_add_cstr(&line, "
\n"); /* convert runs of two or more spaces into runs of   */ while ((spcs_pos = ustr_srch_cstr_fwd(line, spcs_off, " "))) { size_t spcs_len = ustr_spn_chr_fwd(line, spcs_pos - 1, ' '); size_t rep = spcs_len; #if USTR_FALSE /* simpler, but slower */ ustr_sc_free2(&rep_nbsp, USTR_SC_INIT_AUTO(buf_rep, USTR_FALSE, 0)); while (rep--) ustr_add_cstr(&rep_nbsp, " "); if (ustr_enomem(rep_nbsp) || !ustr_sc_sub(&line, spcs_pos, spcs_len, rep_nbsp)) die(prog_name, strerror(ENOMEM)); spcs_off = spcs_pos + (spcs_len * strlen(" ")) - 1; #else rep *= strlen(" "); if (rep > ustr_len(rep_nbsp)) { size_t more = rep - ustr_len(rep_nbsp); while (more) { size_t val = more; if (val > ustr_len(rep_nbsp)) val = ustr_len(rep_nbsp); ustr_add_subustr(&rep_nbsp, rep_nbsp, 1, val); more -= val; } } if (ustr_enomem(rep_nbsp) || !ustr_sc_sub_subustr(&line, spcs_pos, spcs_len, rep_nbsp, 1, rep)) die(prog_name, strerror(ENOMEM)); spcs_off = spcs_pos + rep - 1; #endif } ustr_free(rep_nbsp); } if (ustr_enomem(line)) die(prog_name, strerror(errno)); *pline = line; } static void fp_loop(FILE *in, const char *prog_name) { char buf_line[USTR_SIZE_FIXED(160)]; /* enough for two "normal" lines, after that we alloc. */ Ustr *line = USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0); Ustr *beg = USTR1(\5, "\n"); Ustr *end = USTR1(\6, "\n"); if (!ustr_io_putfile(&beg, stdout)) die(prog_name, strerror(errno)); while (ustr_io_getline(&line, in)) { txt2html(prog_name, &line); if (!ustr_io_putfile(&line, stdout)) die(prog_name, strerror(errno)); if (line != USTR(buf_line)) /* re-init */ ustr_sc_free2(&line, USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0)); } if (errno) die(prog_name, strerror(errno)); ustr_free(line); if (!ustr_io_putfile(&end, stdout)) die(prog_name, strerror(errno)); } static void file_loop(Ustr *fname, const char *prog_name, int sure_file) { FILE *fp = NULL; char buf[32 * 1024]; struct stat st[1]; if (!sure_file && ((stat(ustr_cstr(fname), st) == -1) || !S_ISREG(st->st_mode))) return; if (!(fp = fopen(ustr_cstr(fname), "rb"))) die(prog_name, strerror(errno)); setbuffer(fp, buf, sizeof(buf)); if (!ustr_add_cstr(&fname, ":")) die(prog_name, strerror(ENOMEM)); fp_loop(fp, prog_name); if (fclose(fp) == EOF) die(prog_name, strerror(errno)); ustr_free(fname); } static void loop(Ustr *fname, const char *prog_name) { file_loop(fname, prog_name, USTR_FALSE); } int main(int argc, char *argv[]) { struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; int scan = 0; int optchar = -1; const char *prog_name = NULL; if (!argc) usage(EXIT_FAILURE, NULL); if ((prog_name = strrchr(argv[0], '/'))) ++prog_name; else prog_name = argv[0]; while ((optchar = getopt_long(argc, argv, "hV", long_options, NULL)) != -1) switch (optchar) { case '?': usage(EXIT_FAILURE, prog_name); case 'h': usage(EXIT_SUCCESS, prog_name); case 'V': printf("%s version %s\n", prog_name, "1.0.0"); exit (EXIT_SUCCESS); } argc -= optind; argv += optind; if (!argc) fp_loop(stdin, prog_name); scan = 0; while (scan < argc) { if (ustr_cmp_cstr_eq(USTR1(\1, "-"), argv[scan])) fp_loop(stdin, prog_name); else { Ustr *arg = USTR_NULL; if (!(arg = ustr_dup_cstr(argv[scan]))) die(prog_name, strerror(ENOMEM)); loop(arg, prog_name); } ++scan; } USTR_CNTL_MALLOC_CHECK_END(); return (EXIT_SUCCESS); } ustr-1.0.4/examples/fgrep.c0000644000076400007640000003031110734753156014577 0ustar jamesjames#include "ustr.h" /* this is a simple program showing how you can make fgrep --color, with Ustr */ #include #include #include #include #include #include /* -r */ #ifndef _D_EXACT_NAMLEN # define _D_EXACT_NAMLEN(d) strlen((d)->d_name) #endif static const Ustr *colour_beg = USTR1(\x8, "\x1B[01;31m"); static const Ustr *colour_end = USTR1(\x8, "\x1B[00m\x1B[K"); static Ustr *fgrep_srch = USTR_NULL; static Ustr *fgrep_repl = USTR_NULL; static enum { COLOUR_AUTO, COLOUR_ON, COLOUR_SUB_AUTO, COLOUR_OFF } colour_when = COLOUR_AUTO; static int first_only = USTR_FALSE; static int ignore_case = USTR_FALSE; static enum { PRNT_FNAME_AUTO, PRNT_FNAME_ON, PRNT_FNAME_OFF } prnt_fname = PRNT_FNAME_AUTO; static int prnt_line_num = USTR_FALSE; static int recurse = USTR_FALSE; static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); exit (EXIT_FAILURE); } static void usage(int xcode, const char *prog_name) { fprintf((xcode == EXIT_SUCCESS) ? stdout : stderr, "\ Format: %s [-hV] [filename]...\n\ -h = Print help.\n\ -C --colour = When to do colour.\n\ -R --replace = Replacement string.\n\ -V = Print version.\n\ ", prog_name); exit (xcode); } static int grep_srch_only = USTR_FALSE; static int fgrep(const char *prog_name, Ustr **ps1) { size_t num = 0; if (!ignore_case) { if (grep_srch_only) num = ustr_srch_fwd(*ps1, 0, fgrep_srch); else if (!(num = ustr_replace(ps1, fgrep_srch, fgrep_repl, !first_only)) && errno) die(prog_name, strerror(ENOMEM)); } else { if (grep_srch_only) num = ustr_srch_case_fwd(*ps1, 0, fgrep_srch); else { /* so the output is in the correct case, we need to do it "each" hit separately, so we can't have a ustr_replace function */ size_t pos = 0; while ((pos = ustr_srch_case_fwd(*ps1, pos, fgrep_srch))) { ++num; if (!ustr_ins(ps1, pos - 1 + ustr_len(fgrep_srch), colour_end) || !ustr_ins(ps1, pos - 1, colour_beg)) die(prog_name, strerror(ENOMEM)); pos += ustr_len(fgrep_srch) - 1; pos += ustr_len(colour_beg); pos += ustr_len(colour_end); } } } if (!num) ustr_sc_del(ps1); return (!!num); } /* "Simple" Boyer-Moore-Horspool * http://en.wikipedia.org/wiki/Boyer-Moore-Horspool_algorithm */ static unsigned char fast__off_bad[256]; static void fast_analyze(void) { const unsigned char *ptr = (unsigned char *)ustr_cstr(fgrep_srch); size_t olen = ustr_len(fgrep_srch); size_t scan = 0; if (olen > 255) /* it'll be fast "enough", probably */ { ptr += (olen - 255); olen = 255; } /* init. "bad" offset table to max offset */ memset(fast__off_bad, olen, sizeof(fast__off_bad)); /* init. "bad" offset table from data */ --olen; while (scan < olen) { fast__off_bad[ptr[scan]] = olen - scan; if (ignore_case && (((ptr[scan] >= 0x41) && (ptr[scan] <= 0x5A)) || ((ptr[scan] >= 0x61) && (ptr[scan] <= 0x7A)))) fast__off_bad[ptr[scan] ^ 0x20] = olen - scan; ++scan; } } static void *fast_memsrch(const void *passed_hsptr, size_t hslen) { /* case insensitive, ASCII wise */ const unsigned char *hsptr = passed_hsptr; const unsigned char *ndptr = (unsigned char *)ustr_cstr(fgrep_srch); size_t ndlen = ustr_len(fgrep_srch); size_t last = ndlen - 1; while (hslen >= ndlen) { size_t scan = 0; if (!ignore_case) { if ((*hsptr == *ndptr) && !memcmp(hsptr, ndptr, ndlen)) return ((void *) hsptr); } else while (USTR_TRUE) { unsigned char c1 = hsptr[scan]; unsigned char c2 = ndptr[scan]; if ((c1 >= 0x61) && (c1 <= 0x7a)) c1 ^= 0x20; if ((c2 >= 0x61) && (c2 <= 0x7a)) c2 ^= 0x20; if (c1 != c2) break; if (scan++ > last) return ((void *)hsptr); } hslen -= fast__off_bad[hsptr[last]]; hsptr += fast__off_bad[hsptr[last]]; } return (NULL); } static void fp_loop(FILE *in, Ustr *printable_fname, const char *pname) { char buf_line[USTR_SIZE_FIXED(160)]; /* enough for two "normal" lines, after that we alloc. */ Ustr *line = USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0); uintmax_t line_num = 0; while (ustr_io_getline(&line, in)) { ++line_num; if (!fast_memsrch(ustr_cstr(line), ustr_len(line)) || !fgrep(pname, &line)) ustr_sc_del(&line); else { if (prnt_fname == PRNT_FNAME_ON) { Ustr *tmp = ustr_dup(printable_fname); if (!ustr_io_putfile(&tmp, stdout)) die(pname, strerror(errno)); ustr_free(tmp); } if (prnt_line_num) if (fprintf(stdout, "%ju:", line_num) == -1) die(pname, strerror(errno)); if (!ustr_io_putfile(&line, stdout)) die(pname, strerror(errno)); } if (line != USTR(buf_line)) /* re-init */ ustr_sc_free2(&line, USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0)); } if (errno) die(pname, strerror(errno)); ustr_free(line); ustr_free(printable_fname); } static void file_loop(Ustr *fname, const char *prog_name, int sure_file) { FILE *fp = NULL; char buf[32 * 1024]; struct stat st[1]; if (!sure_file && ((stat(ustr_cstr(fname), st) == -1) || !S_ISREG(st->st_mode))) return; if (!(fp = fopen(ustr_cstr(fname), "rb"))) die(prog_name, strerror(errno)); setbuffer(fp, buf, sizeof(buf)); if (!ustr_add_cstr(&fname, ":")) die(prog_name, strerror(ENOMEM)); fp_loop(fp, fname, prog_name); if (fclose(fp) == EOF) die(prog_name, strerror(errno)); } static void loop(Ustr *, const char *); static void dir_loop(Ustr *fname, DIR *dir, const char *prog_name) { struct dirent *ent = NULL; while ((ent = readdir(dir))) { Ustr *dname = NULL; size_t len = _D_EXACT_NAMLEN(ent); if (ustr_cmp_buf_eq(USTR1(\1, "."), ent->d_name, len) || ustr_cmp_buf_eq(USTR1(\2, ".."), ent->d_name, len)) continue; if (!(dname = ustr_dup(fname)) || !ustr_add_cstr(&dname, "/") || !ustr_add_buf(&dname, ent->d_name, len)) die(prog_name, strerror(ENOMEM)); #ifndef _DIRENT_HAVE_D_TYPE loop(dname, prog_name); #else switch (ent->d_type) { case DT_UNKNOWN: /* FALL THROUGH */ case DT_LNK: /* FALL THROUGH */ case DT_DIR: loop(dname, prog_name); break; case DT_REG: file_loop(dname, prog_name, USTR_TRUE); break; default: continue; } #endif } ustr_free(fname); if (closedir(dir) == -1) die(prog_name, strerror(errno)); } static void loop(Ustr *fname, const char *prog_name) { /* NOTE: takes the reference to fname */ DIR *dir = NULL; if ((dir = opendir(ustr_cstr(fname)))) dir_loop(fname, dir, prog_name); else file_loop(fname, prog_name, USTR_FALSE); } int main(int argc, char *argv[]) { struct option long_options[] = { {"with-filename", no_argument, NULL, 'H'}, {"no-filename", no_argument, NULL, 'h'}, {"without-filename", no_argument, NULL, 'h'}, {"recursive", no_argument, NULL, 'r'}, {"replace", required_argument, NULL, 'R'}, {"colour", optional_argument, NULL, 'C'}, {"color", optional_argument, NULL, 'C'}, {"first-only", no_argument, NULL, 'F'}, {"ignore-case", no_argument, NULL, 'i'}, {"line-number", no_argument, NULL, 'n'}, {"help", no_argument, NULL, 2}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; int scan = 0; int optchar = -1; const char *prog_name = NULL; const char *repl_cstr = NULL; if (!argc) exit (EXIT_FAILURE); if ((prog_name = strrchr(argv[0], '/'))) ++prog_name; else prog_name = argv[0]; while ((optchar = getopt_long(argc, argv, "hirCFHRV", long_options, NULL)) != -1) switch (optchar) { case '?': usage(EXIT_FAILURE, prog_name); case 2: usage(EXIT_SUCCESS, prog_name); case 'V': printf("%s version %s\n", prog_name, "1.0.0"); exit (EXIT_SUCCESS); case 'R': repl_cstr = optarg; break; case 'C': if (ustr_cmp_case_cstr_eq(USTR1(\1, "0"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\5, "never"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\2, "no"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\3, "off"), optarg)) colour_when = COLOUR_OFF; if (ustr_cmp_case_cstr_eq(USTR1(\1, "1"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\6, "always"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\3, "yes"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\2, "on"), optarg)) colour_when = COLOUR_ON; if (ustr_cmp_case_cstr_eq(USTR1(\4, "auto"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\5, "maybe"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\3, "tty"), optarg)) colour_when = COLOUR_AUTO; if (ustr_cmp_case_cstr_eq(USTR1(\5, "sub-1"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\xa, "sub-always"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\7, "sub-yes"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\6, "sub-on"), optarg)) colour_when = COLOUR_ON; if (ustr_cmp_case_cstr_eq(USTR1(\x8, "sub-auto"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\x9, "sub-maybe"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\7, "sub-tty"), optarg)) colour_when = COLOUR_SUB_AUTO; if (ustr_cmp_case_cstr_eq(USTR1(\x9, "replace-1"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\xe, "replace-always"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\xb, "replace-yes"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\xa, "replace-on"), optarg)) colour_when = COLOUR_ON; if (ustr_cmp_case_cstr_eq(USTR1(\x8, "replace-auto"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\x9, "replace-maybe"), optarg) || ustr_cmp_case_cstr_eq(USTR1(\xb, "replace-tty"), optarg)) colour_when = COLOUR_SUB_AUTO; break; case 'F': first_only = USTR_TRUE; break; case 'r': recurse = USTR_TRUE; break; case 'i': ignore_case = USTR_TRUE; break; case 'n': prnt_line_num = USTR_TRUE; break; case 'H': prnt_fname = PRNT_FNAME_ON; break; case 'h': prnt_fname = PRNT_FNAME_OFF; break; } argc -= optind; argv += optind; if (!argc) usage(EXIT_FAILURE, prog_name); if (repl_cstr && !(fgrep_repl = ustr_dupx_cstr(0, 0, USTR_TRUE, USTR_FALSE, repl_cstr))) die(prog_name, strerror(ENOMEM)); if (!(fgrep_srch = ustr_dupx_cstr(0, 1, USTR_TRUE, USTR_FALSE, argv[0]))) die(prog_name, strerror(ENOMEM)); fast_analyze(); if (!fgrep_repl) fgrep_repl = ustr_dup(fgrep_srch); else if (colour_when == COLOUR_AUTO) colour_when = COLOUR_OFF; if (colour_when == COLOUR_SUB_AUTO) colour_when = COLOUR_AUTO; if (colour_when == COLOUR_OFF) /* do nothing */ ; else if ((colour_when == COLOUR_AUTO) && !isatty(STDOUT_FILENO)) /* do nothing */ ; else if (!ustr_ins(&fgrep_repl, 0, colour_beg) || !ustr_add(&fgrep_repl, colour_end)) die(prog_name, strerror(ENOMEM)); grep_srch_only = ustr_cmp_eq(fgrep_srch, fgrep_repl); argc -= 1; argv += 1; if (!argc) { if (prnt_fname == PRNT_FNAME_AUTO) prnt_fname = PRNT_FNAME_OFF; fp_loop(stdin, USTR(""), prog_name); } if (recurse || (argc > 1)) if (prnt_fname == PRNT_FNAME_AUTO) prnt_fname = PRNT_FNAME_ON; scan = 0; while (scan < argc) { if (ustr_cmp_cstr_eq(USTR1(\1, "-"), argv[scan])) fp_loop(stdin, USTR(""), prog_name); else { Ustr *arg = USTR_NULL; if (!(arg = ustr_dup_cstr(argv[scan]))) die(prog_name, strerror(ENOMEM)); loop(arg, prog_name); } ++scan; } ustr_free(fgrep_srch); ustr_free(fgrep_repl); USTR_CNTL_MALLOC_CHECK_END(); return (EXIT_SUCCESS); } ustr-1.0.4/examples/netstr.c0000644000076400007640000003260310734753156015021 0ustar jamesjames /* #define USTR_CONF_COMPILE_USE_INLINE 0 */ #include "ustr.h" #include #include #include static int combine = USTR_FALSE; static int fnames = USTR_FALSE; static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); exit (EXIT_FAILURE); } static void usage(const char *prog_name, int xcode) { fprintf((xcode == EXIT_SUCCESS) ? stdout : stderr, "\ Format: %s [-chiV] [string]...\n\ -c = Combine arguments into a single netstr.\n\ -i = Interpret arguments from C-escaping.\n\ -C = Interpret arguments as CSV lists.\n\ -f = Interpret arguments as filenames.\n\ -h = Print help.\n\ -V = Print version.\n\ ", prog_name ? prog_name : "netstr"); exit (xcode); } /* This function is implemented showing how you can simply use the Ustr as a container for storing a growable byte array+length, and then easily do the more complex operations the same way you would if you managed the entire thing by hand using just a malloc() and storing the length separately. */ static int cescape_decode(Ustr **ps1) { /* Convert \n \t etc. into their correct bytes. */ size_t fpos = 0; size_t len = ustr_len(*ps1); char *src = NULL; char *dst = NULL; if (!(fpos = ustr_srch_chr_fwd(*ps1, 0, '\\')) || (fpos == len)) return (USTR_TRUE); if (!(dst = src = ustr_sc_wstr(ps1))) return (USTR_FALSE); --fpos; src += fpos; dst += fpos; len -= fpos; while (len--) { if ((*src != '\\') || !len) { normal: *dst++ = *src++; } else { --len; ++src; switch (*src) { default: goto normal; case '\n': ++src; break; case '"': ++src; break; case '\'': ++src; break; case 'b': ++src; *dst++ = '\b'; break; case 'f': ++src; *dst++ = '\f'; break; case 'n': ++src; *dst++ = '\n'; break; case 'r': ++src; *dst++ = '\r'; break; case 't': ++src; *dst++ = '\t'; break; case 'v': ++src; *dst++ = '\v'; break; case '\\': ++src; *dst++ = '\\'; break; case 'o': case 'O': if ((len < 1) || !isdigit((unsigned char)src[1])) { *dst++ = '\\'; goto normal; } --len; ++src; /* FALL THROUGH */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { unsigned char val = 0; if (USTR_FALSE) { } else if ((len >= 2) && isdigit((unsigned char)src[1]) && isdigit((unsigned char)src[2])) { val = (*src++ - '0'); val *= 8; val += (*src++ - '0'); val *= 8; val += (*src++ - '0'); len -= 2; } else if ((len >= 1) && isdigit((unsigned char)src[1])) { val = (*src++ - '0'); val *= 8; val += (*src++ - '0'); len -= 1; } else val = (*src++ - '0'); *dst++ = val; break; } case 'x': case 'X': { unsigned char val = 0; Ustr *bconv = USTR1(\x16, "0123456789ABCDEFabcdef"); Ustr *uconv = USTR1(\x10, "0123456789ABCDEF"); Ustr *lconv = USTR1(\x6, "abcdef"); size_t pos = 0; if ((len < 2) || /* only does \xDD and not \xDDDD like C */ !ustr_srch_chr_fwd(bconv, 0, src[1]) || !ustr_srch_chr_fwd(bconv, 0, src[2])) { *dst++ = '\\'; goto normal; } if (!(pos = ustr_srch_chr_fwd(uconv, 0, src[1]))) pos = ustr_srch_chr_fwd(lconv, 0, src[1]) + 10; val = pos - 1; val *= 16; if (!(pos = ustr_srch_chr_fwd(uconv, 0, src[2]))) pos = ustr_srch_chr_fwd(lconv, 0, src[2]) + 10; val += pos - 1; *dst++ = val; len -= 2; src += 3; } break; } } } ustr_del(ps1, src - dst); /* chop the end, if we converted */ return (USTR_TRUE); } static Ustr *gen_netstr_buf(const char *buf, size_t len, int interp) { Ustr *tmp = USTR_NULL; Ustr *ret = USTR_NULL; if (interp) { if (!(tmp = ustr_dup_buf(buf, len))) goto fail_mem; if (!cescape_decode(&tmp)) goto fail_mem; if (!(ret = ustr_dup_fmt("%zu:", ustr_len(tmp)))) goto fail_mem; ustr_add(&ret, tmp); } else { if (!(ret = ustr_dup_fmt("%zu:", len))) goto fail_mem; ustr_add_buf(&ret, buf, len); } ustr_add_rep_chr(&ret, ',', 1); if (ustr_enomem(ret)) goto fail_mem; ustr_free(tmp); return (ret); fail_mem: ustr_free(tmp); ustr_free(ret); return (USTR_NULL); } typedef struct Nstrs { Ustr **ptr; size_t sz; size_t num; size_t total; } Nstrs; static int nstrs_add_ustr(Nstrs *nstrs, Ustr *arg) { if (nstrs->num >= nstrs->sz) { Ustr **tmp = NULL; nstrs->sz <<= 1; if (!(tmp = realloc(nstrs->ptr, nstrs->sz * sizeof(Ustr *)))) return (USTR_FALSE); nstrs->ptr = tmp; } nstrs->ptr[nstrs->num] = arg; nstrs->total += ustr_len(nstrs->ptr[nstrs->num++]); return (USTR_TRUE); } static void nstrs_reset(Nstrs *nstrs, size_t num, size_t total) { if (!nstrs) return; while (nstrs->num > num) ustr_sc_free(&nstrs->ptr[--nstrs->num]); nstrs->total = total; } static Nstrs *nstrs_init(void) { Nstrs *nstrs = NULL; if (!(nstrs = malloc(sizeof(Nstrs)))) goto fail_nstrs; nstrs->sz = 32; if (!(nstrs->ptr = calloc(nstrs->sz, sizeof(Ustr *)))) goto fail_nstrs_ptr; nstrs->num = 0; nstrs->total = 0; return (nstrs); fail_nstrs_ptr: free(nstrs); fail_nstrs: return (NULL); } static void nstrs_free(Nstrs *nstrs) { if (!nstrs) return; nstrs_reset(nstrs, 0, 0); free(nstrs->ptr); free(nstrs); } static Ustr *gen_csv_netstr(Nstrs *nstrs, Ustr **pin, FILE *fp, int csv, int interp) { Ustr *in = *pin; size_t onum; size_t ototal; Ustr *ret = USTR_NULL; size_t off = 0; size_t len = ustr_len(in); size_t scan = 0; int saved_errno = -1; if (!csv) return (gen_netstr_buf(ustr_cstr(in), len, interp)); onum = nstrs->num; ototal = nstrs->total; while (off < len) { size_t tmp = 0; char end = '"'; tmp = ustr_spn_cstr_fwd(in, off, " \t\v\r"); if (tmp) { off += tmp; continue; } switch (*(ustr_cstr(in) + off)) { case ',': /* empty entry */ if (!nstrs_add_ustr(nstrs, USTR1(\3, "0:,"))) goto fail_mem_csv; ++off; continue; default: { /* normal single entry */ size_t spaces = 0; size_t data = 0; do { tmp += spaces + data; spaces = ustr_spn_cstr_fwd(in, off + tmp, " \t\v\r"); data = ustr_cspn_cstr_fwd(in, off + tmp + spaces, " \t\v\r,"); } while (data); if (!(ret = gen_netstr_buf(ustr_cstr(in) + off, tmp, USTR_FALSE))) goto fail_mem_csv; if (!nstrs_add_ustr(nstrs, ret)) goto fail_mem_csv; ret = USTR_NULL; off += tmp + spaces; } break; case '\'': end = '\''; case '"': { char cur = 0; ++off; tmp = 0; while (((off + tmp) < len) || fp) { if ((off + tmp) >= len) { /* have a multi-line CSV entry, from a file */ if (!ustr_add_rep_chr(pin, '\n', 1)) goto fail_mem_csv; if (!ustr_io_getline(pin, fp)) goto fail_bad_csv; ustr_del(pin, 1); in = *pin; len = ustr_len(in); } tmp += ustr_cspn_cstr_fwd(in, off + tmp, "\\\"'"); cur = *(ustr_cstr(in) + off + tmp); if (cur == '\\') tmp += 2; else if (cur != end) tmp += 1; else break; } if (cur != end) goto fail_bad_csv; if (!(ret = gen_netstr_buf(ustr_cstr(in) + off, tmp, USTR_TRUE))) goto fail_mem_csv; if (!nstrs_add_ustr(nstrs, ret)) goto fail_mem_csv; ret = USTR_NULL; off += tmp + 1; off += ustr_spn_cstr_fwd(in, off, " \t\v\r"); } break; } if (off >= len) continue; if (*(ustr_cstr(in) + off) != ',') goto fail_bad_csv; if (off != (len - 1)) /* hack for ending in a blank */ ++off; } if (!(ret = ustr_dup_fmt("%zu:", nstrs->total - ototal))) goto fail_mem_csv; scan = onum; while (scan < nstrs->num) ustr_add(&ret, nstrs->ptr[scan++]); ustr_add_rep_chr(&ret, ',', 1); if (ustr_enomem(ret)) goto fail_mem_csv; nstrs_reset(nstrs, onum, ototal); return (ret); fail_mem_csv: saved_errno = ENOMEM; goto fail_csv; fail_bad_csv: saved_errno = EINVAL; goto fail_csv; fail_csv: ustr_free(ret); nstrs_reset(nstrs, onum, ototal); errno = saved_errno; return (USTR_NULL); } static Ustr *gen_csv_netstr_cstr(Nstrs *nstrs, const char *cstr, int csv, int interp) { Ustr *in = ustr_dup_cstr(cstr); Ustr *ret = USTR_NULL; int saved_errno = -1; if (!in) return (USTR_NULL); ret = gen_csv_netstr(nstrs, &in, NULL, csv, interp); saved_errno = errno; ustr_free(in); errno = saved_errno; return (ret); } static void out_combine(const char *prog_name, Nstrs *nstrs) { size_t scan = 0; Ustr *out = ustr_dup_fmt("%zu:", nstrs->total); if (!out) die(prog_name, strerror(ENOMEM)); if (!ustr_io_putfile(&out, stdout)) die(prog_name, strerror(errno)); ustr_sc_free2(&out, USTR1(\2, ",\n")); scan = 0; while (scan < nstrs->num) if (!ustr_io_putfile(&nstrs->ptr[scan++], stdout)) die(prog_name, strerror(errno)); if (!ustr_io_putfile(&out, stdout)) die(prog_name, strerror(errno)); } int main(int argc, char *argv[]) { struct option long_options[] = { {"combine", no_argument, NULL, 'c'}, {"interpret", no_argument, NULL, 'i'}, {"csv", no_argument, NULL, 'C'}, {"filenames", no_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; const char *prog_name = NULL; Nstrs *nstrs = NULL; int scan = 0; int optchar = -1; int interp = USTR_FALSE; int csv = USTR_FALSE; if (!argc) usage(NULL, EXIT_FAILURE); if ((prog_name = strrchr(argv[0], '/'))) ++prog_name; else prog_name = argv[0]; while ((optchar = getopt_long(argc, argv, "cfhiCV", long_options,NULL)) != -1) switch (optchar) { case '?': usage(prog_name, EXIT_FAILURE); case 'h': usage(prog_name, EXIT_SUCCESS); case 'V': printf("%s version %s\n", prog_name, "1.0.0"); exit (EXIT_SUCCESS); case 'c': combine = !combine; break; case 'i': interp = !interp; break; case 'C': csv = !csv; break; case 'f': fnames = !fnames; break; } argc -= optind; argv += optind; if (!argc) usage(prog_name, EXIT_FAILURE); if (combine || csv) if (!(nstrs = nstrs_init())) die(prog_name, strerror(ENOMEM)); if (fnames) { char buf_line[USTR_SIZE_FIXED(160)]; /* enough for two "normal" lines, after that we alloc. */ Ustr *line = USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0); while (scan < argc) { FILE *fp = NULL; if (ustr_cmp_cstr_eq(USTR1(\1, "-"), argv[scan])) fp = stdin; else if (!(fp = fopen(argv[scan], "rb"))) die(prog_name, strerror(errno)); ++scan; nstrs_reset(nstrs, 0, 0); while (ustr_io_getline(&line, fp)) { Ustr *arg = USTR_NULL; ustr_del(&line, ustr_spn_chr_rev(line, 0, '\n')); if (!(arg = gen_csv_netstr(nstrs, &line, fp, csv, interp))) die(prog_name, strerror(errno)); if (combine) { if (!nstrs_add_ustr(nstrs, arg)) die(prog_name, strerror(ENOMEM)); } else { if (!ustr_io_putfileline(&arg, stdout)) die(prog_name, strerror(errno)); ustr_free(arg); } ustr_sc_del(&line); if (line != USTR(buf_line)) /* re-init */ ustr_sc_free2(&line, USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0)); } if (errno) die(prog_name, strerror(errno)); if (line != USTR(buf_line)) /* re-init */ ustr_sc_free2(&line, USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0)); fclose(fp); if (combine) out_combine(prog_name, nstrs); } } else if (!combine) /* Output one per. line */ while (scan < argc) { Ustr *arg = gen_csv_netstr_cstr(nstrs, argv[scan++], csv, interp); if (!arg || !ustr_io_putfileline(&arg, stdout)) die(prog_name, strerror(errno)); ustr_free(arg); } else { while (scan < argc) { Ustr *arg = gen_csv_netstr_cstr(nstrs, argv[scan++], csv, interp); if (!arg) die(prog_name, strerror(errno)); if (!nstrs_add_ustr(nstrs, arg)) die(prog_name, strerror(ENOMEM)); } out_combine(prog_name, nstrs); } nstrs_free(nstrs); USTR_CNTL_MALLOC_CHECK_END(); return (EXIT_SUCCESS); } ustr-1.0.4/examples/linecat.c0000644000076400007640000000575610735013575015125 0ustar jamesjames#include "ustr.h" /* This is a simple program showing "cat", works a line at a time. Mainly an example of simplicity, Ie. Python's "for line in file():" */ #include #define CAT_BUF 1 #define CAT_SIZED 2 #ifndef CAT_TYPE #define CAT_TYPE CAT_SIZED #endif #if 0 #elif CAT_TYPE == CAT_BUF # define fp_loop fp_buf_loop #elif CAT_TYPE == CAT_SIZED # define fp_loop fp_sized_loop #endif static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); fflush(stderr); exit (EXIT_FAILURE); } static void udie(const char *prog_name, const char *fmtmsg, ...) { va_list ap; Ustr *msg = USTR_NULL; va_start(ap, fmtmsg); msg = ustr_dup_vfmt(fmtmsg, ap); va_end(ap); if (!msg) errno = ENOMEM, die(prog_name, strerror(errno)); fprintf(stderr, "%s: ", prog_name); if (!ustr_io_putfileline(&msg, stderr)) die(prog_name, strerror(errno)); fflush(stderr); exit (EXIT_FAILURE); } static void fp_buf_loop(FILE *in, FILE *out, const char *pname) { char buf_line[USTR_SIZE_FIXED(160)]; /* enough for two "normal" lines, after that we alloc. */ Ustr *line = USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0); while (ustr_io_getline(&line, in)) { /* do something with line, this version doesn't touch malloc() at all which * is kind of nice ... although probably not worth it. * It also limits memory used, if there are any "abnormally large" lines. */ if (!ustr_io_putfile(&line, out)) die(pname, strerror(errno)); if (line != USTR(buf_line)) /* re-init */ ustr_sc_free2(&line, USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0)); } if (errno) die(pname, strerror(errno)); ustr_free(line); } static void fp_sized_loop(FILE *in, FILE *out, const char *pname) { Ustr *line = ustr_dupx_empty(128, 0, USTR_TRUE, USTR_FALSE); if (!line) die(pname, strerror(errno)); while (ustr_io_getline(&line, in)) { /* do something with line, note that we can ustr_dup() for O(1) here. * This version keeps memory it allocates, which can be good or bad. */ if (!ustr_io_putfile(&line, out)) die(pname, strerror(errno)); } if (errno) die(pname, strerror(errno)); ustr_free(line); } int main(int argc, char *argv[]) { int scan = 1; const char *prog_name = NULL; if (!argc) exit (EXIT_FAILURE); if ((prog_name = strrchr(argv[0], '/'))) ++prog_name; else prog_name = argv[0]; if (scan == argc) fp_loop(stdin, stdout, prog_name); while (scan < argc) { if (ustr_cmp_cstr_eq(USTR1(\1, "-"), argv[scan])) fp_loop(stdin, stdout, prog_name); else { FILE *fp = NULL; if (!(fp = fopen(argv[scan], "rb"))) udie(prog_name, "open(%s): %s", argv[scan], strerror(errno)); fp_loop(fp, stdout, prog_name); if (fclose(fp) == EOF) die(prog_name, strerror(errno)); } ++scan; } USTR_CNTL_MALLOC_CHECK_END(); return (EXIT_SUCCESS); } ustr-1.0.4/examples/hello_world.c0000644000076400007640000000461610734753156016017 0ustar jamesjames#include "ustr.h" #include static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); exit (EXIT_FAILURE); } /* simplest, just "create" a Ustr from a constant string */ static void hello_world_one(void) { Ustr *hello_world = USTR1_CHK(\xC, "Hello world!"); if (!ustr_io_putfileline(&hello_world, stdout)) die("hello_world", strerror(errno)); } static void hello_world_two(void) { /* next, create a Ustr from a printf() like format. This needs to be * free'd. */ Ustr *out = ustr_dup_fmt("%s %s", "Hello", "world!"); if (!out || !ustr_io_putfileline(&out, stdout)) die("hello_world", strerror(errno)); } static void hello_world_three(void) { /* manually create a Ustr, from multiple parts. Often "significantly faster" * than using ustr_*_fmt(), due to printf overhead. Still needs to allocate * memory, and maybe resize it. Still need to free it. */ Ustr *hello = USTR1(\5, "Hello"); Ustr *sp = USTR1(\1, " "); Ustr *world = USTR1(\6, "world!"); Ustr *out = ustr_dupx_empty(1, 4, USTR_FALSE, USTR_FALSE); if (!out) die("hello_world", strerror(ENOMEM)); ustr_add(&out, hello); ustr_add(&out, sp); ustr_add(&out, world); if (ustr_enomem(out)) /* check all 3 additions at once */ die("hello_world", strerror(ENOMEM)); if (!ustr_io_putfileline(&out, stdout)) die("hello_world", strerror(errno)); ustr_free(out); } static void hello_world_four(void) { /* manually create a Ustr, but use "auto" allocated storage * (stack instead of heap). As long as you don't use more than ustr_size() * you don't need to free. Also note that ustr_dup() will now always copy. */ Ustr *sp = USTR1(\1, " "); Ustr *world = USTR1(\6, "world!"); char buf_out[1024] = USTR_BEG_FIXED2 "Hello"; Ustr *out = USTR_SC_INIT_AUTO(buf_out, USTR_TRUE, 5); ustr_add(&out, sp); ustr_add(&out, world); /* in this can we know !ustr_enomem() as there is more than enough space */ if (!ustr_io_putfileline(&out, stdout)) die("hello_world", strerror(errno)); /* ustr_free() not needed, because nothing was allocated. * Although it's often good to call it anyway, as it does no harm. */ } int main(void) { USTR_CNTL_MALLOC_CHECK_BEG(USTR_DEBUG); hello_world_one(); hello_world_two(); hello_world_three(); hello_world_four(); USTR_CNTL_MALLOC_CHECK_END(); return (EXIT_SUCCESS); } ustr-1.0.4/examples/basename.c0000644000076400007640000000272510755370543015255 0ustar jamesjames#include "ustr.h" /* This is a simple program showing "basename" */ #include static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); fflush(stderr); exit (EXIT_FAILURE); } /* 1.0.3 is buggy */ size_t u_cspn_chr_rev(const struct Ustr *s1, size_t off, char chr) { size_t f_pos = ustr_srch_chr_rev(s1, off, chr); if (!f_pos) return (ustr_len(s1) - off); return ((ustr_len(s1) - f_pos) - off); } static int u_basename(struct Ustr **ps1) { size_t off = 0; size_t len = ustr_len(*ps1); size_t llen = 0; if (!len) return (ustr_set(ps1, USTR(""))); llen = ustr_cspn_chr_rev(*ps1, 0, '/'); if (!llen) { off = ustr_spn_chr_rev(*ps1, off, '/'); llen = u_cspn_chr_rev(*ps1, off, '/'); } if (!llen) return (ustr_set(ps1, USTR1(\1, "/"))); return (ustr_set_subustr(ps1, *ps1, (len - (off + llen)) + 1, llen)); } int main(int argc, char *argv[]) { const char *prog_name = NULL; Ustr *s1 = USTR_NULL; if (!argc) exit (EXIT_FAILURE); if ((prog_name = strrchr(argv[0], '/'))) ++prog_name; else prog_name = argv[0]; if (argc != 2) die(prog_name, "missing operand"); if (!(s1 = ustr_dup_cstr(argv[1]))) die(prog_name, strerror(errno)); if (!u_basename(&s1)) die(prog_name, strerror(errno)); if (!ustr_io_putfileline(&s1, stdout)) die(prog_name, strerror(errno)); USTR_CNTL_MALLOC_CHECK_END(); exit (EXIT_SUCCESS); } ustr-1.0.4/examples/nums.c0000644000076400007640000001234510734753156014465 0ustar jamesjames/* note this only works upto9 uintmax_t size... unlike the Vstr version */ #include "ustr.h" #include #include #include static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); exit (EXIT_FAILURE); } static void usage(const char *prog_name, int xcode) { fprintf((xcode == EXIT_SUCCESS) ? stdout : stderr, "\ Format: %s \n\ -a = All localization, include hex, octal and binary output.\n\ -l = Call system localization to get seperator and groupings.\n\ -h = Print help.\n\ -V = Print version.\n\ ", prog_name ? prog_name : "nums"); exit (xcode); } static void num2ustr(Ustr **buf, uintmax_t num, unsigned int base, const char *steps, const char *sep) { static const char digits[] = "0123456789ABCDEF"; int st_num = 0; ustr_set_empty(buf); while (num) { if ((*steps > 0) && (*steps < CHAR_MAX) && (st_num >= *steps)) { ustr_add_cstr(buf, sep); st_num = 0; if (steps[1]) ++steps; } ustr_add_rep_chr(buf, digits[num % base], 1); ++st_num; num /= base; } if (!ustr_sc_reverse(buf)) abort(); } int main(int argc, char *argv[]) { struct option long_options[] = { {"localization", no_argument, NULL, 'l'}, {"localisation", no_argument, NULL, 'l'}, {"l10n", no_argument, NULL, 'l'}, {"all-localization", no_argument, NULL, 'a'}, {"all-localisation", no_argument, NULL, 'a'}, {"all-l10n", no_argument, NULL, 'a'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; const char *prog_name = NULL; int optchar = -1; int loc = USTR_FALSE; int all_loc = USTR_FALSE; Ustr *s1 = USTR_NULL; Ustr *out = USTR_NULL; char tout_buf[1024]; Ustr *tout = USTR_SC_INIT_AUTO(tout_buf, USTR_FALSE, 0); const char *sep = "_"; const char *xsteps = "\4"; const char *usteps = "\3"; const char *osteps = "\3"; const char *bsteps = "\4"; uintmax_t num = 0; unsigned int flags = (USTR_FLAG_PARSE_NUM_SEP | USTR_FLAG_PARSE_NUM_OVERFLOW | USTR_FLAG_PARSE_NUM_SPACE | USTR_FLAG_PARSE_NUM_EXACT); unsigned int ern = 0; if (!argc) usage(NULL, EXIT_FAILURE); if ((prog_name = strrchr(argv[0], '/'))) ++prog_name; else prog_name = argv[0]; while ((optchar = getopt_long(argc, argv, "alhV", long_options, NULL)) != -1) switch (optchar) { case '?': usage(prog_name, EXIT_FAILURE); case 'h': usage(prog_name, EXIT_SUCCESS); case 'V': printf("%s version %s\n", prog_name, "1.0.0"); exit (EXIT_SUCCESS); case 'a': all_loc = !all_loc; break; case 'l': loc = !loc; break; } argc -= optind; argv += optind; if (argc != 1) usage(prog_name, EXIT_FAILURE); if (!(s1 = ustr_dup_cstr(argv[0]))) die(prog_name, strerror(ENOMEM)); if (!(out = ustr_dup_empty())) die(prog_name, strerror(ENOMEM)); if (loc) { struct lconv *sys_loc = NULL; setlocale(LC_ALL, ""); if ((sys_loc = localeconv())) { if (!(usteps = sys_loc->grouping)) usteps = ""; if (!(sep = sys_loc->thousands_sep)) usteps = ""; if (all_loc) { xsteps = usteps; osteps = usteps; bsteps = usteps; } } } { uintmax_t num_min = INTMAX_MIN; num = ustr_parse_uintmaxx(s1, 0, flags, -num_min, UINTMAX_MAX, sep, NULL, &ern); } ustr_add_fmt(&out, " Input: %s\n", argv[0]); if (ern) switch (ern) { case USTR_TYPE_PARSE_NUM_ERR_ONLY_S: case USTR_TYPE_PARSE_NUM_ERR_ONLY_SPM: case USTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX: case USTR_TYPE_PARSE_NUM_ERR_OOB: ustr_add_fmt(&out, " Error: %u: %s\n", ern, strerror(EINVAL)); break; case USTR_TYPE_PARSE_NUM_ERR_OVERFLOW: ustr_add_fmt(&out, " Error: %u: %s\n", ern, strerror(E2BIG)); break; /* USTR_TYPE_PARSE_NUM_ERR_NEGATIVE USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO */ default: ustr_add_fmt(&out, " Error: %u\n", ern); } ustr_add_cstr(&out, " %#'x = 0x"); num2ustr(&tout, num, 16, xsteps, sep); if (ustr_enomem(tout)) die(prog_name, strerror(ENOMEM)); ustr_add(&out, tout); ustr_add_rep_chr(&out, '\n', 1); ustr_add_cstr(&out, " %#'u = "); num2ustr(&tout, num, 10, usteps, sep); if (ustr_enomem(tout)) die(prog_name, strerror(ENOMEM)); ustr_add(&out, tout); ustr_add_rep_chr(&out, '\n', 1); ustr_add_cstr(&out, " %#'o = 0o"); num2ustr(&tout, num, 8, osteps, sep); if (ustr_enomem(tout)) die(prog_name, strerror(ENOMEM)); ustr_add(&out, tout); ustr_add_rep_chr(&out, '\n', 1); ustr_add_cstr(&out, " %#'b = 0b"); num2ustr(&tout, num, 2, bsteps, sep); if (ustr_enomem(tout)) die(prog_name, strerror(ENOMEM)); ustr_add(&out, tout); ustr_add_rep_chr(&out, '\n', 1); if (ustr_enomem(out)) die(prog_name, strerror(ENOMEM)); if (!ustr_io_putfile(&out, stdout)) die(prog_name, strerror(errno)); /* cleanup */ ustr_free(s1); ustr_free(out); ustr_free(tout); USTR_CNTL_MALLOC_CHECK_END(); exit (EXIT_SUCCESS); } ustr-1.0.4/examples/hexdump.c0000644000076400007640000001152610734753156015155 0ustar jamesjames#include "ustr.h" /* Note that this version of hexdump might well not scale as well, for large * inputs, as things like the example hexdump that comes with Vstr. */ #include #include static int prnt_spac_bytes = USTR_TRUE; static int prnt_high_bytes = USTR_FALSE; static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); exit (EXIT_FAILURE); } static void usage(const char *prog_name, int xcode) { fprintf((xcode == EXIT_SUCCESS) ? stdout : stderr, "\ Format: %s [-hHSV] [filename]...\n\ -S, --space = Print spaces in output.\n\ -H, --high = Print high bytes in output.\n\ -h = Print help.\n\ -V = Print version.\n\ ", prog_name); exit (xcode); } static void conv_unprintable_chr(Ustr *s1, int prnt_h, int prnt_s) { size_t len = ustr_len(s1); char *ptr = ustr_wstr(s1); while (len--) { unsigned char tst = *ptr; if ((tst >= 0x21) && (tst <= 0x7E)) ++ptr; else if (prnt_h && prnt_s && (tst == 0xA0)) /* high space */ ++ptr; else if (prnt_h && (tst >= 0xA1)) /* "high" chars */ ++ptr; else if (prnt_s && (tst == 0x20)) /* space */ ++ptr; else *ptr++ = '.'; } } #define CONF_READ_SZ 16 static unsigned int addr = 0; static void hexdump(Ustr **ps1) { Ustr *s1 = *ps1; char buf[CONF_READ_SZ * 5]; /* each 16 bytes turns into 70 bytes */ Ustr *out = USTR_SC_INIT_AUTO(buf, USTR_FALSE, 0); char buf_line[128]; /* 16 max */ Ustr *line = USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0); size_t len = ustr_len(s1); const unsigned char *ptr = (const unsigned char *)ustr_cstr(s1); while (len >= 16) { ustr_set_buf(&line, ptr, 16); ustr_add_fmt(&out, "0x%08X:" " %02X%02X %02X%02X %02X%02X %02X%02X" " %02X%02X %02X%02X %02X%02X %02X%02X ", addr, ptr[ 0], ptr[ 1], ptr[ 2], ptr[ 3], ptr[ 4], ptr[ 5], ptr[ 6], ptr[ 7], ptr[ 8], ptr[ 9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]); conv_unprintable_chr(line, prnt_high_bytes, prnt_spac_bytes); ustr_add(&out, line); ustr_add_cstr(&out, "\n"); addr += 16; len -= 16; ptr += 16; } if (len) { size_t missing = 16 - len; missing -= (missing % 2); ustr_set_buf(&line, ptr, len); ustr_add_fmt(&out, "0x%08X:", addr); while (len >= 2) { ustr_add_fmt(&out, " %02X%02X", (unsigned)ptr[ 0], ptr[ 1]); len -= 2; ptr += 2; } if (len) { ustr_add_fmt(&out, " %02X ", ptr[ 0]); len -= 1; ptr += 1; } ustr_add_rep_chr(&out, ' ', (missing * 2) + (missing / 2) + 2); conv_unprintable_chr(line, prnt_high_bytes, prnt_spac_bytes); ustr_add(&out, line); ustr_add_cstr(&out, "\n"); addr += ustr_len(line); } ustr_set(ps1, out); ustr_free(out); ustr_free(line); } static void loop(Ustr **io, FILE *in, const char *prog_name) { int last = USTR_FALSE; size_t got = 0; while (!last && ustr_io_get(io, in, CONF_READ_SZ, &got)) { last = got != CONF_READ_SZ; hexdump(io); if (!ustr_io_putfile(io, stdout)) die(prog_name, strerror(errno)); } } int main(int argc, char *argv[]) { struct option long_options[] = { {"space", no_argument, NULL, 'S'}, {"high", no_argument, NULL, 'H'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; const char *prog_name = NULL; Ustr *io = NULL; int scan = 0; int optchar = -1; if (!argc) exit (EXIT_FAILURE); if ((prog_name = strrchr(argv[0], '/'))) ++prog_name; else prog_name = argv[0]; while ((optchar = getopt_long(argc, argv, "hHSV", long_options, NULL)) != -1) switch (optchar) { case '?': usage(prog_name, EXIT_FAILURE); case 'h': usage(prog_name, EXIT_SUCCESS); case 'V': printf("%s version %s\n", prog_name, "1.0.0"); exit (EXIT_SUCCESS); case 'H': prnt_high_bytes = !prnt_high_bytes; break; case 'S': prnt_spac_bytes = !prnt_spac_bytes; break; } argc -= optind; argv += optind; if (!(io = ustr_dupx_empty(4096, 0, USTR_FALSE, USTR_FALSE))) die(prog_name, strerror(ENOMEM)); if (!argc) loop(&io, stdin, prog_name); scan = 0; while (scan < argc) { if (ustr_cmp_cstr_eq(USTR1(\1, "-"), argv[scan])) loop(&io, stdin, prog_name); else { FILE *fp = fopen(argv[scan], "rb"); if (!fp) die(prog_name, strerror(errno)); loop(&io, fp, prog_name); if (ferror(fp)) die(prog_name, strerror(errno)); fclose(fp); } ++scan; } ustr_free(io); /* to make it allocation "clean" */ USTR_CNTL_MALLOC_CHECK_END(); return (EXIT_SUCCESS); } ustr-1.0.4/examples/custr.c0000644000076400007640000002445010734753156014643 0ustar jamesjames/* #define USTR_CONF_COMPILE_USE_INLINE 0 */ #include "ustr.h" #include #include #include static int combine = USTR_FALSE; static int interp = USTR_FALSE; static int fnames = USTR_FALSE; static void die(const char *prog_name, const char *msg) { fprintf(stderr, "%s: %s\n", prog_name, msg); exit (EXIT_FAILURE); } static void usage(const char *prog_name, int xcode) { fprintf((xcode == EXIT_SUCCESS) ? stdout : stderr, "\ Format: %s [-cfhiV] [string]...\n\ -c = Combine arguments into single line.\n\ -f = Interpret arguments as filenames.\n\ -i = Interpret arguments from C-escaping.\n\ -h = Print help.\n\ -V = Print version.\n\ ", prog_name ? prog_name : "ustr"); exit (xcode); } /* NOTE: copied from netstr ... */ /* This function is implemented showing how you can simply use the Ustr as a container for storing a growable byte array+length, and then easily do the more complex operations the same way you would if you managed the entire thing by hand using just a malloc() and storing the length separately. */ static int cescape_decode(Ustr **ps1) { /* Convert \n \t etc. into their correct bytes. */ size_t fpos = 0; size_t len = ustr_len(*ps1); char *src = NULL; char *dst = NULL; if (!(fpos = ustr_srch_chr_fwd(*ps1, 0, '\\')) || (fpos == len)) return (USTR_TRUE); if (!(dst = src = ustr_sc_wstr(ps1))) return (USTR_FALSE); --fpos; src += fpos; dst += fpos; len -= fpos; while (len--) { if ((*src != '\\') || !len) { normal: *dst++ = *src++; } else { --len; ++src; switch (*src) { default: goto normal; case '\n': ++src; break; case '"': ++src; break; case '\'': ++src; break; case 'b': ++src; *dst++ = '\b'; break; case 'f': ++src; *dst++ = '\f'; break; case 'n': ++src; *dst++ = '\n'; break; case 'r': ++src; *dst++ = '\r'; break; case 't': ++src; *dst++ = '\t'; break; case 'v': ++src; *dst++ = '\v'; break; case '\\': ++src; *dst++ = '\\'; break; case 'o': case 'O': if ((len < 1) || !isdigit((unsigned char)src[1])) { *dst++ = '\\'; goto normal; } --len; ++src; /* FALL THROUGH */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { unsigned char val = 0; if (USTR_FALSE) { } else if ((len >= 2) && isdigit((unsigned char)src[1]) && isdigit((unsigned char)src[2])) { val = (*src++ - '0'); val *= 8; val += (*src++ - '0'); val *= 8; val += (*src++ - '0'); len -= 2; } else if ((len >= 1) && isdigit((unsigned char)src[1])) { val = (*src++ - '0'); val *= 8; val += (*src++ - '0'); len -= 1; } else val = (*src++ - '0'); *dst++ = val; break; } case 'x': case 'X': { unsigned char val = 0; Ustr *bconv = USTR1(\x16, "0123456789ABCDEFabcdef"); Ustr *uconv = USTR1(\x10, "0123456789ABCDEF"); Ustr *lconv = USTR1(\x6, "abcdef"); size_t pos = 0; if ((len < 2) || /* only does \xDD and not \xDDDD like C */ !ustr_srch_chr_fwd(bconv, 0, src[1]) || !ustr_srch_chr_fwd(bconv, 0, src[2])) { *dst++ = '\\'; goto normal; } if (!(pos = ustr_srch_chr_fwd(uconv, 0, src[1]))) pos = ustr_srch_chr_fwd(lconv, 0, src[1]) + 10; val = pos - 1; val *= 16; if (!(pos = ustr_srch_chr_fwd(uconv, 0, src[2]))) pos = ustr_srch_chr_fwd(lconv, 0, src[2]) + 10; val += pos - 1; *dst++ = val; len -= 2; src += 3; } break; } } } ustr_del(ps1, src - dst); /* chop the end, if we converted */ return (USTR_TRUE); } static int cescape_encode(Ustr **ret, const char *src, size_t len) { /* Convert to a C-style string ... lowest common denominator, * mostly use: \xXX. */ const char *last = NULL; if (!ustr_sc_ensure_owner(ret)) return (USTR_FALSE); ustr_add_rep_chr(ret, '"', 1); last = src; while (len--) { if ((*src == 0x20) || (*src == 0x21) || /* not 0x22 == " */ ((*src >= 0x23) && (*src <= 0x7E))) ++src; else { if (last != src) ustr_add_buf(ret, last, src - last); switch (*src) { case '\b': ustr_add_cstr(ret, "\\b"); break; case '\f': ustr_add_cstr(ret, "\\f"); break; case '\n': ustr_add_cstr(ret, "\\n"); break; case '\r': ustr_add_cstr(ret, "\\r"); break; case '\t': ustr_add_cstr(ret, "\\t"); break; case '\v': ustr_add_cstr(ret, "\\v"); break; default: if (!len || /* no problems with merging */ !(((src[1] >= '0') && (src[1] <= '9')) || ((src[1] >= 'A') && (src[1] <= 'F')) || ((src[1] >= 'a') && (src[1] <= 'f')))) { if (!*src) ustr_add_cstr(ret, "\\0"); else ustr_add_fmt(ret, "\\x%02hhX", *src); } else if (!*src) ustr_add_cstr(ret, "\" \"\\0\" \""); else ustr_add_fmt(ret, "\\x%02hhX\" \"", *src); } ++src; last = src; } } if (last != src) ustr_add_buf(ret, last, src - last); ustr_add_rep_chr(ret, '"', 1); return (!ustr_enomem(*ret)); } static Ustr *gen_custr_beg(size_t len) { if (len > 65535) return (ustr_dup_fmt("USTR1(\\x%zX, \\x%02zX, \\x%02zX, \\x%02zX, ", ((len >> 24) & 0xFF), ((len >> 16) & 0xFF), ((len >> 8) & 0xFF), ((len >> 0) & 0xFF))); if (len > 255) return (ustr_dup_fmt("USTR2(\\x%zX, \\x%02zX, ", ((len >> 8) & 0xFF), ((len >> 0) & 0xFF))); if (len > 7) return (ustr_dup_fmt("USTR1(\\x%zX, ", len)); return (ustr_dup_fmt("USTR1(\\%zo, ", len)); } static Ustr *gen_custr_buf(const char *buf, size_t len) { Ustr *tmp = USTR_NULL; Ustr *ret = USTR_NULL; if (interp) { if (!(tmp = ustr_dup_buf(buf, len))) goto fail_mem; if (!cescape_decode(&tmp)) goto fail_mem; if (!(ret = gen_custr_beg(ustr_len(tmp)))) goto fail_mem; if (!cescape_encode(&ret, ustr_cstr(tmp), ustr_len(tmp))) goto fail_mem; } else { if (!(ret = gen_custr_beg(len))) goto fail_mem; if (!cescape_encode(&ret, buf, len)) goto fail_mem; } if (!ustr_add_cstr(&ret, ");")) goto fail_mem; ustr_free(tmp); return (ret); fail_mem: ustr_free(tmp); ustr_free(ret); return (USTR_NULL); } static void custr(Ustr *data, const char *prog_name) { Ustr *arg = USTR_NULL; if (!(arg = gen_custr_buf(ustr_cstr(data), ustr_len(data)))) die(prog_name, strerror(errno)); if (!ustr_io_putfileline(&arg, stdout)) die(prog_name, strerror(errno)); ustr_free(arg); } int main(int argc, char *argv[]) { struct option long_options[] = { {"combine", no_argument, NULL, 'c'}, {"interpret", no_argument, NULL, 'i'}, {"filenames", no_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; int scan = 0; int optchar = -1; const char *prog_name = NULL; if (!argc) usage(NULL, EXIT_FAILURE); if ((prog_name = strrchr(argv[0], '/'))) ++prog_name; else prog_name = argv[0]; while ((optchar = getopt_long(argc, argv, "cfhiV", long_options,NULL)) != -1) switch (optchar) { case '?': usage(prog_name, EXIT_FAILURE); case 'h': usage(prog_name, EXIT_SUCCESS); case 'V': printf("%s version %s\n", prog_name, "1.0.0"); exit (EXIT_SUCCESS); case 'c': combine = !combine; break; case 'f': fnames = !fnames; break; case 'i': interp = !interp; break; } argc -= optind; argv += optind; if (!argc) usage(prog_name, EXIT_FAILURE); if (fnames) { char buf_line[USTR_SIZE_FIXED(160)]; /* enough for two "normal" lines, after that we alloc. */ Ustr *line = USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0); while (scan < argc) { FILE *fp = NULL; if (ustr_cmp_cstr_eq(USTR1(\1, "-"), argv[scan])) fp = stdin; else if (!(fp = fopen(argv[scan], "rb"))) die(prog_name, strerror(errno)); ++scan; if (combine) { if (!ustr_io_getfile(&line, fp)) die(prog_name, strerror(errno)); custr(line, prog_name); } else { while (ustr_io_getline(&line, fp)) { ustr_del(&line, ustr_spn_chr_rev(line, 0, '\n')); custr(line, prog_name); ustr_sc_del(&line); if (line != USTR(buf_line)) /* re-init */ ustr_sc_free2(&line, USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0)); } if (errno) die(prog_name, strerror(errno)); } if (line != USTR(buf_line)) /* re-init */ ustr_sc_free2(&line, USTR_SC_INIT_AUTO(buf_line, USTR_FALSE, 0)); fclose(fp); } } else if (!combine) /* Output one per. line */ while (scan < argc) { Ustr *arg = gen_custr_buf(argv[scan], strlen(argv[scan])); if (!arg || !ustr_io_putfileline(&arg, stdout)) die(prog_name, strerror(errno)); ustr_free(arg); ++scan; } else { char buf_args[USTR_SIZE_FIXED(160)]; /* enough for two "normal" lines, after that we alloc. */ Ustr *args = USTR_SC_INIT_AUTO(buf_args, USTR_FALSE, 0); int done = USTR_FALSE; while (scan < argc) { if (done) ustr_add_cstr(&args, " "); done = USTR_TRUE; ustr_add_cstr(&args, argv[scan++]); } if (ustr_enomem(args)) die(prog_name, strerror(ENOMEM)); custr(args, prog_name); ustr_free(args); } USTR_CNTL_MALLOC_CHECK_END(); return (EXIT_SUCCESS); } ustr-1.0.4/ustr-replace.h0000644000076400007640000000446610673031607014275 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_REPLACE_H #define USTR_REPLACE_H 1 #ifndef USTR_MAIN_H # error " You should include ustr-main.h before this file, or just ustr.h" #endif USTR_CONF_E_PROTO size_t ustr_replace_buf(struct Ustr **, const void *, size_t, const void *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO size_t ustr_replace_cstr(struct Ustr **, const char *, const char *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_replace(struct Ustr **, const struct Ustr *, const struct Ustr *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO size_t ustr_replace_rep_chr(struct Ustr **, char, size_t, char, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO size_t ustrp_replace_buf(struct Ustr_pool *, struct Ustrp **, const void *, size_t, const void *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3, 5)); USTR_CONF_EI_PROTO size_t ustrp_replace_cstr(struct Ustr_pool *, struct Ustrp **, const char *, const char *, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3, 4)); USTR_CONF_E_PROTO size_t ustrp_replace(struct Ustr_pool *, struct Ustrp **, const struct Ustrp *, const struct Ustrp *, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3, 4)); USTR_CONF_E_PROTO size_t ustrp_replace_rep_chr(struct Ustr_pool *, struct Ustrp **, char, size_t, char, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-replace-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-replace-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO size_t ustrp_replace_cstr(struct Ustr_pool *p, struct Ustrp **s1, const char *oc, const char *nc, size_t lim) { return (ustrp_replace_buf(p, s1, oc, strlen(oc), nc, strlen(nc), lim)); } USTR_CONF_II_PROTO size_t ustr_replace_cstr(struct Ustr **s1, const char *oc, const char *nc, size_t lim) { return (ustr_replace_buf(s1, oc, strlen(oc), nc, strlen(nc), lim)); } #endif #endif ustr-1.0.4/ustr-set-code.h0000644000076400007640000002070710754707576014400 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SET_H #error " You should have already included ustr-set.h, or just include ustr.h." #endif USTR_CONF_i_PROTO int ustrp__set_undef(struct Ustr_pool *p, struct Ustr **ps1, size_t nlen) { struct Ustr *s1 = USTR_NULL; struct Ustr *ret = USTR_NULL; size_t clen = 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)); s1 = *ps1; clen = ustr_len(s1); if (nlen == clen) { if (ustr_owner(s1)) return (USTR_TRUE); } else if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc)) { if (nlen > clen) return (ustrp__add_undef(p, ps1, (nlen - clen))); else return (ustrp__del(p, ps1, (clen - nlen))); } else if (ustr_limited(s1)) goto fail_enomem; if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen))) goto fail_enomem; ustrp__sc_free2(p, ps1, ret); return (USTR_TRUE); fail_enomem: ustr_setf_enomem_err(s1); return (USTR_FALSE); } USTR_CONF_I_PROTO int ustr_set_undef(struct Ustr **ps1, size_t nlen) { return (ustrp__set_undef(0, ps1, nlen)); } USTR_CONF_I_PROTO int ustrp_set_undef(struct Ustr_pool *p, struct Ustrp **ps1, size_t nlen) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__set_undef(p, &tmp, nlen); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__set_empty(struct Ustr_pool *p, struct Ustr **ps1) { struct Ustr *ret = USTR_NULL; USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); if (ustr_sized(*ps1) && ustr_owner(*ps1)) return (ustrp__del(p, ps1, ustr_len(*ps1))); if (!(ret = ustrp__dupx_empty(p, USTR__DUPX_FROM(*ps1)))) { ustr_setf_enomem_err(*ps1); return (USTR_FALSE); } ustrp__sc_free2(p, ps1, ret); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_set_empty(struct Ustr **ps1) { return (ustrp__set_empty(0, ps1)); } USTR_CONF_I_PROTO int ustrp_set_empty(struct Ustr_pool *p, struct Ustrp **ps1) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__set_empty(p, &tmp); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__set_buf(struct Ustr_pool *p, struct Ustr **ps1, const void *buf, size_t len) { USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); if (!ustrp__set_undef(p, ps1, len)) return (USTR_FALSE); ustr__memcpy(*ps1, 0, buf, len); USTR_ASSERT(ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_set_buf(struct Ustr **ps1, const void *buf, size_t len) { return (ustrp__set_buf(0, ps1, buf, len)); } USTR_CONF_I_PROTO int ustrp_set_buf(struct Ustr_pool *p, struct Ustrp **ps1, const void *buf, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__set_buf(p, &tmp, buf, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__set(struct Ustr_pool *p, struct Ustr **ps1, const struct Ustr *s2) { struct Ustr *ret = USTR_NULL; USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1) && ustrp__assert_valid(!!p, s2)); if (*ps1 == s2) return (USTR_TRUE); if (ustr__treat_as_buf(*ps1, 0, ustr_len(s2))) return (ustrp__set_buf(p, ps1, ustr_cstr(s2), ustr_len(s2))); 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_set(struct Ustr **ps1, const struct Ustr *s2) { return (ustrp__set(0, ps1, s2)); } USTR_CONF_I_PROTO int ustrp_set(struct Ustr_pool *p, struct Ustrp **ps1, const struct Ustrp *s2) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__set(p, &tmp, &s2->s); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__set_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)); if (!len) return (ustrp__del(p, ps1, ustr_len(*ps1))); clen = ustrp__assert_valid_subustr(!!p, s2, pos, len); if (!clen) return (USTR_FALSE); if (len == clen) return (ustrp__set(p, ps1, s2)); if ((*ps1 == s2) && ustr_owner(s2) && ustr_alloc(s2)) { /* only one reference, so we can't take _cstr() before we realloc */ --pos; ustrp__del(p, ps1, clen - (pos + len)); /* delete bit after */ ustrp__del_subustr(p, ps1, 1, pos); /* delete bit before */ return (USTR_TRUE); } return (ustrp__set_buf(p, ps1, ustr_cstr(s2) + pos - 1, len)); } USTR_CONF_I_PROTO int ustr_set_subustr(struct Ustr **ps1, const struct Ustr *s2, size_t pos, size_t len) { return (ustrp__set_subustr(0, ps1, s2, pos, len)); } USTR_CONF_I_PROTO int ustrp_set_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__set_subustr(p, &tmp, &s2->s, pos, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__set_rep_chr(struct Ustr_pool *p, struct Ustr **ps1, char chr, size_t len) { USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); if (!ustrp__set_undef(p, ps1, len)) return (USTR_FALSE); ustr__memset(*ps1, 0, chr, len); USTR_ASSERT(ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_set_rep_chr(struct Ustr **ps1, char chr, size_t len) { return (ustrp__set_rep_chr(0, ps1, chr, len)); } USTR_CONF_I_PROTO int ustrp_set_rep_chr(struct Ustr_pool *p, struct Ustrp **ps1, char chr, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__set_rep_chr(p, &tmp, chr, len); *ps1 = USTRP(tmp); return (ret); } #ifdef USTR_FMT_H # if USTR_CONF_HAVE_VA_COPY USTR_CONF_i_PROTO int ustrp__set_vfmt_lim(struct Ustr_pool *p, struct Ustr **ps1, size_t lim, const char *fmt, va_list ap) { /* NOTE: Copy and pasted so we can use ustrp_set_undef() */ va_list nap; int rc = -1; char buf[USTR__SNPRINTF_LOCAL]; USTR__VA_COPY(nap, ap); rc = USTR_CONF_VSNPRINTF_BEG(buf, sizeof(buf), fmt, nap); va_end(nap); if ((rc == -1) && ((rc = ustr__retard_vfmt_ret(fmt, ap)) == -1)) return (USTR_FALSE); if (lim && ((size_t)rc > lim)) rc = lim; if ((size_t)rc < sizeof(buf)) /* everything is done */ return (ustrp__set_buf(p, ps1, buf, rc)); if (!ustrp__set_undef(p, ps1, rc)) return (USTR_FALSE); USTR_CONF_VSNPRINTF_END(ustr_wstr(*ps1), rc + 1, fmt, ap); USTR_ASSERT(ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_set_vfmt_lim(struct Ustr **ps1, size_t lim, const char *fmt, va_list ap) { return (ustrp__set_vfmt_lim(0, ps1, lim, fmt, ap)); } USTR_CONF_I_PROTO int ustrp_set_vfmt_lim(struct Ustr_pool *p,struct Ustrp **ps1, size_t lim, const char *fmt, va_list ap) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__set_vfmt_lim(p, &tmp, lim, fmt, ap); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_I_PROTO int ustr_set_fmt_lim(struct Ustr **ps1, size_t lim, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustr_set_vfmt_lim(ps1, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustrp_set_fmt_lim(struct Ustr_pool *p, struct Ustrp **ps1, size_t lim, const char*fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustrp_set_vfmt_lim(p, ps1, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustr_set_vfmt(struct Ustr **ps1, const char *fmt, va_list ap) { return (ustr_set_vfmt_lim(ps1, 0, fmt, ap)); } USTR_CONF_I_PROTO int ustrp_set_vfmt(struct Ustr_pool *p, struct Ustrp **ps1, const char *fmt, va_list ap) { return (ustrp_set_vfmt_lim(p, ps1, 0, fmt, ap)); } USTR_CONF_I_PROTO int ustr_set_fmt(struct Ustr **ps1, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustr_set_vfmt(ps1, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustrp_set_fmt(struct Ustr_pool *p, struct Ustrp **ps1, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustrp_set_vfmt(p, ps1, fmt, ap); va_end(ap); return (ret); } # endif #endif ustr-1.0.4/ustr-compiler.h0000644000076400007640000001364310755371054014475 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_MAIN_H #error " Include ustr.h or ustr-main.h before this file." #endif #ifndef USTR_CONF_HAVE_64bit_SIZE_MAX #define USTR_CONF_HAVE_64bit_SIZE_MAX 0 #endif #ifndef USTR_CONF_HAVE_ATTR_FMT #define USTR_CONF_HAVE_ATTR_FMT 1 #endif /* We assume this is enough, * C99 specifies that va_copy() exists and is a macro */ #ifdef va_copy # define USTR_CONF_HAVE_VA_COPY 1 # define USTR__VA_COPY(x, y) va_copy(x, y) #elif __va_copy # define USTR_CONF_HAVE_VA_COPY 1 # define USTR__VA_COPY(x, y) __va_copy(x, y) #else # define USTR_CONF_HAVE_VA_COPY 0 #endif #ifndef USTR_CONF_HAVE_ATTR_NONNULL #if defined(__GNUC__) && (__GNUC__ > 3) /* not sure */ #define USTR_CONF_HAVE_ATTR_NONNULL 1 #else #define USTR_CONF_HAVE_ATTR_NONNULL 0 #endif #endif #ifndef USTR_CONF_HAVE_ATTR_PURE #if defined(__GNUC__) && \ ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 96))) #define USTR_CONF_HAVE_ATTR_PURE 1 #else #define USTR_CONF_HAVE_ATTR_PURE 0 #endif #endif #ifndef USTR_CONF_HAVE_ATTR_CONST #if defined(__GNUC__) && \ ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 5))) #define USTR_CONF_HAVE_ATTR_CONST 1 #else #define USTR_CONF_HAVE_ATTR_CONST 0 #endif #endif #ifndef USTR_CONF_HAVE_ATTR_MALLOC #if defined(__GNUC__) && (__GNUC__ > 3) /* not sure */ #define USTR_CONF_HAVE_ATTR_MALLOC 1 #else #define USTR_CONF_HAVE_ATTR_MALLOC 0 #endif #endif #ifndef USTR_CONF_HAVE_ATTR_WARN_UNUSED_RET #if defined(__GNUC__) && (__GNUC__ > 3) /* not sure */ #define USTR_CONF_HAVE_ATTR_WARN_UNUSED_RET 1 #else #define USTR_CONF_HAVE_ATTR_WARN_UNUSED_RET 0 #endif #endif #ifndef USTR_CONF_HAVE_ATTR_UNUSED #if defined(__GNUC__) && \ ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 96))) /*before? */ #define USTR_CONF_HAVE_ATTR_UNUSED 1 #else #define USTR_CONF_HAVE_ATTR_UNUSED 0 #endif #endif #ifndef USTR_CONF_HAVE_ATTR_DEPRECATED #if defined(__GNUC__) && (__GNUC__ > 3) /* not sure */ #define USTR_CONF_HAVE_ATTR_DEPRECATED 1 #else #define USTR_CONF_HAVE_ATTR_DEPRECATED 0 #endif #endif #ifndef USTR_CONF_HAVE_ATTR_SENTINEL #if defined(__GNUC__) && \ ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1))) /*before? */ #define USTR_CONF_HAVE_ATTR_SENTINEL 1 #else #define USTR_CONF_HAVE_ATTR_SENTINEL 0 #endif #endif #if USTR_CONF_COMPILE_USE_INLINE #define USTR__INLINE inline #else #define USTR__INLINE /* no inline */ #endif #ifndef USTR_CONF_E_PROTO /* external */ # if USTR_CONF_INCLUDE_CODEONLY_HEADERS # define USTR_CONF_E_PROTO static USTR__INLINE # else # define USTR_CONF_E_PROTO extern # endif #endif #ifndef USTR_CONF_I_PROTO /* implementation */ # if USTR_CONF_INCLUDE_CODEONLY_HEADERS # define USTR_CONF_I_PROTO static USTR__INLINE # else # define USTR_CONF_I_PROTO # endif #endif #ifndef USTR_CONF_EI_PROTO /* external inline */ # if USTR_CONF_INCLUDE_CODEONLY_HEADERS # define USTR_CONF_EI_PROTO static USTR__INLINE # else # define USTR_CONF_EI_PROTO extern # endif #endif #ifndef USTR_CONF_II_PROTO /* implementation of inline */ # if USTR_CONF_INCLUDE_CODEONLY_HEADERS # define USTR_CONF_II_PROTO static USTR__INLINE # else # define USTR_CONF_II_PROTO extern inline # endif #endif #ifndef USTR_CONF_e_PROTO /* internal, unless INCLUDE_CODEONLY_HEADERS=1 */ #define USTR_CONF_e_PROTO static USTR__INLINE #endif #ifndef USTR_CONF_i_PROTO /* implementation of "external", dito. */ #define USTR_CONF_i_PROTO static USTR__INLINE #endif /* GCC helper macros */ #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ USTR_CONF_HAVE_ATTR_FMT && USTR_CONF_COMPILE_USE_ATTRIBUTES # define USTR__COMPILE_ATTR_FMT(x, y) \ __attribute__ ((__format__ (__printf__, x, y))) #else # define USTR__COMPILE_ATTR_FMT(x, y) /* nothing */ #endif #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ USTR_CONF_HAVE_ATTR_NONNULL && USTR_CONF_COMPILE_USE_ATTRIBUTES # define USTR__COMPILE_ATTR_NONNULL_A() \ __attribute__ ((__nonnull__)) # define USTR__COMPILE_ATTR_NONNULL_L(x) \ __attribute__ ((__nonnull__ x)) #else # define USTR__COMPILE_ATTR_NONNULL_A() /* nothing */ # define USTR__COMPILE_ATTR_NONNULL_L(x) /* nothing */ #endif #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ USTR_CONF_HAVE_ATTR_PURE && USTR_CONF_COMPILE_USE_ATTRIBUTES # define USTR__COMPILE_ATTR_PURE() \ __attribute__ ((__pure__)) #else # define USTR__COMPILE_ATTR_PURE() /* nothing */ #endif #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ USTR_CONF_HAVE_ATTR_CONST && USTR_CONF_COMPILE_USE_ATTRIBUTES # define USTR__COMPILE_ATTR_CONST() \ __attribute__ ((__const__)) #else # define USTR__COMPILE_ATTR_CONST() /* nothing */ #endif #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ USTR_CONF_HAVE_ATTR_MALLOC && USTR_CONF_COMPILE_USE_ATTRIBUTES # define USTR__COMPILE_ATTR_MALLOC() \ __attribute__ ((__malloc__)) #else # define USTR__COMPILE_ATTR_MALLOC() /* nothing */ #endif #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ USTR_CONF_HAVE_ATTR_WARN_UNUSED_RET && USTR_CONF_COMPILE_USE_ATTRIBUTES # define USTR__COMPILE_ATTR_WARN_UNUSED_RET() \ __attribute__ ((__warn_unused_result__)) #else # define USTR__COMPILE_ATTR_WARN_UNUSED_RET() /* nothing */ #endif #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ USTR_CONF_HAVE_ATTR_UNUSED && USTR_CONF_COMPILE_USE_ATTRIBUTES # define USTR__COMPILE_ATTR_UNUSED(x) ustr__UNUSED_ ## x __attribute__((unused)) #else # define USTR__COMPILE_ATTR_UNUSED(x) ustr__UNUSED_ ## x #endif #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ USTR_CONF_HAVE_ATTR_DEPRECATED && USTR_CONF_COMPILE_USE_ATTRIBUTES # define USTR__COMPILE_ATTR_DEPRECATED() __attribute__ ((__deprecated__)) #else # define USTR__COMPILE_ATTR_DEPRECATED() /* nothing */ #endif #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ USTR_CONF_HAVE_ATTR_SENTINEL && USTR_CONF_COMPILE_USE_ATTRIBUTES # define USTR__COMPILE_ATTR_SENTINEL(x) \ __attribute__ ((__sentinel__ (x))) #else # define USTR__COMPILE_ATTR_SENTINEL(x) /* nothing */ #endif ustr-1.0.4/ustr-cmp-opt-code.c0000644000076400007640000000127510674563614015150 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-cmp.h" ustr-1.0.4/ustr-replace-internal.h0000644000076400007640000000247410673031626016105 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_REPLACE_INTERNAL_H #define USTR_REPLACE_INTERNAL_H 1 #ifndef USTR_MAIN_H # error " You should have already included ustr-main.h, or just include ustr.h" #endif USTR_CONF_e_PROTO size_t ustrp__replace_inline_buf(struct Ustr_pool *, struct Ustr **, const void *, size_t, const void *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3, 5)); USTR_CONF_e_PROTO size_t ustrp__replace_buf(struct Ustr_pool *, struct Ustr **, const void *, size_t, const void *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3, 5)); USTR_CONF_e_PROTO size_t ustrp__replace(struct Ustr_pool *, struct Ustr **,const struct Ustr *, const struct Ustr *, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3, 4)); USTR_CONF_e_PROTO size_t ustrp__replace_inline_rep_chr(struct Ustr_pool *p, struct Ustr **ps1, char, size_t, char, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO size_t ustrp__replace_rep_chr(struct Ustr_pool *p, struct Ustr **ps1, char, size_t, char, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); #endif ustr-1.0.4/ustr-sub-opt-code.c0000644000076400007640000000140010722116205015130 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-fmt.h" #include "ustr-ins.h" #include "ustr-srch.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-sub.h" ustr-1.0.4/ustr-sub-code.h0000644000076400007640000004076110760716436014370 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_SUB_H #error " Include ustr-sub.h before this file." #endif USTR_CONF_i_PROTO int ustrp__sub_undef(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, size_t len) { size_t clen; USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); if (!len) return (USTR_TRUE); clen = ustrp__assert_valid_subustr(!!p, *ps1, pos, 1); if (!clen) return (USTR_FALSE); --pos; if ((clen - pos) < len) { /* need to expand s1, it's basically like ustr_set() with an offset */ if (!ustrp__add_undef(p, ps1, len - (clen - pos))) return (USTR_FALSE); } else if (!ustrp__sc_ensure_owner(p, ps1)) return (USTR_FALSE); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_sub_undef(struct Ustr **ps1, size_t pos, size_t len) { return (ustrp__sub_undef(0, ps1, pos, len)); } USTR_CONF_I_PROTO int ustrp_sub_undef(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sub_undef(p, &tmp, pos, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sub_buf(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, const void *buf, size_t len) { if (!ustrp__sub_undef(p, ps1, pos, len)) return (USTR_FALSE); --pos; ustr__memcpy(*ps1, pos, buf, len); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_sub_buf(struct Ustr **ps1, size_t pos, const void *buf, size_t len) { return (ustrp__sub_buf(0, ps1, pos, buf, len)); } USTR_CONF_I_PROTO int ustrp_sub_buf(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, const void *buf, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sub_buf(p, &tmp, pos, buf, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sub(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, const struct Ustr *s2) { if (*ps1 == s2) return (ustrp__ins_subustr(p, ps1, pos - 1, s2, 1, pos - 1)); return (ustrp__sub_buf(p, ps1, pos, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_I_PROTO int ustr_sub(struct Ustr **ps1, size_t pos, const struct Ustr *s2) { return (ustrp__sub(0, ps1, pos, s2)); } USTR_CONF_I_PROTO int ustrp_sub(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, const struct Ustrp *s2) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sub(p, &tmp, pos, &s2->s); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sub_subustr(struct Ustr_pool *p, struct Ustr **ps1, size_t pos1, const struct Ustr *s2, size_t pos2, size_t len2) { size_t clen2 = 0; if (!len2) return (USTR_TRUE); if (!(clen2 = ustrp__assert_valid_subustr(!!p, s2, pos2, len2))) return (USTR_FALSE); if (clen2 == len2) return (ustrp__sub(p, ps1, pos1, s2)); if ((*ps1 == s2) && ustr_owner(*ps1)) { struct Ustr *tmp = USTR_NULL; int ret = USTR_FALSE; if (pos1 == pos2) /* delete from end */ return (ustrp__del(p, ps1, ((ustr_len(*ps1) - pos1) + 1) - len2)); /* This is somewhat difficult to do "well". So punt. */ if (!(tmp = ustrp__dup_subustr(p, s2, pos2, len2))) return (USTR_FALSE); ret = ustrp__sub(p, ps1, pos1, tmp); ustrp__free(p, tmp); return (ret); } --pos2; return (ustrp__sub_buf(p, ps1, pos1, ustr_cstr(s2) + pos2, len2)); } USTR_CONF_I_PROTO int ustr_sub_subustr(struct Ustr **ps1, size_t pos1, const struct Ustr *s2, size_t pos2, size_t len2) { return (ustrp__sub_subustr(0, ps1, pos1, s2, pos2, len2)); } USTR_CONF_I_PROTO int ustrp_sub_subustrp(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos1, const struct Ustrp *s2, size_t pos2, size_t len2) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sub_subustr(p, &tmp, pos1, &s2->s, pos2, len2); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sub_rep_chr(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, char chr, size_t len) { if (!ustrp__sub_undef(p, ps1, pos, len)) return (USTR_FALSE); --pos; ustr__memset(*ps1, pos, chr, len); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_sub_rep_chr(struct Ustr **ps1, size_t pos, char chr, size_t len) { return (ustrp__sub_rep_chr(0, ps1, pos, chr, len)); } USTR_CONF_I_PROTO int ustrp_sub_rep_chr(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, char chr, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sub_rep_chr(p, &tmp, pos, chr, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sc_sub_undef(struct Ustr_pool *p,struct Ustr **ps1, size_t pos, size_t olen, size_t len) { USTR_ASSERT(ps1); if (!olen) return (ustrp__ins_undef(p, ps1, pos - 1, len)); if (!ustrp__assert_valid_subustr(!!p, *ps1, pos, olen)) return (USTR_FALSE); if (len == olen) return (ustrp__sc_ensure_owner(p, ps1)); /* work at end, so we don't have to memmove as much */ if (len < olen) return (ustrp__del_subustr(p, ps1, pos + len, olen - len)); return (ustrp__ins_undef( p, ps1, pos + olen - 1, len - olen)); } USTR_CONF_I_PROTO int ustr_sc_sub_undef(struct Ustr **ps1, size_t pos, size_t olen, size_t len) { return (ustrp__sc_sub_undef(0, ps1, pos, olen, len)); } USTR_CONF_I_PROTO int ustrp_sc_sub_undef(struct Ustr_pool *p,struct Ustrp **ps1, size_t pos, size_t olen, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_sub_undef(p, &tmp, pos, olen, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sc_sub_buf(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, size_t olen, const void *buf, size_t len) { if (!ustrp__sc_sub_undef(p, ps1, pos, olen, len)) return (USTR_FALSE); return (ustrp__sub_buf(p, ps1, pos, buf, len)); } USTR_CONF_I_PROTO int ustr_sc_sub_buf(struct Ustr **ps1, size_t pos, size_t olen, const void *buf, size_t len) { return (ustrp__sc_sub_buf(0, ps1, pos, olen, buf, len)); } USTR_CONF_I_PROTO int ustrp_sc_sub_buf(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, size_t olen, const void *buf, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_sub_buf(p, &tmp, pos, olen, buf, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sc_sub(struct Ustr_pool *p, struct Ustr **ps1,size_t pos,size_t olen, const struct Ustr *s2) { if (!olen) return (ustrp__ins(p, ps1, pos - 1, s2)); if ((*ps1 == s2) && ustr_owner(*ps1)) { size_t clen = ustrp__assert_valid_subustr(!!p, *ps1, pos, olen); size_t alen = (clen - olen); size_t epos = ( pos + olen); size_t elen = (clen - epos) + 1; char *ptr; if (!clen) return (USTR_FALSE); /* abcd/1.2 => abcdcd abcd/2.2 => aabcdd abcd/3.2 => ababcd */ if (!ustrp__add_undef(p, ps1, alen)) return (USTR_FALSE); ptr = ustr_wstr(*ps1); if (pos != 1) { size_t bpos = pos - 1; size_t blen = bpos; /* move current data, to make room */ memmove(ptr + bpos, ptr, clen); memcpy(ptr, ptr + bpos, blen); epos += blen; clen += blen; } ustr__memcpy(*ps1, clen, ptr + epos - 1, elen); USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } return (ustrp__sc_sub_buf(p, ps1, pos, olen, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_I_PROTO int ustr_sc_sub(struct Ustr **ps1,size_t pos,size_t olen, const struct Ustr *s2) { return (ustrp__sc_sub(0, ps1, pos, olen, s2)); } USTR_CONF_I_PROTO int ustrp_sc_sub(struct Ustr_pool *p, struct Ustrp **ps1,size_t pos,size_t olen, const struct Ustrp *s2) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_sub(p, &tmp, pos, olen, &s2->s); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sc_sub_subustr(struct Ustr_pool *p, struct Ustr **ps1, size_t pos1, size_t len1, const struct Ustr *s2, size_t pos2, size_t len2) { size_t clen2 = 0; if (!len2) return (ustrp__del_subustr(p, ps1, pos1, len1)); if (!(clen2 = ustrp__assert_valid_subustr(!!p, s2, pos2, len2))) return (USTR_FALSE); if (clen2 == len2) return (ustrp__sc_sub(p, ps1, pos1, len1, s2)); if ((*ps1 == s2) && ustr_owner(*ps1)) { struct Ustr *tmp = USTR_NULL; int ret = USTR_FALSE; /* This is somewhat difficult to do "well". So punt. */ if (!(tmp = ustrp__dup_subustr(p, s2, pos2, len2))) return (USTR_FALSE); ret = ustrp__sc_sub(p, ps1, pos1, len1, tmp); ustrp__free(p, tmp); return (ret); } --pos2; return (ustrp__sc_sub_buf(p, ps1, pos1, len1, ustr_cstr(s2) + pos2, len2)); } USTR_CONF_I_PROTO int ustr_sc_sub_subustr(struct Ustr **ps1, size_t pos1, size_t len1, const struct Ustr *s2, size_t pos2, size_t len2) { return (ustrp__sc_sub_subustr(0, ps1, pos1, len1, s2, pos2, len2)); } USTR_CONF_I_PROTO int ustrp_sc_sub_subustrp(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos1, size_t len1, const struct Ustrp *s2, size_t pos2, size_t len2) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_sub_subustr(p, &tmp, pos1, len1, &s2->s, pos2, len2); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sc_sub_rep_chr(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, size_t olen, char chr, size_t len) { if (!ustrp__sc_sub_undef(p, ps1, pos, olen, len)) return (USTR_FALSE); return (ustrp__sub_rep_chr(p, ps1, pos, chr, len)); } USTR_CONF_I_PROTO int ustr_sc_sub_rep_chr(struct Ustr **ps1, size_t pos, size_t olen, char chr, size_t len) { return (ustrp__sc_sub_rep_chr(0, ps1, pos, olen, chr, len)); } USTR_CONF_I_PROTO int ustrp_sc_sub_rep_chr(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, size_t olen, char chr, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_sub_rep_chr(p, &tmp, pos, olen, chr, len); *ps1 = USTRP(tmp); return (ret); } #ifdef USTR_FMT_H # if USTR_CONF_HAVE_VA_COPY USTR_CONF_i_PROTO int ustrp__sub_vfmt_lim(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, size_t lim, const char *fmt, va_list ap) { /* NOTE: Copy and pasted so we can use ustrp_set_undef() */ va_list nap; int rc = -1; char buf[USTR__SNPRINTF_LOCAL]; char *ptr; char save_end; USTR__VA_COPY(nap, ap); rc = USTR_CONF_VSNPRINTF_BEG(buf, sizeof(buf), fmt, nap); va_end(nap); if ((rc == -1) && ((rc = ustr__retard_vfmt_ret(fmt, ap)) == -1)) return (USTR_FALSE); if (lim && ((size_t)rc > lim)) rc = lim; if ((size_t)rc < sizeof(buf)) /* everything is done */ return (ustrp__sub_buf(p, ps1, pos, buf, rc)); if (!ustrp__sub_undef(p, ps1, pos--, rc)) return (USTR_FALSE); ptr = ustr_wstr(*ps1); save_end = ptr[pos + rc]; /* might be NIL, might be a char */ USTR_CONF_VSNPRINTF_END(ptr + pos, rc + 1, fmt, ap); ptr[pos + rc] = save_end; USTR_ASSERT(ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_sub_vfmt_lim(struct Ustr **ps1,size_t pos,size_t lim, const char *fmt, va_list ap) { return (ustrp__sub_vfmt_lim(0, ps1, pos, lim, fmt, ap)); } USTR_CONF_I_PROTO int ustrp_sub_vfmt_lim(struct Ustr_pool *p,struct Ustrp **ps1, size_t pos, size_t lim, const char *fmt, va_list ap) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sub_vfmt_lim(p, &tmp, pos, lim, fmt, ap); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_I_PROTO int ustr_sub_fmt_lim(struct Ustr **ps1, size_t pos, size_t lim, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustr_sub_vfmt_lim(ps1, pos, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustrp_sub_fmt_lim(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, size_t lim, const char*fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustrp_sub_vfmt_lim(p, ps1, pos, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustr_sub_vfmt(struct Ustr **ps1, size_t pos, const char *fmt, va_list ap) { return (ustr_sub_vfmt_lim(ps1, pos, 0, fmt, ap)); } USTR_CONF_I_PROTO int ustrp_sub_vfmt(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, const char *fmt, va_list ap) { return (ustrp_sub_vfmt_lim(p, ps1, pos, 0, fmt, ap)); } USTR_CONF_I_PROTO int ustr_sub_fmt(struct Ustr **ps1, size_t pos, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustr_sub_vfmt(ps1, pos, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustrp_sub_fmt(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustrp_sub_vfmt(p, ps1, pos, fmt, ap); va_end(ap); return (ret); } USTR_CONF_i_PROTO int ustrp__sc_sub_vfmt_lim(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, size_t len, size_t lim, const char *fmt, va_list ap) { /* NOTE: Copy and pasted so we can use ustrp_set_undef() */ va_list nap; int rc = -1; char buf[USTR__SNPRINTF_LOCAL]; char *ptr; char save_end; USTR__VA_COPY(nap, ap); rc = USTR_CONF_VSNPRINTF_BEG(buf, sizeof(buf), fmt, nap); va_end(nap); if ((rc == -1) && ((rc = ustr__retard_vfmt_ret(fmt, ap)) == -1)) return (USTR_FALSE); if (lim && ((size_t)rc > lim)) rc = lim; if ((size_t)rc < sizeof(buf)) /* everything is done */ return (ustrp__sc_sub_buf(p, ps1, pos, len, buf, rc)); if (!ustrp__sc_sub_undef(p, ps1, pos--, len, rc)) return (USTR_FALSE); ptr = ustr_wstr(*ps1); save_end = ptr[pos + rc]; /* might be NIL if at end, might be a char */ USTR_CONF_VSNPRINTF_END(ptr + pos, rc + 1, fmt, ap); ptr[pos + rc] = save_end; USTR_ASSERT(ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_sc_sub_vfmt_lim(struct Ustr **ps1,size_t pos, size_t len, size_t lim, const char *fmt, va_list ap) { return (ustrp__sc_sub_vfmt_lim(0, ps1, pos, len, lim, fmt, ap)); } USTR_CONF_I_PROTO int ustrp_sc_sub_vfmt_lim(struct Ustr_pool *p,struct Ustrp **ps1, size_t pos, size_t len, size_t lim, const char *fmt, va_list ap) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_sub_vfmt_lim(p, &tmp, pos, len, lim, fmt, ap); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_I_PROTO int ustr_sc_sub_fmt_lim(struct Ustr **ps1, size_t pos, size_t len, size_t lim, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustr_sc_sub_vfmt_lim(ps1, pos, len, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustrp_sc_sub_fmt_lim(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, size_t len, size_t lim, const char*fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustrp_sc_sub_vfmt_lim(p, ps1, pos, len, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustr_sc_sub_vfmt(struct Ustr **ps1, size_t pos, size_t len, const char *fmt, va_list ap) { return (ustr_sc_sub_vfmt_lim(ps1, pos, len, 0, fmt, ap)); } USTR_CONF_I_PROTO int ustrp_sc_sub_vfmt(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, size_t len, const char *fmt, va_list ap) { return (ustrp_sc_sub_vfmt_lim(p, ps1, pos, len, 0, fmt, ap)); } USTR_CONF_I_PROTO int ustr_sc_sub_fmt(struct Ustr **ps1, size_t pos, size_t len, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustr_sc_sub_vfmt(ps1, pos, len, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustrp_sc_sub_fmt(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, size_t len, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustrp_sc_sub_vfmt(p, ps1, pos, len, fmt, ap); va_end(ap); return (ret); } # endif #endif ustr-1.0.4/ustr-cntl.h0000644000076400007640000000635210722060227013611 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_CNTL_H #define USTR_CNTL_H 1 #ifndef USTR_MAIN_H # error " You should include ustr-main.h before this file, or just ustr.h" #endif #define USTR_CNTL_OPT_GET_REF_BYTES ( 1) #define USTR_CNTL_OPT_SET_REF_BYTES ( 2) #define USTR_CNTL_OPT_GET_HAS_SIZE ( 3) #define USTR_CNTL_OPT_SET_HAS_SIZE ( 4) #define USTR_CNTL_OPT_GET_EXACT_BYTES ( 5) #define USTR_CNTL_OPT_SET_EXACT_BYTES ( 6) #define USTR_CNTL_OPT_GET_MEM ( 7) #define USTR_CNTL_OPT_SET_MEM ( 8) #define USTR_CNTL_OPT_GET_MC_M_SCRUB ( 9) #define USTR_CNTL_OPT_SET_MC_M_SCRUB (10) #define USTR_CNTL_OPT_GET_MC_F_SCRUB (11) #define USTR_CNTL_OPT_SET_MC_F_SCRUB (12) #define USTR_CNTL_OPT_GET_MC_R_SCRUB (13) #define USTR_CNTL_OPT_SET_MC_R_SCRUB (14) #define USTR_CNTL_OPT_GET_FMT (15) #define USTR_CNTL_OPT_SET_FMT (16) /* move to dynamic configuration, so it's more usable from a shared library */ #undef USTR_CONF_REF_BYTES #define USTR_CONF_REF_BYTES (ustr__opts->ref_bytes) #undef USTR_CONF_HAS_SIZE #define USTR_CONF_HAS_SIZE (ustr__opts->has_size) #undef USTR_CONF_EXACT_BYTES #define USTR_CONF_EXACT_BYTES (ustr__opts->exact_bytes) #undef USTR_CONF_MALLOC #define USTR_CONF_MALLOC(x) ((*ustr__opts->umem.sys_malloc)(x)) #undef USTR_CONF_REALLOC #define USTR_CONF_REALLOC(x, y) ((*ustr__opts->umem.sys_realloc)((x), (y))) #undef USTR_CONF_FREE #define USTR_CONF_FREE(x) ((*ustr__opts->umem.sys_free)(x)) #undef USTR_CONF_VSNPRINTF_BEG #define USTR_CONF_VSNPRINTF_BEG ustr__opts->ufmt.sys_vsnprintf_beg #undef USTR_CONF_VSNPRINTF_END #define USTR_CONF_VSNPRINTF_END ustr__opts->ufmt.sys_vsnprintf_end struct Ustr_cntl_mem { void *(*sys_malloc)(size_t); void *(*sys_realloc)(void *, size_t); void (*sys_free)(void *); }; struct Ustr_cntl_fmt { int (*sys_vsnprintf_beg)(char *, size_t, const char *, va_list); int (*sys_vsnprintf_end)(char *, size_t, const char *, va_list); }; #if USTR_CONF_INCLUDE_INTERNAL_HEADERS struct Ustr_opts { size_t ref_bytes; struct Ustr_cntl_mem umem; struct Ustr_cntl_fmt ufmt; unsigned int has_size : 1; unsigned int exact_bytes : 1; unsigned int mc_m_scrub : 1; unsigned int mc_f_scrub : 1; unsigned int mc_r_scrub : 1; }; /* this is for use within the shared library only... */ extern struct Ustr_opts ustr__opts[1]; USTR_CONF_e_PROTO int ustr__cntl_mc_setup_env2bool(const char *, int) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_e_PROTO void ustr__cntl_mc_setup_main(void); USTR_CONF_e_PROTO void *ustr__cntl_mc_setup_malloc(size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_e_PROTO void *ustr__cntl_mc_malloc(size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_e_PROTO void *ustr__cntl_mc_realloc(void *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_e_PROTO void ustr__cntl_mc_free(void *); #else struct Ustr_opts; /* declare opaque struct */ #endif #if USTR_CONF_COMPILE_TYPEDEF typedef struct Ustr_cntl_mem Ustr_cntl_mem; typedef struct Ustr_cntl_fmt Ustr_cntl_fmt; typedef struct Ustr_opts Ustr_opts; #endif USTR_CONF_E_PROTO int ustr_cntl_opt(int, ...) USTR__COMPILE_ATTR_NONNULL_A(); #if USTR_CONF_INCLUDE_CODEONLY_HEADERS #include "ustr-cntl-code.h" #endif #endif ustr-1.0.4/ustr-sc-opt-code.c0000644000076400007640000000135110722117305014753 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-spn.h" #include "ustr-utf8.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-sc.h" ustr-1.0.4/ustr-io.h0000644000076400007640000001003410721115505013247 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_IO_H #define USTR_IO_H 1 #ifndef USTR_MAIN_H #error " You should have already included ustr-main.h, or just include ustr.h." #endif USTR_CONF_E_PROTO int ustr_io_get(struct Ustr **, FILE *, size_t, size_t *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 2)); USTR_CONF_E_PROTO int ustr_io_getfile(struct Ustr **, FILE *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_io_getfilename(struct Ustr **, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_io_getdelim(struct Ustr **, FILE *, char) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_io_getline(struct Ustr **, FILE *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_io_put(struct Ustr **, FILE *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_io_putline(struct Ustr **, FILE *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_io_putfile(struct Ustr **, FILE *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_io_putfileline(struct Ustr **, FILE *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_io_putfilename(struct Ustr **, const char *, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_io_get(struct Ustr_pool *, struct Ustrp **, FILE *, size_t, size_t *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_io_getfile(struct Ustr_pool *, struct Ustrp **, FILE *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_io_getfilename(struct Ustr_pool *, struct Ustrp **,const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_io_getdelim(struct Ustr_pool *, struct Ustrp **, FILE *, char) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_io_getline(struct Ustr_pool *, struct Ustrp**,FILE*) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_io_put(struct Ustr_pool *, struct Ustrp **, FILE *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_io_putline(struct Ustr_pool *, struct Ustrp **, FILE *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_EI_PROTO int ustrp_io_putfile(struct Ustr_pool *, struct Ustrp **, FILE *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_EI_PROTO int ustrp_io_putfileline(struct Ustr_pool *, struct Ustrp **, FILE *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_io_putfilename(struct Ustr_pool *, struct Ustrp **, const char *, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3, 4)); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-io-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-io-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO int ustr_io_putfile(struct Ustr **ps1, FILE *fp) { return (ustr_io_put(ps1, fp, ustr_len(*ps1))); } USTR_CONF_II_PROTO int ustr_io_putfileline(struct Ustr **ps1, FILE *fp) { return (ustr_io_putline(ps1, fp, ustr_len(*ps1))); } USTR_CONF_II_PROTO int ustrp_io_putfile(struct Ustr_pool *p, struct Ustrp **ps1, FILE *fp) { return (ustrp_io_put(p, ps1, fp, ustrp_len(*ps1))); } USTR_CONF_II_PROTO int ustrp_io_putfileline(struct Ustr_pool *p, struct Ustrp **ps1, FILE *fp) { return (ustrp_io_putline(p, ps1, fp, ustrp_len(*ps1))); } #endif #endif ustr-1.0.4/ustr-b-code.h0000644000076400007640000000011510630610426013771 0ustar jamesjames# error " This is just here to make Makefiles happy, it should not be used." ustr-1.0.4/ustr-fmt-opt-code.c0000644000076400007640000000127510674563614015157 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-fmt.h" ustr-1.0.4/ustr-b-dbg-code.c0000644000076400007640000000130110674563614014532 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-b.h" ustr-1.0.4/ustr-pool-opt-code.c0000644000076400007640000000127610674563614015343 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-pool.h" ustr-1.0.4/ustr-conf-debug-multilib-linux.h0000644000076400007640000000033110723716346017640 0ustar jamesjames/* This might be Linux/GLibc specific */ #include #if __WORDSIZE == 32 #include #elif __WORDSIZE == 64 #include #else #error "Unknown word size" #endif ustr-1.0.4/ustr-debug.h0000644000076400007640000000102410722116026013725 0ustar jamesjames#ifndef USTR_H #define USTR_H 1 #ifndef USTR_DEBUG #define USTR_DEBUG 1 #endif #if USTR_DEBUG # include "ustr-conf-debug.h" #else # include "ustr-conf.h" #endif #include "ustr-main.h" #include "ustr-b.h" #include "ustr-cmp.h" #include "ustr-fmt.h" #include "ustr-io.h" #include "ustr-ins.h" #include "ustr-parse.h" #include "ustr-pool.h" #include "ustr-set.h" #include "ustr-srch.h" #include "ustr-utf8.h" #include "ustr-spn.h" #include "ustr-sub.h" #include "ustr-replace.h" #include "ustr-split.h" #include "ustr-sc.h" #endif ustr-1.0.4/ustr-spn-opt-code.c0000644000076400007640000000135310674563614015166 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-srch.h" #include "ustr-utf8.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-spn.h" ustr-1.0.4/ustr-import-multilib.in0000644000076400007640000000263110763662551016172 0ustar jamesjames#! /bin/sh -e INCDIR=@INCLUDEDIR@ MBINDIR=@MBINDIR@ NOT_DONE=1 inst32() { foo=no if [ "x$1" = "xeither" ]; then foo=either shift fi if [ -f "$MBINDIR/ustr-import-32" ]; then "$MBINDIR/ustr-import-32" "$@" RETVAL=$? fi if [ "x$foo" = "xeither" ]; then # This assume an installed multilib ustr-conf.h if [ $RETVAL -eq 0 ] && [ -f ustr-conf.h ]; then mv ustr-conf.h ustr-conf-32.h cp "$INCDIR/ustr-conf.h" . fi if [ $RETVAL -eq 0 ] && [ -f ustr-conf-debug.h ]; then mv ustr-conf-debug.h ustr-conf-debug-32.h cp "$INCDIR/ustr-conf-debug.h" . fi NOT_DONE=0 else exit $RETVAL fi } inst64() { foo=no if [ "x$1" = "xeither" ]; then foo=either shift fi if [ -f "$MBINDIR/ustr-import-64" ]; then "$MBINDIR/ustr-import-64" "$@" RETVAL=$? fi if [ "x$foo" = "xeither" ]; then # This assume an installed multilib ustr-conf.h if [ $RETVAL -eq 0 ] && [ -f ustr-conf.h ]; then mv ustr-conf.h ustr-conf-64.h cp "$INCDIR/ustr-conf.h" . fi if [ $RETVAL -eq 0 ] && [ -f ustr-conf-debug.h ]; then mv ustr-conf-debug.h ustr-conf-debug-64.h cp "$INCDIR/ustr-conf-debug.h" . fi NOT_DONE=0 else exit $RETVAL fi } if [ "x$1" = "x--32" ]; then shift inst32 $@ fi if [ "x$1" = "x--64" ]; then shift inst64 $@ fi inst64 either $@ inst32 either $@ exit $NOT_DONE ustr-1.0.4/ustr-conf-debug-64.h0000644000076400007640000000367710760731462015130 0ustar jamesjames#ifndef USTR_CONF_H #define USTR_CONF_H 1 /* this is the custom version for the library itself, for everyone else * ustr-import generates one depending on the options. */ /* The default is now to link against libc. */ #ifndef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #endif /* We can't: if defined(__GLIBC__) && (!defined(_GNU_SOURCE) || !_GNU_SOURCE) * because by the time we've included a libc header it's too late. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif /* maybe move memmem / memrchr here? */ #if ! USTR_CONF_INCLUDE_CODEONLY_HEADERS /* If you aren't just using the headers, these should match the .c's */ # define USTR_CONF_HAVE_64bit_SIZE_MAX 1 # define USTR_CONF_HAVE_RETARDED_VSNPRINTF 0 # define USTR_CONF_HAVE_STDINT_H 1 # define USTR_CONF_HAVE_DYNAMIC_CONF 1 # define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF # define USTR_CONF_REF_BYTES 1 # define USTR_CONF_EXACT_BYTES 0 # define USTR_CONF_USE_SIZE 0 # define USTR_CONF_USE_ASSERT 1 # define USTR_CONF_USE_EOS_MARK 1 #else /* Same defaults, but can be altered at will. */ /* Note that you really shouldn't alter the _HAVE_* ones, but whatever */ # ifndef USTR_CONF_HAVE_64bit_SIZE_MAX # define USTR_CONF_HAVE_64bit_SIZE_MAX 1 # endif # ifndef USTR_CONF_HAVE_RETARDED_VSNPRINTF # define USTR_CONF_HAVE_RETARDED_VSNPRINTF 0 # endif # ifndef USTR_CONF_HAVE_STDINT_H # define USTR_CONF_HAVE_STDINT_H 1 # endif # ifndef USTR_CONF_HAVE_DYNAMIC_CONF # define USTR_CONF_HAVE_DYNAMIC_CONF 1 # endif /* no USE_DYNAMIC_CONF ... use default in ustr-main.h */ # ifndef USTR_CONF_REF_BYTES # define USTR_CONF_REF_BYTES 1 # endif # ifndef USTR_CONF_EXACT_BYTES # define USTR_CONF_EXACT_BYTES 0 # endif # ifndef USTR_CONF_USE_SIZE # define USTR_CONF_USE_SIZE 0 # endif # ifndef USTR_CONF_USE_ASSERT # define USTR_CONF_USE_ASSERT 1 # endif # ifndef USTR_CONF_USE_EOS_MARK # define USTR_CONF_USE_EOS_MARK 1 # endif #endif #endif ustr-1.0.4/ustr-pool-code.h0000644000076400007640000002030010711000362014507 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_POOL_H #error " You should have already included ustr-pool.h, or just include ustr.h." #endif struct Ustr__pool_ll_node { struct Ustr__pool_ll_node *next; void *ptr; }; struct Ustr__pool_ll_base { /* "simple" pool implementation */ struct Ustr_pool cbs; struct Ustr__pool_ll_node *beg; struct Ustr__pool_ll_base *sbeg; /* wasting a lot of space for sub pools */ struct Ustr__pool_ll_base *base; struct Ustr__pool_ll_base *next; struct Ustr__pool_ll_base *prev; unsigned int free_num : 30; /* how many nodes we search to free */ unsigned int call_realloc : 1; }; #define USTR__POOL_LL_SIB_NULL ((struct Ustr__pool_ll_base *) 0) USTR_CONF_e_PROTO void *ustr__pool_ll_sys_malloc(struct Ustr_pool *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A() USTR__COMPILE_ATTR_MALLOC(); USTR_CONF_e_PROTO void *ustr__pool_ll_sys_realloc(struct Ustr_pool *, void *, size_t, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)) USTR__COMPILE_ATTR_MALLOC(); USTR_CONF_e_PROTO void ustr__pool_ll_sys_free(struct Ustr_pool *, void *) USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_e_PROTO struct Ustr_pool *ustr__pool_ll_make_subpool(struct Ustr_pool *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_MALLOC(); USTR_CONF_e_PROTO void ustr__pool_ll__clear(struct Ustr__pool_ll_base *, int); USTR_CONF_e_PROTO void ustr__pool_ll_clear(struct Ustr_pool *) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO void ustr__pool_ll__free(struct Ustr__pool_ll_base *, int); USTR_CONF_e_PROTO void ustr__pool_ll_free(struct Ustr_pool *); USTR_CONF_i_PROTO void *ustr__pool_ll_sys_malloc(struct Ustr_pool *p,size_t len) { struct Ustr__pool_ll_base *sip = (struct Ustr__pool_ll_base *)p; struct Ustr__pool_ll_node *np; void *ret = USTR_CONF_MALLOC(len); ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(p, sizeof(struct Ustr__pool_ll_base))); if (!ret) return (ret); if (!(np = USTR_CONF_MALLOC(sizeof(struct Ustr__pool_ll_node)))) { USTR_CONF_FREE(ret); return (0); } np->next = sip->beg; sip->beg = np; np->ptr = ret; return (ret); } USTR_CONF_i_PROTO void *ustr__pool_ll_sys_realloc(struct Ustr_pool *p, void *old, size_t olen, size_t nlen) { struct Ustr__pool_ll_base *sip = (struct Ustr__pool_ll_base *)p; void *ret = 0; ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(p, sizeof(struct Ustr__pool_ll_base))); USTR_ASSERT((old && sip->beg && sip->beg->ptr) || !olen); ustr_assert(olen ? USTR_CNTL_MALLOC_CHECK_MEM_MINSZ(old, olen) : (!old || USTR_CNTL_MALLOC_CHECK_MEM(old))); if (!nlen) ++nlen; if (olen && (sip->beg->ptr == old) && sip->call_realloc) { /* let the last allocated Ustrp grow/shrink */ if ((ret = USTR_CONF_REALLOC(old, nlen))) sip->beg->ptr = ret; } else if (olen >= nlen) /* always allow reductions/nothing */ { USTR__CNTL_MALLOC_CHECK_FIXUP_REALLOC(old, nlen); return (old); } else if ((ret = ustr__pool_ll_sys_malloc(p, nlen))) memcpy(ret, old, olen); return (ret); } USTR_CONF_i_PROTO void ustr__pool_ll_sys_free(struct Ustr_pool *p, void *old) { struct Ustr__pool_ll_base *sip = (struct Ustr__pool_ll_base *)p; struct Ustr__pool_ll_node **op = &sip->beg; unsigned int num = sip->free_num; ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(p, sizeof(struct Ustr__pool_ll_base))); ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM(old)); while (*op && num--) { if ((*op)->ptr == old) { struct Ustr__pool_ll_node *rm = *op; *op = rm->next; USTR_CONF_FREE(rm->ptr); USTR_CONF_FREE(rm); return; } op = &(*op)->next; } } USTR_CONF_i_PROTO void ustr__pool_ll__clear(struct Ustr__pool_ll_base *base, int siblings) { struct Ustr__pool_ll_node *scan; if (!base) return; scan = base->beg; while (scan) { struct Ustr__pool_ll_node *scan_next = scan->next; USTR_CONF_FREE(scan->ptr); USTR_CONF_FREE(scan); scan = scan_next; } base->beg = 0; if (siblings) ustr__pool_ll__clear(base->next, USTR_TRUE); ustr__pool_ll__clear(base->sbeg, USTR_TRUE); } USTR_CONF_i_PROTO void ustr__pool_ll_clear(struct Ustr_pool *base) { ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(base, sizeof(struct Ustr__pool_ll_base))); ustr__pool_ll__clear((struct Ustr__pool_ll_base *)base, USTR_FALSE); } USTR_CONF_i_PROTO void ustr__pool_ll__free(struct Ustr__pool_ll_base *base, int siblings) { if (!base) return; if (siblings) ustr__pool_ll__free(base->next, USTR_TRUE); ustr__pool_ll__free(base->sbeg, USTR_TRUE); base->sbeg = 0; ustr__pool_ll__clear(base, USTR_FALSE); USTR_CONF_FREE(base); } USTR_CONF_i_PROTO void ustr__pool_ll_free(struct Ustr_pool *p) { struct Ustr__pool_ll_base *sip = (struct Ustr__pool_ll_base *)p; ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(p, sizeof(struct Ustr__pool_ll_base))); if (sip->prev) sip->prev->next = sip->next; else if (sip->base) sip->base->sbeg = sip->next; if (sip->next) sip->next->prev = sip->prev; ustr__pool_ll__free(sip, USTR_FALSE); } USTR_CONF_i_PROTO struct Ustr_pool *ustr__pool_ll_make_subpool(struct Ustr_pool *p) { struct Ustr__pool_ll_base *sip = (struct Ustr__pool_ll_base *)p; struct Ustr__pool_ll_base *tmp; if (!(tmp = USTR_CONF_MALLOC(sizeof(struct Ustr__pool_ll_base)))) return (USTR_POOL_NULL); tmp->cbs.pool_sys_malloc = ustr__pool_ll_sys_malloc; tmp->cbs.pool_sys_realloc = ustr__pool_ll_sys_realloc; tmp->cbs.pool_sys_free = ustr__pool_ll_sys_free; tmp->cbs.pool_make_subpool = ustr__pool_ll_make_subpool; tmp->cbs.pool_clear = ustr__pool_ll_clear; tmp->cbs.pool_free = ustr__pool_ll_free; tmp->beg = 0; tmp->sbeg = USTR__POOL_LL_SIB_NULL; tmp->prev = USTR__POOL_LL_SIB_NULL; tmp->next = USTR__POOL_LL_SIB_NULL; tmp->base = USTR__POOL_LL_SIB_NULL; tmp->free_num = 2; /* magic number, allows dupx + copy + free */ tmp->call_realloc = USTR_TRUE; if (!p) return (&tmp->cbs); ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(p, sizeof(struct Ustr__pool_ll_base))); if ((tmp->next = sip->sbeg)) tmp->next->prev = tmp; sip->sbeg = tmp; tmp->base = sip; return (&tmp->cbs); } /* linked list pool API */ USTR_CONF_I_PROTO struct Ustr_pool *ustr_pool_ll_make(void) { return (ustr__pool_ll_make_subpool(USTR_POOL_NULL)); } #include /* va_list for va_arg() functionality */ USTR_CONF_I_PROTO int ustr_pool_ll_cntl(struct Ustr_pool *p, int option, ...) { struct Ustr__pool_ll_base *sip = (struct Ustr__pool_ll_base *)p; int ret = USTR_FALSE; va_list ap; va_start(ap, option); switch (option) { case USTR_POOL_LL_CNTL_GET_FREE_CMP: { unsigned int *num = va_arg(ap, unsigned int *); *num = sip->free_num; ret = USTR_TRUE; } break; case USTR_POOL_LL_CNTL_SET_FREE_CMP: { unsigned int num = va_arg(ap, unsigned int); USTR_ASSERT_RET((num <= 65535), USTR_FALSE); /* 2 ** 16 */ sip->free_num = num; ret = USTR_TRUE; } break; case USTR_POOL_LL_CNTL_GET_REALLOC: { int *toggle = va_arg(ap, int *); *toggle = sip->call_realloc; ret = USTR_TRUE; } break; case USTR_POOL_LL_CNTL_SET_REALLOC: { int toggle = va_arg(ap, int); USTR_ASSERT_RET((toggle == !!toggle), USTR_FALSE); sip->call_realloc = toggle; ret = USTR_TRUE; } break; } USTR_ASSERT(ret); va_end(ap); return (ret); } /* "block" pool API */ /* USTR_CONF_I_PROTO struct Ustr_pool *ustr_pool_blk_make(void) { return (ustr__pool_blk_make_subpool(USTR_POOL_NULL)); } */ /* choose one of the above -- linked list */ USTR_CONF_I_PROTO struct Ustr_pool *ustr_pool_make_pool(void) { return (ustr__pool_ll_make_subpool(USTR_POOL_NULL)); } ustr-1.0.4/T-installed/0000755000076400007640000000000010763663475013702 5ustar jamesjamesustr-1.0.4/T-installed/tst_io.c0000644000076400007640000000020610707032437015327 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR(""); if (!ustr_io_getfilename(&s1, __FILE__)) return 1; return 0; } ustr-1.0.4/T-installed/tst_cmp.c0000644000076400007640000000016710707031424015500 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR(""); if (!ustr_cmp_eq(s1, s1)) return 1; return 0; } ustr-1.0.4/T-installed/Makefile0000644000076400007640000002106710707554642015341 0ustar jamesjames HIDE=@ # These are tests which are run agains the currently installed ustr # due to ustr-import and libustr usage. TST_ALL = \ tst_b_c_norm tst_b_c_dbg1 tst_b_c_dbg2 \ tst_b_i_norm tst_b_i_dbg1 tst_b_i_dbg2 \ tst_b_l_norm tst_b_l_dbg1 tst_b_l_dbg2 \ \ tst_cmp_c_norm tst_cmp_c_dbg1 tst_cmp_c_dbg2 \ tst_cmp_i_norm tst_cmp_i_dbg1 tst_cmp_i_dbg2 \ tst_cmp_l_norm tst_cmp_l_dbg1 tst_cmp_l_dbg2 \ \ tst_cntl_c_norm tst_cntl_c_dbg1 tst_cntl_c_dbg2 \ tst_cntl_l_norm tst_cntl_l_dbg1 tst_cntl_l_dbg2 \ \ tst_fmt_c_norm tst_fmt_c_dbg1 tst_fmt_c_dbg2 \ tst_fmt_i_norm tst_fmt_i_dbg1 tst_fmt_i_dbg2 \ tst_fmt_l_norm tst_fmt_l_dbg1 tst_fmt_l_dbg2 \ \ tst_ins_c_norm tst_ins_c_dbg1 tst_ins_c_dbg2 \ tst_ins_i_norm tst_ins_i_dbg1 tst_ins_i_dbg2 \ tst_ins_l_norm tst_ins_l_dbg1 tst_ins_l_dbg2 \ \ tst_io_c_norm tst_io_c_dbg1 tst_io_c_dbg2 \ tst_io_i_norm tst_io_i_dbg1 tst_io_i_dbg2 \ tst_io_l_norm tst_io_l_dbg1 tst_io_l_dbg2 \ \ tst_parse_c_norm tst_parse_c_dbg1 tst_parse_c_dbg2 \ tst_parse_i_norm tst_parse_i_dbg1 tst_parse_i_dbg2 \ tst_parse_l_norm tst_parse_l_dbg1 tst_parse_l_dbg2 \ \ tst_pool_c_norm tst_pool_c_dbg1 tst_pool_c_dbg2 \ tst_pool_i_norm tst_pool_i_dbg1 tst_pool_i_dbg2 \ tst_pool_l_norm tst_pool_l_dbg1 tst_pool_l_dbg2 \ \ tst_replace_c_norm tst_replace_c_dbg1 tst_replace_c_dbg2 \ tst_replace_i_norm tst_replace_i_dbg1 tst_replace_i_dbg2 \ tst_replace_l_norm tst_replace_l_dbg1 tst_replace_l_dbg2 \ \ tst_sc_c_norm tst_sc_c_dbg1 tst_sc_c_dbg2 \ tst_sc_i_norm tst_sc_i_dbg1 tst_sc_i_dbg2 \ tst_sc_l_norm tst_sc_l_dbg1 tst_sc_l_dbg2 \ \ tst_set_c_norm tst_set_c_dbg1 tst_set_c_dbg2 \ tst_set_i_norm tst_set_i_dbg1 tst_set_i_dbg2 \ tst_set_l_norm tst_set_l_dbg1 tst_set_l_dbg2 \ \ tst_split_c_norm tst_split_c_dbg1 tst_split_c_dbg2 \ tst_split_i_norm tst_split_i_dbg1 tst_split_i_dbg2 \ tst_split_l_norm tst_split_l_dbg1 tst_split_l_dbg2 \ \ tst_spn_c_norm tst_spn_c_dbg1 tst_spn_c_dbg2 \ tst_spn_i_norm tst_spn_i_dbg1 tst_spn_i_dbg2 \ tst_spn_l_norm tst_spn_l_dbg1 tst_spn_l_dbg2 \ \ tst_srch_c_norm tst_srch_c_dbg1 tst_srch_c_dbg2 \ tst_srch_i_norm tst_srch_i_dbg1 tst_srch_i_dbg2 \ tst_srch_l_norm tst_srch_l_dbg1 tst_srch_l_dbg2 \ \ tst_sub_c_norm tst_sub_c_dbg1 tst_sub_c_dbg2 \ tst_sub_i_norm tst_sub_i_dbg1 tst_sub_i_dbg2 \ tst_sub_l_norm tst_sub_l_dbg1 tst_sub_l_dbg2 \ \ tst_utf8_c_norm tst_utf8_c_dbg1 tst_utf8_c_dbg2 \ tst_utf8_i_norm tst_utf8_i_dbg1 tst_utf8_i_dbg2 \ tst_utf8_l_norm tst_utf8_l_dbg1 tst_utf8_l_dbg2 AR = ar RANLIB = ranlib CFLAGS=-Wall -W -O1 -g all: $(TST_ALL) $(HIDE)echo Done all. tst_%_c_norm: dir-c_norm-%/libustr.a tst_%.c $(HIDE)echo CC: $@ $(HIDE)$(CC) $(CFLAGS) -o $@ tst_$*.c -Idir-c_norm-$* $< $(HIDE)rm -rf dir-c_norm-$* tst_%_c_dbg1: dir-c_dbg1-%/libustr.a tst_%.c $(HIDE)echo CC: $@ $(HIDE)$(CC) $(CFLAGS) -o $@ tst_$*.c -Idir-c_dbg1-$* $< $(HIDE)rm -rf dir-c_dbg1-$* tst_%_c_dbg2: dir-c_dbg2-%/libustr.a tst_%.c $(HIDE)echo CC: $@ $(HIDE)$(CC) $(CFLAGS) -o $@ tst_$*.c -Idir-c_dbg2-$* $< $(HIDE)rm -rf dir-c_dbg2-$* tst_%_i_norm: dir-i_norm-% tst_%.c $(HIDE)echo CC: $@ $(HIDE)$(CC) $(CFLAGS) -o $@ tst_$*.c -I$< $(HIDE)rm -rf $< tst_%_i_dbg1: dir-i_dbg1-% tst_%.c $(HIDE)echo CC: $@ $(HIDE)$(CC) $(CFLAGS) -o $@ tst_$*.c -I$< $(HIDE)rm -rf $< tst_%_i_dbg2: dir-i_dbg2-% tst_%.c $(HIDE)echo CC: $@ $(HIDE)$(CC) $(CFLAGS) -o $@ tst_$*.c -I$< $(HIDE)rm -rf $< tst_%_l_norm: tst_%.c $(HIDE)echo CC: $@ $(HIDE)$(CC) $(CFLAGS) -o $@ tst_$*.c -lustr tst_%_l_dbg1: tst_%.c $(HIDE)echo CC: $@ $(HIDE)$(CC) $(CFLAGS) -DUSTR_DEBUG=1 -o $@ tst_$*.c -lustr-debug tst_%_l_dbg2: tst_%.c $(HIDE)echo CC: $@ $(HIDE)$(CC) $(CFLAGS) -DUSTR_DEBUG=1 -o $@ tst_$*.c -lustr-debug clean: rm -f $(TST_ALL) rm -rf dir-* # -------------------- dir-c_norm-%/libustr.a: dir-c_norm-% $(HIDE)$(CC) $(CFLAGS) -o $ int main(void) { Ustr *s1 = USTR1_CHK(\2, "ab"); Ustr *s2 = USTR1_CHK(\0, ""); Ustr *s3 = USTR(""); if (!ustr_len(s1)) return 1; if ( ustr_len(s2)) return 2; if ( ustr_cstr(s1) == (char *)s1) return 3; if ( ustr_cstr(s2) == (char *)s2) return 4; if ( ustr_cstr(s3) != (char *)s3) return 5; if (!*(char *)s1) return 6; if (!*(char *)s2) return 7; if ( *(char *)s3) return 8; return 0; } ustr-1.0.4/T-installed/tst_set.c0000644000076400007640000000016510707044634015521 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR(""); if (!ustr_set(&s1, s1)) return 1; return 0; } ustr-1.0.4/T-installed/tst_parse.c0000644000076400007640000000022310707044231016024 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR1(\1, "4"); if (ustr_parse_uint(s1, 0, 0, NULL, NULL) != 4) return 1; return 0; } ustr-1.0.4/T-installed/tst_utf8.c0000644000076400007640000000016710707046704015616 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR(""); if (!ustr_utf8_valid(s1)) return 1; return 0; } ustr-1.0.4/T-installed/tst_spn.c0000644000076400007640000000022510707046453015524 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR1(\4, "1234"); if (ustr_spn_fwd(s1, 0, USTR1(\2, "12")) != 2) return 1; return 0; } ustr-1.0.4/T-installed/tst_sub.c0000644000076400007640000000017010707045252015510 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR(""); if (!ustr_sub(&s1, 1, s1)) return 1; return 0; } ustr-1.0.4/T-installed/tst_ins.c0000644000076400007640000000017010707033207015505 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR(""); if (!ustr_ins(&s1, 0, s1)) return 1; return 0; } ustr-1.0.4/T-installed/tst_fmt.c0000644000076400007640000000020310707032346015502 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR(""); if (!ustr_add_fmt(&s1, "%s", "abcd")) return 1; return 0; } ustr-1.0.4/T-installed/tst_vstr_chk.c0000644000076400007640000000443110726704247016555 0ustar jamesjames/* this compiles with: gcc -Wall -W -lustr $(pkg-config --cflags --libs vstr) \ tst_vstr_chk.c -o tst_vstr_chk */ #include #include #include static int ufmt__ustr_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *spec) { Ustr *us1 = VSTR_FMT_CB_ARG_PTR(spec, 0); size_t sf_len = ustr_len(us1); if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len, VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR)) return (USTR_FALSE); if (!vstr_add_buf(base, pos, ustr_cstr(us1), sf_len)) return (USTR_FALSE); if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len)) return (USTR_FALSE); return (USTR_TRUE); } static int ufmt_add_ustr(struct Vstr_conf *conf, const char *name) { return (vstr_fmt_add(conf, name, ufmt__ustr_cb, VSTR_TYPE_FMT_PTR_VOID, VSTR_TYPE_FMT_END)); } static Vstr_base *vs1 = NULL; int ufmt_beg(char *buf, size_t len, const char *fmt, va_list ap) { size_t ret; vstr_del(vs1, 1, vs1->len); if (!vstr_add_vfmt(vs1, 0, fmt, ap)) return -1; ret = vs1->len; vstr_export_cstr_buf(vs1, 1, vs1->len, buf, len); if (vs1->len > len) vstr_del(vs1, 1, vs1->len); return ret; } int ufmt_end(char *buf, size_t len, const char *fmt, va_list ap) { size_t ret = vs1->len; vstr_export_cstr_buf(vs1, 1, vs1->len, buf, len); vstr_del(vs1, 1, vs1->len); return ret; } int main(void) { Ustr *us1 = USTR(""); struct Ustr_cntl_fmt ufmt; int bad = 1; ufmt.sys_vsnprintf_beg = ufmt_beg; ufmt.sys_vsnprintf_end = ufmt_end; if (!ustr_cntl_opt(USTR_CNTL_OPT_SET_FMT, &ufmt)) return bad; ++bad; if (!vstr_init()) return bad; ++bad; if (!(vs1 = vstr_make_base(NULL))) return bad; ++bad; if (!vstr_cntl_conf(vs1->conf, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '$')) return bad; ++bad; if (!VSTR_SC_FMT_ADD(NULL, ufmt_add_ustr, "")) return bad; ++bad; if (!ustr_add_fmt(&us1, "a%sb", " | ")) return bad; ++bad; assert(ustr_cmp_eq(USTR1(\5, "a | b"), us1)); ustr_sc_del(&us1); assert(!ustr_len(us1)); if (!ustr_add_fmt(&us1, "a$b", USTR1(\3, " | "))) return bad; ++bad; assert(ustr_cmp_eq(USTR1(\5, "a | b"), us1)); vstr_free_base(vs1); vstr_exit(); ustr_sc_free(&us1); return 0; } ustr-1.0.4/T-installed/tst_srch.c0000644000076400007640000000051010707225222015651 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR1(\4, "1234"); if (ustr_srch_fwd(s1, 0, USTR1(\2, "23")) != 2) return 1; /* didn't include a Versioned symbol in 1.0.1 */ if (ustr_srch_rep_chr_fwd(s1, 0, '3', 1) != 3) return 1; if (ustr_srch_rep_chr_fwd(s1, 0, '3', 2) != 0) return 1; return 0; } ustr-1.0.4/T-installed/tst_replace.c0000644000076400007640000000043410707044557016344 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR1(\2, "14"); const char *ptr = NULL; if (ustr_replace(&s1, USTR1(\1, "4"), USTR1(\2, "21"), 0) != 1) return 1; ptr = ustr_cstr(s1); if (ptr[0] != '1' || ptr[1] != '2' || ptr[2] != '1') return 1; return 0; } ustr-1.0.4/T-installed/tst_pool.c0000644000076400007640000000016410707275611015677 0ustar jamesjames#include "ustr.h" int main(void) { Ustr_pool *p = ustr_pool_ll_make(); if (!p) return 1; return 0; } ustr-1.0.4/T-installed/tst_cntl.c0000644000076400007640000000023510707040561015657 0ustar jamesjames#include "ustr.h" int main(void) { size_t val = 0; if (!ustr_cntl_opt(USTR_CNTL_OPT_GET_REF_BYTES, &val) || (val != 1)) return 1; return 0; } ustr-1.0.4/T-installed/tst_split.c0000644000076400007640000000025510707046467016067 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR1(\3, "a|b"); size_t off = 0; if (!ustr_split(s1, &off, USTR1(\1, "|"), NULL, 0)) return 1; return 0; } ustr-1.0.4/T-installed/tst_sc.c0000644000076400007640000000017510707044602015327 0ustar jamesjames#include "ustr.h" int main(void) { Ustr *s1 = USTR(""); if (!ustr_sc_ensure_owner(&s1)) return 1; return 0; } ustr-1.0.4/ustr-ins-code.h0000644000076400007640000002214310760725575014366 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_INS_H #error " Include ustr-ins.h before this file." #endif USTR_CONF_I_PROTO int ustrp__ins_undef(struct Ustr_pool*p,struct Ustr **ps1,size_t pos,size_t len) { /* basically the opposite of ustr_del_subustr() */ 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; const char *ocstr = 0; USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); if (!len) return (USTR_TRUE); s1 = *ps1; clen = ustr_len(s1); USTR_ASSERT_RET(pos <= clen, USTR_FALSE); if (pos == clen) /* inserting at the end */ return (ustrp__add_undef(p, ps1, len)); if ((nlen = clen + len) < clen) /* overflow */ goto fail_enomem; if (ustr__rw_mod(*ps1, nlen, &sz, &oh, &osz, &nsz, &alloc)) { char *ptr; if (!ustrp__add_undef(p, ps1, len)) return (USTR_FALSE); ptr = ustr_wstr(*ps1); memmove(ptr + pos + len, ptr + pos, (clen - pos)); USTR_ASSERT(ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen))) goto fail_enomem; ocstr = ustr_cstr(s1); USTR_ASSERT(pos || (clen - pos)); /* can be both */ ustr__memcpy(ret, 0, ocstr, pos); ustr__memcpy(ret, pos + len, ocstr + pos, clen - pos); 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_ins_undef(struct Ustr **ps1, size_t pos, size_t len) { return (ustrp__ins_undef(0, ps1, pos, len)); } USTR_CONF_I_PROTO int ustrp_ins_undef(struct Ustr_pool *p,struct Ustrp**ps1,size_t pos,size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__ins_undef(p, &tmp, pos, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__ins_buf(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, const void *buf, size_t len) { if (!ustrp__ins_undef(p, ps1, pos, len)) return (USTR_FALSE); ustr__memcpy(*ps1, pos, buf, len); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_ins_buf(struct Ustr **ps1, size_t pos, const void *buf, size_t len) { return (ustrp__ins_buf(0, ps1, pos, buf, len)); } USTR_CONF_I_PROTO int ustrp_ins_buf(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, const void *buf, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__ins_buf(p, &tmp, pos, buf, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__ins(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, const struct Ustr *s2) { if (pos == ustr_len(*ps1)) return (ustrp__add(p, ps1, s2)); if ((*ps1 == s2) && ustr_owner(*ps1)) { size_t len = ustr_len(*ps1); size_t blen = 0; size_t pos2 = 0; if (!ustrp__ins_undef(p, ps1, pos, len)) return (USTR_FALSE); blen = pos; ustr__memcpy(*ps1, pos, ustr_cstr(*ps1), blen); pos += blen; pos2 += len; pos2 += blen; len -= blen; ustr__memcpy(*ps1, pos, ustr_cstr(*ps1) + pos2, len); USTR_ASSERT(ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } return (ustrp__ins_buf(p, ps1, pos, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_I_PROTO int ustr_ins(struct Ustr **ps1, size_t pos, const struct Ustr *s2) { return (ustrp__ins(0, ps1, pos, s2)); } USTR_CONF_I_PROTO int ustrp_ins(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, const struct Ustrp *s2) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__ins(p, &tmp, pos, &s2->s); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__ins_subustr(struct Ustr_pool *p, struct Ustr **ps1, size_t pos1, const struct Ustr *s2, size_t pos2, size_t len2) { size_t clen2 = 0; if (!len2) return (USTR_TRUE); if (!(clen2 = ustrp__assert_valid_subustr(!!p, s2, pos2, len2))) return (USTR_FALSE); if (clen2 == len2) return (ustrp__ins(p, ps1, pos1, s2)); if (pos1 == clen2) return (ustrp__add_subustr(p, ps1, s2, pos2, len2)); if ((*ps1 == s2) && ustr_owner(*ps1)) { if (!ustrp__ins_undef(p, ps1, pos1, len2)) return (USTR_FALSE); if (pos2 > pos1) pos2 += len2; else if ((pos2 + len2 - 1) > pos1) { size_t blen = (pos1 - pos2) + 1; ustr__memcpy(*ps1, pos1, ustr_cstr(*ps1) + pos2 - 1, blen); pos1 += blen; pos2 += len2; pos2 += blen; len2 -= blen; } ustr__memcpy(*ps1, pos1, ustr_cstr(*ps1) + pos2 - 1, len2); USTR_ASSERT(ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } --pos2; return (ustrp__ins_buf(p, ps1, pos1, ustr_cstr(s2) + pos2, len2)); } USTR_CONF_I_PROTO int ustr_ins_subustr(struct Ustr **ps1, size_t pos1, const struct Ustr *s2, size_t pos2, size_t len2) { return (ustrp__ins_subustr(0, ps1, pos1, s2, pos2, len2)); } USTR_CONF_I_PROTO int ustrp_ins_subustrp(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos1, const struct Ustrp *s2, size_t pos2, size_t len2) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__ins_subustr(p, &tmp, pos1, &s2->s, pos2, len2); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__ins_rep_chr(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, char chr, size_t len) { if (!ustrp__ins_undef(p, ps1, pos, len)) return (USTR_FALSE); ustr__memset(*ps1, pos, chr, len); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_ins_rep_chr(struct Ustr **ps1, size_t pos, char chr, size_t len) { return (ustrp__ins_rep_chr(0, ps1, pos, chr, len)); } USTR_CONF_I_PROTO int ustrp_ins_rep_chr(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, char chr, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__ins_rep_chr(p, &tmp, pos, chr, len); *ps1 = USTRP(tmp); return (ret); } #ifdef USTR_FMT_H # if USTR_CONF_HAVE_VA_COPY USTR_CONF_i_PROTO int ustrp__ins_vfmt_lim(struct Ustr_pool *p, struct Ustr **ps1, size_t pos, size_t lim, const char *fmt, va_list ap) { /* NOTE: Copy and pasted so we can use ustrp_set_undef() */ va_list nap; int rc = -1; char buf[USTR__SNPRINTF_LOCAL]; char *ptr; char save_end; USTR__VA_COPY(nap, ap); rc = USTR_CONF_VSNPRINTF_BEG(buf, sizeof(buf), fmt, nap); va_end(nap); if ((rc == -1) && ((rc = ustr__retard_vfmt_ret(fmt, ap)) == -1)) return (USTR_FALSE); if (lim && ((size_t)rc > lim)) rc = lim; if ((size_t)rc < sizeof(buf)) /* everything is done */ return (ustrp__ins_buf(p, ps1, pos, buf, rc)); if (!ustrp__ins_undef(p, ps1, pos, rc)) return (USTR_FALSE); ptr = ustr_wstr(*ps1); save_end = ptr[pos + rc]; /* might be NIL, might be a char */ USTR_CONF_VSNPRINTF_END(ptr + pos, rc + 1, fmt, ap); ptr[pos + rc] = save_end; USTR_ASSERT(ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_ins_vfmt_lim(struct Ustr **ps1,size_t pos,size_t lim, const char *fmt, va_list ap) { return (ustrp__ins_vfmt_lim(0, ps1, pos, lim, fmt, ap)); } USTR_CONF_I_PROTO int ustrp_ins_vfmt_lim(struct Ustr_pool *p,struct Ustrp **ps1, size_t pos, size_t lim, const char *fmt, va_list ap) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__ins_vfmt_lim(p, &tmp, pos, lim, fmt, ap); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_I_PROTO int ustr_ins_fmt_lim(struct Ustr **ps1, size_t pos, size_t lim, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustr_ins_vfmt_lim(ps1, pos, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustrp_ins_fmt_lim(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, size_t lim, const char*fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustrp_ins_vfmt_lim(p, ps1, pos, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustr_ins_vfmt(struct Ustr **ps1, size_t pos, const char *fmt, va_list ap) { return (ustr_ins_vfmt_lim(ps1, pos, 0, fmt, ap)); } USTR_CONF_I_PROTO int ustrp_ins_vfmt(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, const char *fmt, va_list ap) { return (ustrp_ins_vfmt_lim(p, ps1, pos, 0, fmt, ap)); } USTR_CONF_I_PROTO int ustr_ins_fmt(struct Ustr **ps1, size_t pos, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustr_ins_vfmt(ps1, pos, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustrp_ins_fmt(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos, const char *fmt, ...) { va_list ap; int ret = USTR_FALSE; va_start(ap, fmt); ret = ustrp_ins_vfmt(p, ps1, pos, fmt, ap); va_end(ap); return (ret); } # endif #endif ustr-1.0.4/Documentation/0000755000076400007640000000000010763663475014333 5ustar jamesjamesustr-1.0.4/Documentation/constants.txt0000644000076400007640000003655210726704140017103 0ustar jamesjamesSection: Compile switch constants Constant: USTR_CONF_INCLUDE_CODEONLY_HEADERS Explanation: This switch controls whether all the code will be included as inline functions. Having this be non-zero means that you don't have to link against the library. Constant: USTR_CONF_USE_EOS_MARK Explanation: This switch turns on End of String markers, so any bounds overflow will be noticed by ustr_assert_valid(). Note: Changing this will not do anything useful unless USTR_CONF_INCLUDE_CODEONLY_HEADERS is non-zero. Constant: USTR_CONF_USE_ASSERT Explanation: This switch turns USTR_ASSERT() calls on, so the code within them will be evaluated. Note that there are many calls to ustr_assert_valid() within USTR_ASSERT() macros and that call is relatively expensive. Note: Changing this will not do anything useful unless USTR_CONF_INCLUDE_CODEONLY_HEADERS is non-zero. Constant: USTR_CONF_COMPILE_USE_ATTRIBUTES Explanation: This switch controls whether gcc type __attribute__() statements are used in the public headers headers for the library. If the value is 1 then if they are supported by the compiler that built the library they will be used, if the value is 0 they won't be used at all. Constant: USTR_CONF_COMPILE_TYPEDEF Explanation: This switch controls whether typedef will be used for the structs in the public headers for the library. If the value is 1 then they will be used, if the value is 0 they won't be used at all (and your code will have to use struct tags instead -- note all libraries using ustr should compile without this option set). Constant: USTR_CONF_COMPILE_USE_INLINE Explanation: This switch controls whether inline functions will be used in a few cases where the function bodies are very small. Note: In some cases this is used so that GCC can eliminate calls to strlen(), for the *_cstr() functions. Section: Constants to created fixed/read-only Ustr's Constant: USTR_BEG_CONST1 Explanation: This macro is a constant C-style string of the first byte of a constant/read-only Ustr that has a length in the range 0-255. Constant: USTR_BEG_CONST2 Explanation: This macro is a constant C-style string of the first byte of a constant/read-only Ustr that has a length in the range 0-65535. Constant: USTR_BEG_CONST4 Explanation: This macro is a constant C-style string of the first byte of a constant/read-only Ustr that has a length in the range 0-4294967295. Constant: USTR_BEG_FIXED1 Explanation: This macro is a constant C-style string of the first byte of a fixed Ustr that has a length in the range 0-255. Constant: USTR_BEG_FIXED2 Explanation: This macro is a constant C-style string of the first byte of a fixed Ustr that has a length in the range 0-65535. Constant: USTR_BEG_FIXED4 Explanation: This macro is a constant C-style string of the first byte of a fixed Ustr that has a length in the range 0-4294967295. Constant: USTR_BEG_FIXED8 Explanation: This macro is a constant C-style string of the first byte of a fixed Ustr that has a length in the range 0-18446744073709551615. Note: This macro is only available if the Ustr code was compiled in a 64bit environment. Constant: USTR_END_ALOCDx Explanation: This macro is a constant C-style string of the last bytes of an allocated Ustr. Note: Unless USTR_CONF_USE_EOS_MARK is non-zero, this is just the NIL byte. Constant: USTR_END_CONSTx Explanation: This macro is a constant C-style string of the last bytes of a constant/read-only Ustr. Note: Unless USTR_CONF_USE_EOS_MARK is non-zero, this is just the NIL byte. Constant: USTR_END_FIXEDx Explanation: This macro is a constant C-style string of the last bytes of a fixed Ustr. Note: Unless USTR_CONF_USE_EOS_MARK is non-zero, this is just the NIL byte. Section: Constants to use with parsing numbers: ustr_parse_uintmaxx, etc. Constant: USTR_FLAG_PARSE_NUM_DEF Explanation: Default flags, this is merely 0 but can be used as live documentation. Constant: USTR_FLAG_PARSE_NUM_SEP Explanation: This flag allows the parsing (and ignoring) of the seperator character, at arbitrary pointers in the number, so "1234" and "1_234" would both parse the same (assuming "_" is the seperator). Constant: USTR_FLAG_PARSE_NUM_OVERFLOW Explanation: This flag turns on the overflow checking, in other words without it USTR_TYPE_PARSE_NUM_ERR_OVERFLOW will never be returned as an error code. Constant: USTR_FLAG_PARSE_NUM_SPACE Explanation: This flag allows one or more ' ' (Space) characters before the number or number prefix (Plus Sign, Hyphen). Note: Other forms of whitespace don't count, this just affects ' '. Constant: USTR_FLAG_PARSE_NUM_NO_BEG_ZERO Explanation: This flag disallows one or more '0' (Digit Zero) characters before the number. Constant: USTR_FLAG_PARSE_NUM_NO_BEG_PM Explanation: This flag disallows a plus or a minus character before the number. Constant: USTR_FLAG_PARSE_NUM_NO_NEGATIVE Explanation: This flag disallows negative values. Constant: USTR_FLAG_PARSE_NUM_EXACT Explanation: This flag makes the parsing functions return an error if the entire string doesn't contain the number being parsed. Constant: USTR_TYPE_PARSE_NUM_ERR_NONE Explanation: This error code has the value 0, and means that no error occurred parsing the number. Constant: USTR_TYPE_PARSE_NUM_ERR_ONLY_S Explanation: This error code means that the Ustr string consisted only of spaces. Constant: USTR_TYPE_PARSE_NUM_ERR_ONLY_SPM Explanation: This error code means that the Ustr string consisted only spaces, and a plus or minus sign. Constant: USTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX Explanation: This error code means that the Ustr string consisted of only spaces, a plus or minus sign and a "0x" base 16 prefix. Constant: USTR_TYPE_PARSE_NUM_ERR_OOB Explanation: This error code means that the Ustr string had characters in it that where out of bounds from the working base. Note: Without the USTR_FLAG_PARSE_NUM_EXACT, this error is ignored as soon as any number is parsed. This out of bounds includes the Ustr string "++" as well as "4A", when parsing in a base less than 11. Constant: USTR_TYPE_PARSE_NUM_ERR_OVERFLOW Explanation: This error code means that the number parsed from the Ustr string would overflow the type it is being parsed into, this is only returned when the USTR_FLAG_PARSE_NUM_OVERFLOW flag was passed to the parse function. Constant: USTR_TYPE_PARSE_NUM_ERR_NEGATIVE Explanation: This error code means that the number parsed from the Vstr string starts with a '-' (Hyphen) character when it is supposed to be an unsigned number. Constant: USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO Explanation: This error code means that the number parsed from the Vstr string starts with a '0' (Digit Zero) character, when the USTR_FLAG_PARSE_NUM_NO_BEG_ZERO flag was passed to the parse function. Section: Constants to pass to ustr_split* Constant: USTR_FLAG_SPLIT_DEF Explanation: Default flags, this is merely 0 but can be used as live documentation. Constant: USTR_FLAG_SPLIT_RET_SEP Explanation: Return the separator along with the tokens. For example splitting "a,b," using separator "," will return the tokens "a," and "b," whereas without this flag only "a" and "b" would be returned. Constant: USTR_FLAG_SPLIT_RET_NON Explanation: Return empty tokens. For example: splitting "a,,b" with separator "," will return the tokens {"a" "" "b"}. Constant: USTR_FLAG_SPLIT_KEEP_CONFIG Explanation: Force the returned Ustr's to have same configuration parameters as the Ustr string that is being split. Section: Misc constants to use in code Constant: USTR_NULL Explanation: This macro is merely 0 cast to (struct Ustr *), and can be used anywhere NULL would be but "returns" the correct type. Constant: USTR_POOL_NULL Explanation: This macro is merely 0 cast to (struct Ustr_pool *), and can be used anywhere NULL would be but "returns" the correct type. Constant: USTR_TRUE Explanation: This macro is 1, but shows the intent that a boolean value is expected and not a number. Constant: USTR_FALSE Explanation: This macro is 0, but shows the intent that a boolean value is expected and not a number. Section: Constants passed to ustr_cntl_opt() Constant: USTR_CNTL_OPT_GET_REF_BYTES Parameter[1]: Number of bytes for default reference count in Ustr Type[1]: size_t * Explanation: This option will get the default number of bytes used for a reference count when creating Ustr's. Constant: USTR_CNTL_OPT_SET_REF_BYTES Parameter[1]: Number of bytes for default reference count in Ustr Type[1]: size_t Explanation: This option will set the default number of bytes used for a reference count when creating Ustr's. Note: For a single instance, the ustr_dupx_*() functions can be used. Constant: USTR_CNTL_OPT_GET_HAS_SIZE Parameter[1]: Default flag for whether to include an explicit size in a Ustr Type[1]: int * Explanation: This option will get the default flag for whether to store an explicit size in created Ustr's. Constant: USTR_CNTL_OPT_SET_HAS_SIZE Parameter[1]: Default flag for whether to include an explicit size in a Ustr Type[1]: int Explanation: This option will set the default flag for whether to store an explicit size in created Ustr's. Note: For a single instance, the ustr_dupx_*() functions can be used. Constant: USTR_CNTL_OPT_GET_EXACT_BYTES Parameter[1]: Default flag for whether to exactly allocate memory Type[1]: int * Explanation: This option will get the default flag for whether to exactly allocate memory when a Ustr needs to be resized. Constant: USTR_CNTL_OPT_SET_EXACT_BYTES Parameter[1]: Default flag for whether to exactly allocate memory Type[1]: int Explanation: This option will set the default flag for whether to exactly allocate memory when a Ustr needs to be resized. Note: For a single instance, the ustr_dupx_*() functions can be used. Constant: USTR_CNTL_OPT_GET_MEM Parameter[1]: Pointer to colleciton of function pointers for system allocation Type[1]: struct Ustr_cntl_mem * Explanation: This option will get the "system" allocation functions (malloc, realloc, free) for allocated Ustr's. Note: As you would expect the default values are: malloc, realloc, free. Constant: USTR_CNTL_OPT_SET_MEM Parameter[1]: Pointer to colleciton of function pointers for system allocation Type[1]: const struct Ustr_cntl_mem * Explanation: This option will set the "system" allocation functions (malloc, realloc, free) for allocated Ustr's. Note: If this option is set after a Ustr has been created, then when freeing or reallocating the existing Ustr the given functions will be used. So they must either be compatible with the default or you must ensure that nothing is allocated before they are set. Constant: USTR_CNTL_OPT_GET_MC_M_SCRUB Parameter[1]: Flag for whether to include an explicit size in a Ustr Type[1]: int * Explanation: This option will get the flag for whether to "scrub" data allocated via. malloc check. Note: Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. Constant: USTR_CNTL_OPT_SET_MC_M_SCRUB Parameter[1]: Flag for whether to include an explicit size in a Ustr Type[1]: int Explanation: This option will set the flag for whether to "scrub" data allocated via. malloc check. Note: Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. Constant: USTR_CNTL_OPT_GET_MC_F_SCRUB Parameter[1]: Flag for whether to include an explicit size in a Ustr Type[1]: int * Explanation: This option will get the flag for whether to "scrub" data freed via. malloc check. Note: Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. Constant: USTR_CNTL_OPT_SET_MC_F_SCRUB Parameter[1]: Flag for whether to include an explicit size in a Ustr Type[1]: int Explanation: This option will set the flag for whether to "scrub" data freed via. malloc check. Note: Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. Constant: USTR_CNTL_OPT_GET_MC_R_SCRUB Parameter[1]: Flag for whether to include an explicit size in a Ustr Type[1]: int * Explanation: This option will get the flag for whether to "scrub" data reallocated via. malloc check. This is done by turning all reallocations into a malloc() and free(), and so is even more costly than normal scrubbing. Note: Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. Constant: USTR_CNTL_OPT_SET_MC_R_SCRUB Parameter[1]: Flag for whether to include an explicit size in a Ustr Type[1]: int Explanation: This option will set the flag for whether to "scrub" data reallocated via. malloc check. This is done by turning all reallocations into a malloc() and free(), and so is even more costly than normal scrubbing. Note: Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. Constant: USTR_CNTL_OPT_GET_FMT Parameter[1]: Pointer to colleciton of function pointers for system formating Type[1]: struct Ustr_cntl_fmt * Explanation: This option will get the system formatting functions (vsnprintf) for Ustr's. There are two functions, the first is always called and the second is likely called (always with the exact same arguments) if the length passed to the first call was not big enough. Note: As you would expect the default values are: vsnprintf and vsnprintf Constant: USTR_CNTL_OPT_SET_FMT Parameter[1]: Pointer to colleciton of function pointers for system formatting Type[1]: const struct Ustr_cntl_fmt * Explanation: This option will set the system formatting functions (vsnprintf) for Ustr's. Section: Constants passed to ustr_pool_ll_cntl() Constant: USTR_POOL_LL_CNTL_GET_FREE_CMP Parameter[1]: Number of pointers to compare to in the pool Type[1]: unsigned int * Explanation: This option will get the number of comparisons done on a pool free operation. Constant: USTR_POOL_LL_CNTL_SET_FREE_CMP Parameter[1]: Number of pointers to compare to in the pool Type[1]: unsigned int Explanation: This option will set the number of comparisons done on a pool free operation. Note: The default is a small non-zero value, as it's significantly common to have very short lived ustr's ... however this doesn't mean that you can't forget to take references even with pool allocated ustrs. Constant: USTR_POOL_LL_CNTL_GET_REALLOC Parameter[1]: Flag for if we should call realloc() Type[1]: int * Explanation: This option will get the flag for if we call realloc() to make data bigger, or revert to just allocating anew each time. Constant: USTR_POOL_LL_CNTL_SET_REALLOC Parameter[1]: Flag for if we should call realloc() Type[1]: int Explanation: This option will set the flag for if we call realloc() to make data bigger, or revert to just allocating anew each time. Note: As with USTR_POOL_LL_CNTL_SET_FREE_CMP this option means you can't assume that pool allocated data is never freed until ustr_pool_free() is called, and again it is due to there being significant speed improvements for not making that assumption. Instead of disabling this option, just take areference (which will also make sure the ustr isn't modified behind your back). ustr-1.0.4/Documentation/txt2man.pl0000755000076400007640000001277410763530035016264 0ustar jamesjames#! /usr/bin/perl -w use strict; use FileHandle; my $docs = undef; if (0) {} elsif (-d "./Documentation") # In main dir... { $docs ="./Documentation"; } elsif (-d "../Documentation") # Probably in the docs dir... { $docs ="../Documentation"; } if (!defined ($docs)) { STDERR->print("Can't find Documentation.\n"); exit (1); } my $hdr_date = `date '+%d-%b-%Y'`; chomp($hdr_date); # FIXME: More C&P of VERSION my $hdr_ver = "1.0.4"; my $man_funcs_header = <print(");\n"); } while () { if (s!^(Function): (.*)\(\)$!$2! || s!^(Constant|Member): (.*)$!$2!) { chomp; if (!$funcs) { OUT->print(".br\n"); OUT->print(".ti \\w' 'u\n"); OUT->print("\\fB$_\\fR\n"); } else { if ($func) { fin($funcs, $args); } $args = 0; $func = $_; } if (( $funcs && $1 ne "Function") || (!$funcs && $1 eq "Function") || 0) { die "Bad txt documentation."; } } elsif ($funcs && /^ Type: (.*)/) { my $spc = " "; $_ = $1; chomp; if (/\*$/) { $spc = ""; } OUT->print(".br\n"); # FIXME: \w doesn't account for space filling OUT->print(".in \\w' $_$spc\\fB$func\\fR('u\n"); OUT->print(".ti \\w' 'u\n"); OUT->print("$_$spc\\fB$func\\fR("); } elsif ($funcs && /^ Type\[.+\]: (.*)/) { $_ = $1; chomp; if ($args) { OUT->print(", "); } ++$args; OUT->print("$1"); } elsif (/^Section:/) { if ($func) { fin($funcs, $args); } $args = 0; $func = 0; OUT->print(".sp\n"); } } fin($funcs, $args); OUT->print("\n"); } sub conv_A_refs { my $params = shift; my $markup = shift; my $raw = shift; s/\\/\\\\/g if (!$raw); s/-/\\-/g ; s![*]{2}([^*]+)[*]{2}!\\fB$1\\fR!g if ($markup); } sub convert() { my $in_pre_tag = ""; my $in_const = 0; while () { my $next_in_const = 0; my $beg_replace = "$in_pre_tag.br\n"; if ($in_const) { $beg_replace = "$in_pre_tag\n"; } if (s!^(Constant|Function|Member): (.*)$!$beg_replace\\fB$1: \\fR $2! || s!^ Explanation:\s*$!$beg_replace\\fBExplanation:\\fR! || s!^ Note:\s*$!.sp\n\\fBNote:\\fR! || s!^Section:\s*(.*)$!.SH $1! || 0) { s/-/\\-/g ; if (defined ($1) && ($1 eq "Function")) { $_ = ".ti -2\n" . $_; } if (defined ($1) && ($1 eq "Constant")) { $next_in_const = 1; } } elsif (m!^ ([A-Z][a-z]+)(\[\d\]|\[ \.\.\. \])?: (.*)$!) { if (defined $2) { if ($1 eq "Type") { $_ = ".br\n$1\\fB$2\\fR: $3\n"; } else { $_ = ".br\n$1\\fB$2\\fR: $3\n"; } } else { if ($1 eq "Type") { $_ = ".br\n$1: $3\n"; } else { $_ = ".br\n$1: $3\n"; } } conv_A_refs(0, 0, 1); } elsif (/^ \.\.\./) { if (/\.\.\.$/) { conv_A_refs(1, 1, 0); $_ = ".Ve\n$_.Vb 4\n"; $in_pre_tag = "\n.Ve"; } else { conv_A_refs(1, 1, 0); $_ = ".Ve\n$_"; $in_pre_tag = ""; } } elsif (/\.\.\.$/) { conv_A_refs(1, 1, 0); $_ = "$_\n.Vb 4"; $in_pre_tag = "\n.Ve"; } elsif (!$in_pre_tag) { if (!/^$/) { chomp; if (/^ /) { $_ = "\n.br\n" . $_; } } conv_A_refs(1, 1, 0); } else { conv_A_refs(1, 1, 0); } $in_const = $next_in_const; OUT->print($_); } } # MAIN # functions man page... open (IN, "< $docs/functions.txt") || die "open(functions.txt): $!"; open (OUT, "> ustr.3") || die "open(ustr.3): $!"; OUT->print($man_funcs_header); synopsis(1); open (IN, "< $docs/functions.txt") || die "open(functions.txt): $!"; OUT->print($man_funcs_desc); convert(); OUT->print($man_funcs_seealso); # constants man page... open (IN, "< $docs/constants.txt") || die "open(constants.txt): $!"; open (OUT, "> ustr_const.3") || die "open(ustr_const.3): $!"; OUT->print($man_consts_header); synopsis(0); open (IN, "< $docs/constants.txt") || die "open(constants.txt): $!"; OUT->print($man_consts_desc); convert(); OUT->print($man_consts_seealso); exit (0); ustr-1.0.4/Documentation/ustr_pad.xml0000644000076400007640000001145310763652513016671 0ustar jamesjames gsoftpad 1.3 To find more on gsoftpad go to http://gsoftpad.sourceforge.net James Antill www.and.org James Antill james@and.org James Antill james@and.org james@and.org james@and.org james@and.org ustr 1.0.4 03 5 2008 0 USD Freeware Minor Update Install and Uninstall Linux,Unix,WinXP,WinNT 4.x,Windows2000,Windows CE,Mac PPC,MS-DOS English Fixed a bug in ustr_cspn_chr_rev. Added join/concat functions. Minor fixes and cleanups. Development Tools N N N ustr ustr-1.0.4 ustr-1.0.3 ustr-1.0.4.tar.gz 300001 292.97 0.29 N string small String library, safe, small and easy to use. String library, using safe dyanmic resizing of storage, small and easy to use. Ustr is a safe and very small string library for C. It is designed for usage with lots of small strings. It also contains a lot of helper functions, and can be used without linking. Ustr is a safe and very small string library for C. It is designed for usage with lots of small strings. It also contains a lot of helper functions, and can be used without linking. Ustr is a safe and very small string library for C, with an average overhead of only 44% over plain strdup() for strings in the 0-20 byte range. It is designed for usage with lots of small strings, including reference counting etc. It can be used to constant/read-only strings and stack based allocated strings. It also contains a lot of helper functions, and can be used without linking. http://www.and.org/ustr/ http://www.and.org/ustr/ustr_pad.xml http://www.and.org/ustr/1.0.3/ustr-1.0.3.tar.gz ftp://ftp.and.org/pub/james/ustr/1.0.3/ustr-1.0.3.tar.gz http://www.and.org/ustr/1.0.3/rpms/ ftp://ftp.and.org/pub/james/ustr/1.0.3/rpms/ MIT, BSD, LGPL (Version 2.1, February 1999 -- or later) n/a ustr-1.0.4/Documentation/Makefile0000644000076400007640000000064510630164053015755 0ustar jamesjamesALL = \ functions.html \ constants.html \ ustr.3 \ ustr_const.3 \ all: $(ALL) # This _shouldn't_ be part of teh normal build ... so we need to make sure it # happens before we distribute. functions.html: functions.txt txt2html.pl ./txt2html.pl constants.html: constants.txt txt2html.pl ./txt2html.pl ustr.3: functions.txt txt2man.pl ./txt2man.pl ustr_const.3: constants.txt txt2man.pl ./txt2man.pl ustr-1.0.4/Documentation/functions.html0000644000076400007640000116440510763663475017244 0ustar jamesjames Ustr - 1.0.4 reference documentation -- functions

Ustr - 1.0.4 reference documentation -- functions (301)

Index of sections

Index of sections, and their contents

Creating read-only Ustr functions

Function: USTR()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Pointer to Ustr data
Type[1]: void *
Explanation:

This macro function is normally used with the empty string "".

Note:

There is basically just a simple cast behind the macro.

Function: USTRP()
Returns: Ustrp string
Type: struct Ustrp *
Parameter[1]: Pointer to Ustrp data
Type[1]: void *
Explanation:

This macro function is normally used with the empty string "".

Note:

There is basically just a simple cast behind the macro.

Function: USTR1()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Encoded number of the length of Ustr string
Type[1]: symbol
Parameter[2]: Data for Ustr string
Type[2]: const char[]
Explanation:

This macro function simplifies the creation of read-only Ustr string's. And is normally used like...

  USTR1(\x4, "abcd")

...it is worth pointing out that running with debugging turned on (USTR_CONF_USE_ASSERT) will complain if the length isn't encoded correctly, as in...

  USTR1(\x3, "abcd")

...here ustr_assert_valid() will fail, which is called before most functions do anything in debugging mode. Note also that extra debugging (USTR_CONF_USE_EOS_MARK) will still catch cases like...

  USTR1(\x3, "abc\0d")

...at least using debugging is esp. important if you are putting UTF-8 characters into the strings.

Note:

Having ustr_ro() return true means that the Ustr cannot be written to without be reallocated into allocation space ... not that ustr_add() etc. will fail.

There is now USTR1_CHK() which performs a compile time check so you can never have an invalid ustr.

Function: USTR2()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Encoded 2nd byte of number of the length of Ustr string
Type[1]: symbol
Parameter[2]: Encoded 1st byte of number of the length of Ustr string
Type[2]: symbol
Parameter[3]: Data for Ustr string
Type[3]: const char[]
Explanation:

This function works in the same way as USTR1() but takes two length bytes, so the read-only string can be upto 65,535 (2**16 - 1) bytes in length.

Function: USTR4()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Encoded 4th byte of number of the length of Ustr string
Type[1]: symbol
Parameter[2]: Encoded 3rd byte of number of the length of Ustr string
Type[2]: symbol
Parameter[3]: Encoded 2nd byte of number of the length of Ustr string
Type[3]: symbol
Parameter[4]: Encoded 1st byte of number of the length of Ustr string
Type[4]: symbol
Parameter[5]: Data for Ustr string
Type[5]: const char[]
Explanation:

This function works in the same way as USTR1() but takes four length bytes, so the read-only string can be upto 2**32 - 1 bytes in length.

Function: USTR1_CHK()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Encoded number of the length of Ustr string
Type[1]: symbol
Parameter[2]: Data for Ustr string
Type[2]: const char[]
Explanation:

This function works in the same way as USTR1() but it does a check against the length of (Parameter[2]) using sizeof() - 1.

Note:

If the check fails the returned Ustr * will be "", so you can check ustr_len() to see if you screwed something up.

Function: USTR2_CHK()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Encoded 2nd byte of number of the length of Ustr string
Type[1]: symbol
Parameter[2]: Encoded 1st byte of number of the length of Ustr string
Type[2]: symbol
Parameter[3]: Data for Ustr string
Type[3]: const char[]
Explanation:

This function works in the same way as USTR2() but it does a check against the length of (Parameter[2]) using sizeof() - 1.

Note:

If the check fails the returned Ustr * will be "".

Function: USTR4_CHK()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Encoded 4th byte of number of the length of Ustr string
Type[1]: symbol
Parameter[2]: Encoded 3rd byte of number of the length of Ustr string
Type[2]: symbol
Parameter[3]: Encoded 2nd byte of number of the length of Ustr string
Type[3]: symbol
Parameter[4]: Encoded 1st byte of number of the length of Ustr string
Type[4]: symbol
Parameter[5]: Data for Ustr string
Type[5]: const char[]
Explanation:

This function works in the same way as USTR4() but it does a check against the length of (Parameter[2]) using sizeof() - 1.

Note:

If the check fails the returned Ustr * will be "".

Function: USTRP1()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Encoded number of the length of Ustr string
Type[1]: symbol
Parameter[2]: Data for Ustr string
Type[2]: const char[]
Explanation:

This function works like USTR1(), but returns a Ustrp instead.

Function: USTRP2()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Encoded 2nd byte of number of the length of Ustr string
Type[1]: symbol
Parameter[2]: Encoded 1st byte of number of the length of Ustr string
Type[2]: symbol
Parameter[3]: Data for Ustr string
Type[3]: const char[]
Explanation:

This function works like USTR4(), but returns a Ustrp instead.

Function: USTRP4()
Returns: Ustrp string
Type: struct Ustrp *
Parameter[1]: Encoded 4th byte of number of the length of Ustrp string
Type[1]: symbol
Parameter[2]: Encoded 3rd byte of number of the length of Ustrp string
Type[2]: symbol
Parameter[3]: Encoded 2nd byte of number of the length of Ustrp string
Type[3]: symbol
Parameter[4]: Encoded 1st byte of number of the length of Ustrp string
Type[4]: symbol
Parameter[5]: Data for Ustr string
Type[5]: const char[]
Explanation:

This function works like USTR2(), but returns a Ustrp instead.

Function: USTRP1_CHK()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Encoded number of the length of Ustr string
Type[1]: symbol
Parameter[2]: Data for Ustr string
Type[2]: const char[]
Explanation:

This function works like USTR1_CHK(), but returns a Ustrp instead.

Function: USTRP2_CHK()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Encoded 2nd byte of number of the length of Ustr string
Type[1]: symbol
Parameter[2]: Encoded 1st byte of number of the length of Ustr string
Type[2]: symbol
Parameter[3]: Data for Ustr string
Type[3]: const char[]
Explanation:

This function works like USTR4_CHK(), but returns a Ustrp instead.

Function: USTRP4_CHK()
Returns: Ustrp string
Type: struct Ustrp *
Parameter[1]: Encoded 4th byte of number of the length of Ustrp string
Type[1]: symbol
Parameter[2]: Encoded 3rd byte of number of the length of Ustrp string
Type[2]: symbol
Parameter[3]: Encoded 2nd byte of number of the length of Ustrp string
Type[3]: symbol
Parameter[4]: Encoded 1st byte of number of the length of Ustrp string
Type[4]: symbol
Parameter[5]: Data for Ustr string
Type[5]: const char[]
Explanation:

This function works like USTR2_CHK(), but returns a Ustrp instead.

Creating fixed Ustr functions

Function: USTR_SIZE_FIXED()
Returns: Size of area of memory
Type: size_t
Parameter[1]: Size of area of memory
Type[1]: size_t
Explanation:

This macro function is replaced by a static conversion from the max length desired (Parameter[1]) to the storage size needed. In other words it works out what ustr_size_overhead() will be, and adds that value.

Note:

This is useful is you want a small fixed size allocation, as you can declare it like so:

char buf[USTR_SIZE_FIXED(4)]; ...to give you exactly 4 bytes as a maximum, this is esp. useful if you want a limited (ustr_limited() == USTR_TRUE) Ustr string.

Function: ustr_init_fixed()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Pointer to area of memory to use as a Ustr string
Type[1]: void *
Parameter[2]: Size of area of memory
Type[2]: size_t
Parameter[3]: Whether the fixed size Ustr should be limited
Type[3]: int
Parameter[4]: The initial length of the Ustr
Type[4]: size_t
Explanation:

This creates a new Ustr string, which is "fixed". This means the Ustr storage is managed outside of the ustr_* API, it is often used for stack allocated strings.

As you add data to the Ustr past the size allowed via. the fixed storge the Ustr will automatically be converted into an allocated Ustr. So if this is possible you should always call ustr_free(), as this does nothing if given a fixed size Ustr.

Note:

For simplicity you probably want to use USTR_SC_INIT_AUTO() or USTR_SC_INIT_AUTO() when possible.

Function: USTR_SC_INIT_AUTO()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Area of memory to use as a Ustr string
Type[1]: char[]
Parameter[2]: Whether the fixed size Ustr should be limited
Type[2]: int
Parameter[3]: The initial length of the Ustr
Type[3]: size_t
Explanation:

This calls ustr_init_fixed() with sizeof() the area of memory (Parameter[1]) as the second argument.

Note:

This does mean that the first argument must be the correct size, as far as sizeof() is concerned, as in...

 char buf_sz[1024];
 Ustr *s1 = USTR_SC_INIT_AUTO(buf_sz, USTR_FALSE, 0);

...so passing pointers to memory from malloc() will probably just return NULL.

Function: USTR_SC_INIT_AUTO_OSTR()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Area of memory to use as a Ustr string
Type[1]: char[]
Parameter[2]: Whether the fixed size Ustr should be limited
Type[2]: int
Parameter[3]: The initial string in the buffer, as a constant string
Type[3]: size_t
Explanation:

This calls ustr_init_fixed() with sizeof() the area of memory (Parameter[1]) as the second argument, given as an "object string".

Note:

This does mean that the first argument must be the correct size, as far as sizeof() is concerned, as in...

 char buf_sz[1024] = USTR_BEG_FIXED2 "abcd";
 Ustr *s1 = USTR_SC_INIT_AUTO_OSTR(buf_sz, USTR_FALSE, "abcd");

...so passing pointers to memory from malloc() will probably just return NULL.

Debugging functions

Function: ustr_assert_valid()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a Ustr string
Type[1]: Ustr *
Explanation:

This function asserts a few internal consistency checks, and can help point out when a Ustr is invalid.

Note:

This calls ustr_assert_ret() so that when USTR_DEBUG if off the checks are still performed and the result is returned.

Function: ustr_assert_valid_subustr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a Ustr string
Type[1]: Ustr *
Parameter[2]: Position in the Ustr
Type[2]: size_t
Parameter[3]: Length to delete from the Ustr
Type[3]: size_t
Explanation:

This function calls ustr_assert_valid() and also checks that the position and length are within the Ustr. If they aren't valid it returns 0, if they are valid it returns ustr_len().

Function: USTR_CNTL_MALLOC_CHECK_BEG()
Returns: Success or failure
Type: int
Parameter[1]: Condition for begin malloc checking or not
Type[1]: int
Explanation:

This function begins malloc checking, meaning all ustr allocations will go through the malloc check routines, but it fails if the condition check (Parameter[1]) fails.

Note:

Turning malloc checking on after one or more allocations has happened will lead to false failures unless you really known what you are doing.

You can automatically turn malloc checking on by giving the USTR_CNTL_MC environment variable the value of "1", "yes" or "on".

Function: USTR_CNTL_MALLOC_CHECK_LVL()
Returns: Level of current malloc check
Type: int
Parameter[1]: Nothing
Type[1]: void
Explanation:

This function returns the current "level" of the malloc check, with 0 indicating that malloc check isn't enabled.

The level goes up by one whenever USTR_CNTL_MALLOC_CHECK_BEG() or USTR_CNTL_MALLOC_CHECK_ADD() returns success, and goes down by one whenever USTR_CNTL_MALLOC_CHECK_DEL() or USTR_CNTL_MALLOC_CHECK_END() returns success.

Function: USTR_CNTL_MALLOC_CHECK_MEM()
Returns: Success or failure
Type: int
Parameter[1]: Pointer returned from malloc check
Type[1]: void *
Explanation:

This function asserts that the pointer (Parameter[1]) was allocated from malloc checking.

Note:

Unless you are doing something special, or using a builtin Ustr_pool it is very likely you want to just call USTR_CNTL_MALLOC_CHECK_MEM_USTR().

Function: USTR_CNTL_MALLOC_CHECK_MEM_SZ()
Returns: Success or failure
Type: int
Parameter[1]: Pointer returned from malloc check
Type[1]: void *
Parameter[2]: Length of allocated memory
Type[2]: size_t
Explanation:

This function asserts that the pointer (Parameter[1]) was allocated from malloc checking, and has the specified size (Parameter[2]).

Note:

Unless you are doing something special, or using a builtin Ustr_pool it is very likely you want to just call USTR_CNTL_MALLOC_CHECK_MEM_USTR().

Function: USTR_CNTL_MALLOC_CHECK_MEM_MINSZ()
Returns: Success or failure
Type: int
Parameter[1]: Pointer returned from malloc check
Type[1]: void *
Parameter[2]: Length of allocated memory
Type[2]: size_t
Explanation:

This function asserts that the pointer (Parameter[1]) was allocated from malloc checking, and has at least the specified size (Parameter[2]).

Note:

Unless you are doing something special, or using a builtin Ustr_pool it is very likely you want to just call USTR_CNTL_MALLOC_CHECK_MEM_USTR().

Function: USTR_CNTL_MALLOC_CHECK_MEM_USTR()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a Ustr string
Type[1]: Ustr *
Explanation:

This function asserts that the pointer (Parameter[1]) is a Ustr allocated from malloc checking, if the Ustr is allocated (if not it returns TRUE).

Note:

Because of the layering between the Ustr code and the pool code, if you allocate an implicity sized Ustrp from a pool and then delete some data from it (which fails) the Ustr layer will think it has an implicit less than the actual size so this function will fail. This is what USTR_CNTL_MALLOC_CHECK_MEM_USTRP() is for.

Function: USTR_CNTL_MALLOC_CHECK_MEM_USTRP()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a Ustrp string
Type[1]: Ustrp *
Explanation:

This function asserts that the pointer (Parameter[1]) is a Ustr allocated from a builtin pool using malloc checking, if the Ustr is allocated (if not it returns TRUE).

Function: USTR_CNTL_MALLOC_CHECK_END()
Returns: Success or failure
Type: int
Parameter[1]: Nothing
Type[1]: void
Explanation:

This macro will cleanup any memory used by malloc check, and assert that no memory is left allocated.

Note:

If any memory is left allocated, each one found is output to stderr with the file/line/function of the level it was allocated from.

Function: USTR_CNTL_MALLOC_CHECK_ADD()
Returns: Success or failure
Type: int
Parameter[1]: Condition to begin malloc checking or not
Type[1]: int
Explanation:

This function works like USTR_CNTL_MALLOC_CHECK_END() but it fails if the condition check (Parameter[1]) fails, or if USTR_CNTL_MALLOC_CHECK_LVL() is zero.

Function: USTR_CNTL_MALLOC_CHECK_DEL()
Returns: Success or failure
Type: int
Parameter[1]: Condition to end malloc checking or not
Type[1]: int
Explanation:

This function works like USTR_CNTL_MALLOC_CHECK_END() but it fails if the condition check (Parameter[1]) fails, or if USTR_CNTL_MALLOC_CHECK_LVL() is one.

Note:

The condition (Parameter[1]) to this macro should almost certainly be the return value from USTR_CNTL_MALLOC_CHECK_ADD().

Creating allocated Ustr functions

Function: ustr_init_size()
Returns: Size that needs to be allocated
Type: size_t
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: Length of data in the Ustr
Type[4]: size_t
Explanation:

This function finds out the exact size of memory needed to store the specified Ustr of the given configuration.

Function: ustr_init_alloc()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Pointer to area of memory to use as a Ustr string
Type[1]: void *
Parameter[2]: Size of area of memory
Type[2]: size_t
Parameter[3]: Whether Ustr should store the size
Type[3]: size_t
Parameter[4]: Number of bytes to use for references
Type[4]: size_t
Parameter[5]: Whether the Ustr should use exact allocations
Type[5]: int
Parameter[6]: Whether the Ustr should have the "enomem" flag set
Type[6]: int
Parameter[7]: The initial length of the Ustr
Type[7]: size_t
Explanation:

This creates a new Ustr string, you should have allocated the data via. USTR_CONF_MALLOC() or bad things will happen if the Ustr string is ever free'd or reallocated.

Function: ustr_dupx_empty()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocation flag
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Explanation:

This function creates an empty Ustr, owned by you, that is allocated from system memory, or it returns NULL.

The size is the desired allocation size for the entire Ustr, including overhead for metadata. This value will be rounded up, if it's too small, so passing 1 as the size means you want a stored size but to allocate the smallest amount of memory possible.

The exact memory allocation flag says if the Ustr should round allocations up to the nearest half power of two or should be no more than needed.

The ENOMEM memory error flag sets the iniital state of the user visible flag for memory allocation errors. Eg. ustr_enomem(), ustr_setf_enomem_clr() and ustr_setf_enomem_err()

Note:

The reference byte count can only be one of the following values: 0, 1, 2 or 4, or 8 (on environments with a 64bit size_t).

It can be useful to ensure that the Ustr is in system memory, so that you can add things to it and check for errors with ustr_enomem().

If you chose to store the allocated size in the Ustr then the number of bytes allocated for the reference count will be a minimum of 2.

Function: ustr_dup_empty()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Nothing
Type[1]: void
Explanation:

This function is the same as calling ustr_dupx_empty() with the current set of default options.

Function: ustr_dupx_undef()
Returns: Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: Length of new undefined data
Type[5]: size_t
Explanation:

This function works like you called ustr_dupx_empty() and then ustr_add_undef().

Function: ustr_dup_undef()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Length of new undefined data
Type[1]: size_t
Explanation:

This function is the same as calling ustr_dupx_undef() with the current set of default options.

Function: ustr_dup()
Returns: A pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function tries to increase the reference count on the passed Ustr string, and if that succeeds returns that as an argument. If that fails it tries creates a new Ustr string that looks identical to the old Ustr string, apart from the reference count.

Note:

Because the new Ustr string is configured identically to the old Ustr string this means the result can be very different to what you get if you call ustr_dup_buf() with ustr_cstr() and ustr_len() from the original string where the configuration would be whatever the default is.

Esp. worth of note is that if you ustr_dup() a Ustr string with an explicit size of 900 but a length of 1, and the reference count is full the returned Ustr string will have a size of 900 bytes and so will have allocated a little over that. ustr_dup_buf(), even with a sized configuration would only allocate about 12 bytes and have a size a little less than that.

Function: ustr_dupx()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: Pointer to a constant Ustr string
Type[5]: const struct Ustr *
Explanation:

This function tries to add a reference if the value of the size, reference bytes, exact memory allocations and ENOMEM are the same as those in the passed Ustr string (Parameter[5]). If the comparison fails or the addition of a reference fails it works like ustr_dupx_buf() using ustr_cstr() and ustr_len().

Function: ustr_sc_dup()
Returns: A pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function works like calling ustr_dup(), but if the reference count is maxed out then and so a new Ustr string has been allocated then that is stored in the passed argument (Parameter[1]) and the "old" Ustr string is returned.

Note:

The reason to use this is that if you have a "main" Ustr string pointer that a lot of things are getting references too then when the reference count maxes out you'll degrade into worst case behaviour which acts as though there are no reference counts. This function stops that problem.

As an example, if you have a 1 byte reference count and have 255 * 2 references then using ustr_dup() will create 256 Ustr strings using this function will create 4 Ustr strings.

Function: ustr_sc_dupx()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: A pointer to a pointer to a Ustr string
Type[5]: struct Ustr **
Explanation:

This function works like calling ustr_dupx(), but if the reference count is maxed out then and so a new Ustr string is allocated then that is stored in the passed argument (Parameter[1]) and the "old" Ustr string is returned.

If the configurations of the new Ustr string and the old Ustr string are not the same, this function works identically to ustr_dupx().

Note:

The reason to use this is that if you have a "main" Ustr string pointer that a lot of things are getting references too then when the reference count maxes out you'll degrade into worst case behaviour which acts as though there are no reference counts. This function stops that problem.

As an example, if you have a 1 byte reference count and have 255 * 2 references then using ustr_dupx() will create 256 Ustr strings using this function will create 4 Ustr strings.

Function: ustr_dup_buf()
Returns: A pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Pointer to data
Type[1]: const void *
Parameter[2]: Length of data
Type[2]: size_t
Explanation:

This function works as if you had called ustr_dup_undef() and then copied the data into the new undefined space.

Function: ustr_dupx_buf()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: Pointer to data
Type[5]: const void *
Parameter[6]: Length of data
Type[6]: size_t
Explanation:

This function works as if you had called ustr_dupx_undef() and then copied the data into the new undefined space.

Function: ustr_dup_cstr()
Returns: A pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Pointer to constant C-style string
Type[1]: const char *
Explanation:

This function works as if you had called ustr_dup_buf() and passed strlen() as the length.

Function: ustr_dupx_cstr()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: Pointer to constant C-style string
Type[5]: const char *
Explanation:

This function works as if you had called ustr_dupx_buf() and passed strlen() as the length.

Function: USTR_DUP_OSTR()
Returns: A pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: A constant C-style string
Type[1]: const char []
Explanation:

This function works as if you had called ustr_dup_buf() and passed sizeof() - 1 as the length.

Function: USTR_DUP_OBJ()
Returns: A pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: A symbol
Type[1]: ...
Explanation:

This function works as if you had called ustr_dup_buf() and passed sizeof() as the length.

Note:

In most cases you'll want to use USTR_DUP_OSTR().

Function: ustr_dup_subustr()
Returns: A pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Position in the Ustr
Type[2]: size_t
Parameter[3]: Length to add from the Ustr
Type[3]: size_t
Explanation:

This function mostly works as if you had called ustr_dup_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be added.

Note:

If the position is 1 and the length is the length of the Ustr string then it just calls ustr_dup().

Function: ustr_dupx_subustr()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: A pointer to a constant Ustr string
Type[5]: const struct Ustr *
Parameter[6]: Position in the Ustr
Type[6]: size_t
Parameter[7]: Length to add from the Ustr
Type[7]: size_t
Explanation:

This function mostly works as if you had called ustr_dupx_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be added.

Note:

If the position is 1 and the length is the length of the Ustr string then it just calls ustr_dupx().

Function: ustr_dup_rep_chr()
Returns: A pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Byte value of data
Type[1]: char
Parameter[2]: Length of bytes as data
Type[2]: size_t
Explanation:

This function works as if you had called ustr_dup_undef() and then copied the byte value to each position.

Function: ustr_dupx_rep_chr()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: Byte value of data
Type[5]: char
Parameter[6]: Length of bytes as data
Type[6]: size_t
Explanation:

This function works as if you had called ustr_dupx_undef() and then copied the byte value to each position.

Function: ustr_sc_vjoin()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Separator to go between Ustr strings
Type[1]: const struct Ustr *
Parameter[2]: A pointer to the first constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: A pointer to the second constant Ustr string
Type[3]: const struct Ustr *
Parameter[4]: Variable argument list variable, from va_start()
Type[4]: va_list
Explanation:

This function works as if you called ustr_dup() on the first Ustr string (Parameter[2]), and then ustr_add() on the separator (Parameter[1]) followed by ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached.

Note:

This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually.

Function: ustr_sc_join()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Separator to go between Ustr strings
Type[1]: const struct Ustr *
Parameter[2]: A pointer to the first constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: A pointer to the second constant Ustr string
Type[3]: const struct Ustr *
Parameter[4]: Zero or more pointers to constant Ustr strings and then USTR_NULL
Type[4]: ...
Explanation:

This function calls va_start() to get a variable argument list and then calls ustr_sc_vjoin().

Note:

This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually.

Function: ustr_sc_vjoinx()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: Separator to go between Ustr strings
Type[5]: const struct Ustr *
Parameter[6]: A pointer to the first constant Ustr string
Type[6]: const struct Ustr *
Parameter[7]: A pointer to the second constant Ustr string
Type[7]: const struct Ustr *
Parameter[8]: Variable argument list variable, from va_start()
Type[8]: va_list
Explanation:

This function works as if you called ustr_dupx() on the first Ustr string (Parameter[2]), and then ustr_add() on the separator (Parameter[1]) followed by ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached.

Note:

This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually.

Function: ustr_sc_joinx()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: Separator to go between Ustr strings
Type[5]: const struct Ustr *
Parameter[6]: A pointer to the first constant Ustr string
Type[6]: const struct Ustr *
Parameter[7]: A pointer to the second constant Ustr string
Type[7]: const struct Ustr *
Parameter[8]: Zero or more pointers to constant Ustr strings and then USTR_NULL
Type[8]: ...
Explanation:

This function calls va_start() to get a variable argument list and then calls ustr_sc_vjoinx().

Function: ustr_sc_vconcat()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: A pointer to the first constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Variable argument list variable, from va_start()
Type[2]: va_list
Explanation:

This function works as if you called ustr_dup() on the first Ustr string (Parameter[1]), and then ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached.

Note:

This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually.

Function: ustr_sc_concat()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: A pointer to the first constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Zero or more pointers to constant Ustr strings and then USTR_NULL
Type[2]: ...
Explanation:

This function calls va_start() to get a variable argument list and then calls ustr_sc_vconcat().

Function: ustr_sc_vconcatx()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: A pointer to the first constant Ustr string
Type[5]: const struct Ustr *
Parameter[6]: Variable argument list variable, from va_start()
Type[6]: va_list
Explanation:

This function works as if you called ustr_dupx() on the first Ustr string (Parameter[1]), and then ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached.

Note:

This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually.

Function: ustr_sc_concatx()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: A pointer to the first constant Ustr string
Type[5]: const struct Ustr *
Parameter[6]: Zero or more pointers to constant Ustr strings and then USTR_NULL
Type[6]: ...
Explanation:

This function calls va_start() to get a variable argument list and then calls ustr_sc_vconcatx().

Deleting a Ustr, or data within a Ustr

Function: ustr_free()
Returns: Nothing
Type: void
Parameter[1]: Pointer to a Ustr
Type[1]: struct Ustr *
Explanation:

This function decrements the reference count on a Ustr, if there is one, and free's it if it is allocated and the reference count becomes zero.

Note:

This function does nothing if passed USTR_NULL.

Function: ustrp_free()
Returns: Nothing
Type: void
Parameter[1]: Pointer to a Ustr pool object
Type[1]: struct Ustr_pool *
Parameter[2]: Pointer to a Ustrp (pool allocated Ustr)
Type[2]: struct Ustrp *
Explanation:

This function works like ustr_free() but calls the pool_free member function of the Ustr_pool (Parameter[1]) instead of the ustr system free.

Function: ustr_sc_free()
Returns: Nothing
Type: void
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function calls ustr_free() and then sets the pointer (Parameter[1]) to USTR_NULL, which is a noop when passed to ustr_free(). This can be used to help prevent "double free" errors.

Note:

While the point to the pointer must be non-NULL, this function also accepts a NULL ustr and does nothing. So you can pass the same pointer to this function multiple times and only the first one will do anything.

Function: ustr_sc_free2()
Returns: Nothing
Type: void
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Pointer to a Ustr string
Type[2]: struct Ustr *
Explanation:

This function works like ustr_sc_free() but instead of setting the pointer (Parameter[1]) to USTR_NULL it sets it to the Ustr string (Parameter[2]).

Note:

While the point to the pointer must be non-NULL, this function also accepts a NULL ustr to be free'd and does nothing. So you can pass the same pointer to ustr_sc_free() and then this function safely.

The passed value (Parameter[2]) shouldn't be USTR_NULL, and in debugging mode the function will assert() that it isn't.

Function: ustr_sc_free_shared()
Returns: Nothing
Type: void
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function is a simple way to "free" a Ustr string that has been shared (ustr_shared() returns USTR_TRUE), normally ustr_free() is ignored on a shared Ustr string. It just calls ustr_setf_owner() and then ustr_sc_free().

Function: ustr_del()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Length to delete from the Ustr
Type[2]: size_t
Explanation:

This function deletes data from the end of Ustr, possibly re-sizing the Ustr at the same time.

Note:

The Ustr is never re-sized when the size is stored explicitly, so the pointer never changes.

Function: ustr_del_subustr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position in the Ustr
Type[2]: size_t
Parameter[3]: Length to delete from the Ustr
Type[3]: size_t
Explanation:

This function works like ustr_del() but can delete an arbitrary section of the Ustr.

Function: ustr_sc_del()
Returns: Nothing
Type: void
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function is like calling ustr_del() with ustr_len() as the length, however if that fails it does a ustr_free() and then sets the pointer to USTR("").

Note:

While the benifit is that you don't have to check for memory failure errors, if there is a memory failure and you have a non-default configuration the configuration will revert back to the default.

Adding data to a Ustr

Function: ustr_add_undef()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Length of new undefined data
Type[2]: size_t
Explanation:

The Ustr string is expanded (possibly reallocated) so that it can contain length (Parameter[2]) extra data, if the length is not zero the Ustr will be writable. Or it'll return USTR_FALSE (zero) on failure.

Function: ustr_add_buf()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Pointer to data
Type[2]: const void *
Parameter[3]: Length of data
Type[3]: size_t
Explanation:

This function works as if you had called ustr_add_undef() and then copied the data into the new undefined space.

Function: ustr_add_cstr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Pointer to constant C-style string
Type[2]: const char *
Explanation:

This function works as if you had called ustr_add_buf() and passed strlen() as the length.

Function: USTR_ADD_OSTR()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A constant C-style string
Type[2]: const char []
Explanation:

This function works as if you had called ustr_add_buf() and passed sizeof() - 1 as the length.

Function: USTR_ADD_OBJ()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A symbol
Type[2]: ...
Explanation:

This function works as if you had called ustr_add_buf() and passed sizeof() as the length.

Note:

In most cases you'll want to use USTR_ADD_OSTR().

Function: ustr_add()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function mostly works as if you had called ustr_add_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added.

Note:

If the Ustr string is zero length and isn't writable this function may just add a reference, this is fine for Ustr strings that are "constant" because if the Ustr is read-only then the memory will not be written to.

Function: ustr_add_subustr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to add from the Ustr
Type[4]: size_t
Explanation:

This function mostly works as if you had called ustr_add_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be added. The exception being if you add a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr, but this function just works.

Note:

If the position is 1 and the length is the length of the Ustr string then it just calls ustr_add().

Function: ustr_add_rep_chr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Byte value of data
Type[2]: char
Parameter[3]: Length of bytes as data
Type[3]: size_t
Explanation:

This function works as if you had called ustr_add_undef() and then copied the byte value to each position.

Setting a Ustr to some data

Function: ustr_set_undef()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: size_t
Type[2]: size_t
Explanation:

This function works as if you had called ustr_del() for the entire string and the ustr_add_undef().

Function: ustr_set_empty()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function works as if you had called ustr_del() for the entire string, however the string will be allocated if this completes.

Function: ustr_set_buf()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Buffer containting data
Type[2]: const void *
Parameter[3]: Length of Buffer
Type[3]: size_t
Explanation:

This function works as if you had called ustr_del() for the entire string and the ustr_add_buf().

Function: ustr_set_cstr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Explanation:

This function works as if you had called ustr_del() for the entire string and then ustr_add_cstr().

Function: USTR_SET_OSTR()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A constant C-style string
Type[2]: const char []
Explanation:

This function works as if you had called ustr_del() for the entire string and then USTR_ADD_OSTR().

Function: USTR_SET_OBJ()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A symbol
Type[2]: ...
Explanation:

This function works as if you had called ustr_del() for the entire string and then USTR_ADD_OBJ().

Note:

In most cases you'll want to use USTR_SET_OSTR().

Function: ustr_set()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function works as if you had called ustr_del() for the entire string and the ustr_add().

Function: ustr_set_subustr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to set from the Ustr
Type[4]: size_t
Explanation:

This function works as if you had called ustr_del() for the entire string and the ustr_add_subustr(). The exception being if you set a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works.

Function: ustr_set_rep_chr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Byte value of data
Type[2]: char
Parameter[3]: Length of bytes as data
Type[3]: size_t
Explanation:

This function works as if you had called ustr_del() for the entire string and the ustr_add_rep_chr().

Inserting data into a Ustr

Function: ustr_ins_undef()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[3]: Length of new undefined data
Type[3]: size_t
Explanation:

The Ustr string is expanded (possibly reallocated) so that it can contain length (Parameter[2]) extra data, from after the required position. If the length is not zero the Ustr will be writable. Or it'll return USTR_FALSE (zero) on failure. The data in the Ustr is moved as needed to put the new data at position (Parameter[2]) + 1.

Function: ustr_ins_buf()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[3]: Pointer to data
Type[3]: const void *
Parameter[4]: Length of data
Type[4]: size_t
Explanation:

This function works as if you had called ustr_ins_undef() and then copied the data into the new undefined space.

Function: ustr_ins_cstr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[3]: Pointer to constant C-style string
Type[3]: const char *
Explanation:

This function works as if you had called ustr_ins_buf() and passed strlen() as the length.

Function: USTR_INS_OSTR()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[3]: A constant C-style string
Type[3]: const char []
Explanation:

This function works as if you had called ustr_ins_buf() and passed sizeof() - 1 as the length.

Function: USTR_INS_OBJ()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[3]: A symbol
Type[3]: ...
Explanation:

This function works as if you had called ustr_ins_buf() and passed sizeof() as the length.

Note:

In most cases you'll want to use USTR_INS_OSTR().

Function: ustr_ins()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string
Type[3]: const struct Ustr *
Explanation:

This function works as if you had called ustr_ins_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added.

Function: ustr_ins_subustr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to ins from the Ustr
Type[4]: size_t
Explanation:

This function mostly as if you had called ustr_ins_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be insed. The exception being if you insert a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works.

Function: ustr_ins_rep_chr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[2]: Byte value of data
Type[2]: char
Parameter[3]: Length of bytes as data
Type[3]: size_t
Explanation:

This function works as if you had called ustr_ins_undef() and then copied the byte value to each position.

Adding, duplicating and setting formatted data to a Ustr

Function: ustr_add_vfmt_lim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Limit of data to add
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string
Type[3]: const char *
Parameter[4]: Variable argument list variable, from va_start()
Type[4]: va_list
Explanation:

This function works like calling the system vsnprintf() with the limit (Parameter[2]) as the limit to vsnprintf() and then calling ustr_add_buf().

Function: ustr_add_vfmt()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Parameter[3]: Variable argument list variable, from va_start()
Type[3]: va_list
Explanation:

This function works like calling the system vsnprintf() and then calling ustr_add_buf().

Function: ustr_add_fmt_lim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Limit of data to add
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string
Type[3]: const char *
Parameter[4]: Options depending on value of Parameter[3]
Type[4]: ...
Explanation:

This function works like calling the system snprintf() with the limit (Parameter[2]) as the limit to snprintf() and then calling ustr_add_buf().

Function: ustr_add_fmt()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Parameter[3]: Options depending on value of Parameter[2]
Type[3]: ...
Explanation:

This function works like calling the system snprintf() and then calling ustr_add_buf().

Function: ustr_dup_vfmt_lim()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Limit of data to dup
Type[1]: size_t
Parameter[2]: Pointer to a constant Ustr string
Type[2]: const char *
Parameter[3]: Variable argument list variable, from va_start()
Type[3]: va_list
Explanation:

This function works like calling the system vsnprintf() with the limit (Parameter[2]) as the limit to vsnprintf() and then calling ustr_dup_buf().

Function: ustr_dup_vfmt()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Limit of data to dup
Type[1]: size_t
Parameter[2]: Pointer to a constant Ustr string
Type[2]: const char *
Parameter[3]: Variable argument list variable, from va_start()
Type[3]: va_list
Explanation:

This function works like calling the system vsnprintf() and then calling ustr_dup_buf().

Function: ustr_dup_fmt_lim()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Limit of data to dup
Type[1]: size_t
Parameter[2]: Pointer to a constant Ustr string
Type[2]: const char *
Parameter[3]: Options depending on value of Parameter[2]
Type[3]: ...
Explanation:

This function works like calling the system snprintf() with the limit (Parameter[2]) as the limit to snprintf() and then calling ustr_dup_buf().

Function: ustr_dup_fmt()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Pointer to a constant Ustr string
Type[1]: const char *
Parameter[2]: Options depending on value of Parameter[1]
Type[2]: ...
Explanation:

This function works like calling the system snprintf() and then calling ustr_dup_buf().

Function: ustr_dupx_fmt_lim()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: Limit of data to dup
Type[5]: size_t
Parameter[6]: Pointer to a constant Ustr string
Type[6]: const char *
Parameter[7]: Options depending on value of Parameter[6]
Type[7]: ...
Explanation:

This function works like calling the system snprintf() with the limit (Parameter[2]) as the limit to snprintf() and then calling ustr_dupx_buf().

Function: ustr_dupx_fmt()
Returns: Pointer to a Ustr string
Type: struct Ustr *
Parameter[1]: Size of allocated storage
Type[1]: size_t
Parameter[2]: Number of bytes to use for reference count
Type[2]: size_t
Parameter[3]: Exact memory allocations
Type[3]: int
Parameter[4]: ENOMEM, memory error flag
Type[4]: int
Parameter[5]: Pointer to a constant Ustr string
Type[5]: const char *
Parameter[6]: Options depending on value of Parameter[5]
Type[6]: ...
Explanation:

This function works like calling the system snprintf() and then calling ustr_dup_bufx().

Function: ustr_set_vfmt_lim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Limit of data to set
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string
Type[3]: const char *
Parameter[4]: Variable argument list variable, from va_start()
Type[4]: va_list
Explanation:

This function works like calling ustr_del() for all the data and then ustr_add_vfmt_lim().

Function: ustr_set_vfmt()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Parameter[3]: Variable argument list variable, from va_start()
Type[3]: va_list
Explanation:

This function works like calling ustr_del() for all the data and then ustr_add_vfmt().

Function: ustr_set_fmt_lim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Limit of data to set
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string
Type[3]: const char *
Parameter[4]: Options depending on value of Parameter[3]
Type[4]: ...
Explanation:

This function works like calling ustr_del() for all the data and then ustr_add_fmt_lim().

Function: ustr_set_fmt()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Parameter[3]: Options depending on value of Parameter[2]
Type[3]: ...
Explanation:

This function works like calling ustr_del() for all the data and then ustr_add_fmt().

Function: ustr_ins_vfmt_lim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[3]: Limit of data to insert
Type[3]: size_t
Parameter[4]: A pointer to a constant C-style string
Type[4]: const char *
Parameter[5]: Variable argument list variable, from va_start()
Type[5]: va_list
Explanation:

This function works like calling the system vsnprintf() with the limit (Parameter[3]) as the limit to vsnprintf() and then calling ustr_ins_buf().

Function: ustr_ins_vfmt()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string
Type[3]: const char *
Parameter[4]: Variable argument list variable, from va_start()
Type[4]: va_list
Explanation:

This function works like calling the system vsnprintf() and then calling ustr_ins_buf().

Function: ustr_ins_fmt_lim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[3]: Limit of data to insert
Type[3]: size_t
Parameter[4]: A pointer to a constant C-style string
Type[4]: const char *
Parameter[5]: Options depending on value of Parameter[4]
Type[5]: ...
Explanation:

This function works like calling the system snprintf() with the limit (Parameter[3]) as the limit to snprintf() and then calling ustr_ins_buf().

Function: ustr_ins_fmt()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position after which the data should be added
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string
Type[3]: const char *
Parameter[4]: Options depending on value of Parameter[3]
Type[4]: ...
Explanation:

This function works like calling the system snprintf() and then calling ustr_ins_buf().

Function: ustr_sub_vfmt_lim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Limit of data to substitute
Type[3]: size_t
Parameter[4]: A pointer to a constant C-style string
Type[4]: const char *
Parameter[5]: Variable argument list variable, from va_start()
Type[5]: va_list
Explanation:

This function works like calling the system vsnprintf() with the limit (Parameter[3]) as the limit to vsnprintf() and then calling ustr_sub_buf().

Function: ustr_sub_vfmt()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string
Type[3]: const char *
Parameter[4]: Variable argument list variable, from va_start()
Type[4]: va_list
Explanation:

This function works like calling the system vsnprintf() and then calling ustr_sub_buf().

Function: ustr_sub_fmt_lim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Limit of data to substitute
Type[3]: size_t
Parameter[4]: A pointer to a constant C-style string
Type[4]: const char *
Parameter[5]: Options depending on value of Parameter[4]
Type[5]: ...
Explanation:

This function works like calling the system snprintf() with the limit (Parameter[3]) as the limit to snprintf() and then calling ustr_sub_buf().

Function: ustr_sub_fmt()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string
Type[3]: const char *
Parameter[4]: Options depending on value of Parameter[3]
Type[4]: ...
Explanation:

This function works like calling the system snprintf() and then calling ustr_sub_buf().

Function: ustr_sc_sub_vfmt_lim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: Limit of data to substitute
Type[4]: size_t
Parameter[5]: A pointer to a constant C-style string
Type[5]: const char *
Parameter[6]: Variable argument list variable, from va_start()
Type[6]: va_list
Explanation:

This function works like calling the system vsnprintf() with the limit (Parameter[4]) as the limit to vsnprintf() and then calling ustr_sc_sub_buf().

Function: ustr_sc_sub_vfmt()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: A pointer to a constant C-style string
Type[4]: const char *
Parameter[5]: Variable argument list variable, from va_start()
Type[5]: va_list
Explanation:

This function works like calling the system vsnprintf() and then calling ustr_sc_sub_buf().

Function: ustr_sc_sub_fmt_lim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: Limit of data to substitute
Type[4]: size_t
Parameter[5]: A pointer to a constant C-style string
Type[5]: const char *
Parameter[6]: Options depending on value of Parameter[5]
Type[6]: ...
Explanation:

This function works like calling the system snprintf() with the limit (Parameter[3]) as the limit to snprintf() and then calling ustr_sc_sub_buf().

Function: ustr_sc_sub_fmt()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: A pointer to a constant C-style string
Type[4]: const char *
Parameter[5]: Options depending on value of Parameter[5]
Type[5]: ...
Explanation:

This function works like calling the system snprintf() and then calling ustr_sc_sub_buf().

Accessing the "variables" of a Ustr

Function: ustr_len()
Returns: The length of the Ustr
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function returns the length of the data within the Ustr, much like strlen() but without getting the value wrong in the case of extra NIL bytes.

Function: ustr_cstr()
Returns: Read-only pointer to the start of data in the Ustr
Type: const char *
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function returns a read-only pointer to the start of the data of the Ustr string. Due to there always being a terminating NIL byte in a Ustr, this is also a valid C-style string.

Function: ustr_wstr()
Returns: Writable pointer to the start of data in the Ustr, or NULL
Type: char *
Parameter[1]: A pointer to a constant Ustr string
Type[1]: struct Ustr *
Explanation:

This function returns a writable pointer to the start of the data of the Ustr string. Due to there always being a terminating NIL byte in a Ustr, this is also a valid C-style string.

If the ustr is read-only (ustr_ro() == USTR_TRUE) then this function will return NULL.

Note:

Unless the string is owned (ustr_owner() == USTR_TRUE) it can be a very bad idea to use this to change data, as then all references will be updated. See ustr_sc_wstr().

Function: ustr_alloc()
Returns: A boolean flag of either USTR_TRUE or USTR_FALSE
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function says if the Ustr is currently in allocated storage.

Function: ustr_exact()
Returns: A boolean flag of either USTR_TRUE or USTR_FALSE
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function says if the Ustr is doing exact allocations, so as the Ustr grows it will only have storage allocated exactly as required and not in half powers of two.

Note:

This will always be USTR_FALSE for read-only Ustr strings (ustr_ro() == USTR_TRUE), even though the default may be to used exact sized allocations when adding data to them etc.

Function: ustr_sized()
Returns: A boolean flag of either USTR_TRUE or USTR_FALSE
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function says if the Ustr stores an explicit allocation size, if not the size is implied as the next highest half power of two.

Function: ustr_ro()
Returns: A boolean flag of either USTR_TRUE or USTR_FALSE
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function says if the Ustr is current in read-only storage.

Read-only storage is not writable but can be referenced via. ustr_dup() an infinite amount of times.

Function: ustr_fixed()
Returns: A boolean flag of either USTR_TRUE or USTR_FALSE
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function says if the Ustr is current in fixed size storage.

Fixed size storage is writable but cannot be referenced.

Note:

Fixed size storage always explicitly stores the size of the storage.

Function: ustr_enomem()
Returns: A boolean flag of either USTR_TRUE or USTR_FALSE
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function just returns the value of the user settable flag in the Ustr. It can be set via. ustr_setf_enomem_err() and cleared by ustr_setf_enomem_clr().

This function is automatically set to on whever a memory allocation failure happens for a Ustr.

Note:

If a Ustr is referenced multiple times, ustr_setf_enomem_err() will fail.

This always fails for Ustr's in read-only storage.

Function: ustr_shared()
Returns: A boolean flag of either USTR_TRUE or USTR_FALSE
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function says if the Ustr is in the "shared" mode. It can be set via. ustr_setf_shared() and cleared by ustr_setf_owner() on allocated Ustr's.

Shared mode means that a Ustr can be referenced and unreferenced an infinite number of times.

Note:

This always succeeds for Ustr's in read-only storage.

This always fails for Ustr's in fixed size storage.

Function: ustr_limited()
Returns: A boolean flag of either USTR_TRUE or USTR_FALSE
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function says if the Ustr is currently in fixed size storage and cannot move to allocated storage.

Note:

This always fails for Ustr's in allocated storage.

This always fails for Ustr's in read-only storage.

Function: ustr_owner()
Returns: A boolean flag of either USTR_TRUE or USTR_FALSE
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function says if there is only a single reference to the Ustr string.

Note:

This always fails for Ustr's in read-only storage.

This always succeeds for Ustr's in fixed size storage.

Function: ustr_size()
Returns: size_t
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function calculates the maximum amount of data that could be stored (Ie. the max ustr_len()) without having to re-size the Ustr string.

Function: ustr_size_alloc()
Returns: size_t
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function returns the size of the storage for the Ustr.

Function: ustr_size_overhead()
Returns: size_t
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function returns the difference between the size of the storage and the maximum amount of data that could be stored without having to re-size the Ustr string.

Function: ustr_conf()
Returns: Nothing
Type: void
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Return size allocated number
Type[2]: size_t *
Parameter[3]: Return number of bytes used in the reference count
Type[3]: size_t *
Parameter[4]: Return exact allocations flag
Type[4]: int *
Parameter[5]: Return number of bytes used in the length
Type[5]: size_t *
Parameter[5]: Return number of references to this Ustr
Type[5]: size_t *
Explanation:

This function gives the configuration of the current Ustr needed to duplicate it via. the ustr_dupx_*() functions. It also gives the number of bytes used for the length and the number of references, which are mainly informational.

Note:

This function differs from calling the ustr_exact() etc. functions in that it returns the global options if this Ustr isn't allocated, thus telling you what the configuration would be if the Ustr was turned into an allocated Ustr by adding data etc.

Zero references for an allocated Ustr with a non-zero number of bytes for a reference count means it's in "shared" mode).

Setting the "flags" of a Ustr

Function: ustr_setf_enomem_err()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a Ustr string
Type[1]: struct Ustr *
Explanation:

This function sets the enomem flag, which can be observed via. the ustr_enomem() function.

The implication of setting this flag is that a memory error has occured in a previous function call on this Ustr.

Note:

This function fails if ustr_owner() fails for the Ustr.

Function: ustr_setf_enomem_clr()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a Ustr string
Type[1]: struct Ustr *
Explanation:

This function clears the enomem flag, which can be observed via. the ustr_enomem() function.

The implication of this flag being set is that a memory error has occured in a previous function call on this Ustr, so on clearing the flag you should know you have brought the Ustr back to a known state.

Note:

This function fails if ustr_owner() fails for the Ustr.

Function: ustr_setf_share()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a Ustr string
Type[1]: struct Ustr *
Explanation:

This function sets the shared mode, which can be observed via. the ustr_shared() function.

This is used on a Ustr so that it can have more references than it is able to hold in it's reference count. After this call the Ustr can be referenced and unreferenced an infinite number of times.

Note:

After this call the Ustr will never be deleted until ustr_setf_owner() is called.

This function fails if ustr_alloc() fails for the Ustr.

Function: ustr_setf_owner()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a Ustr string
Type[1]: struct Ustr *
Explanation:

This function removes the shared mode, which can be observed via. the ustr_shared() function.

This is used so that a Ustr in shared mode can be free'd.

Note:

This function fails if ustr_alloc() fails for the Ustr.

Comparing data in a Ustr

Function: ustr_cmp_buf()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to constant bytes, to compare
Type[2]: const void *
Parameter[3]: Length of comparison bytes
Type[3]: size_t
Explanation:

This function works like memcmp() on the Ustr and the passed data.

Function: ustr_cmp()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function works like ustr_cmp_buf() but with the data from ustr_cstr() and the length from ustr_len().

Function: ustr_cmp_subustr()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to compare from the Ustr
Type[4]: size_t
Explanation:

This function works like ustr_cmp() but with a limit on the data and length.

Function: ustr_cmp_cstr()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Explanation:

This function works like ustr_cmp_buf() but with a length from strlen().

Function: ustr_cmp_fast_buf()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to constant bytes, to compare
Type[2]: const void *
Parameter[3]: Length of comparison bytes
Type[3]: size_t
Explanation:

This function works like ustr_cmp_buf() but the order of comparison is optimized for speed, but is much less friendly to humans.

Function: ustr_cmp_fast()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function works like ustr_cmp_fast_buf() but with the data from ustr_cstr() and the length from ustr_len().

Function: ustr_cmp_fast_subustr()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to compare from the Ustr
Type[4]: size_t
Explanation:

This function works like ustr_cmp_fast() but with a limit on the data and length.

Function: ustr_cmp_fast_cstr()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Explanation:

This function works like ustr_cmp_fast_buf() but with a length from strlen().

Function: ustr_cmp_case_buf()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to constant bytes, to compare
Type[2]: const void *
Parameter[3]: Length of comparison bytes
Type[3]: size_t
Explanation:

This function works like ustr_cmp_buf() but the order of comparison ignores ASCII case.

Function: ustr_cmp_case()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function works like ustr_cmp_case_buf() but with the data from ustr_cstr() and the length from ustr_len().

Function: ustr_cmp_case_subustr()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to compare from the Ustr
Type[4]: size_t
Explanation:

This function works like ustr_cmp_case() but with a limit on the data and length.

Function: ustr_cmp_case_cstr()
Returns: Less then zero, zero or greater than zero depending on comparison
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Explanation:

This function works like ustr_cmp_case_buf() but with a length from strlen().

Function: ustr_cmp_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function works like comparing ustr_cmp() against 0.

Function: ustr_cmp_buf_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to constant bytes, to compare
Type[2]: const void *
Parameter[3]: Length of comparison bytes
Type[3]: size_t
Explanation:

This function works like comparing ustr_cmp_buf() against 0.

Function: ustr_cmp_subustr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to compare from the Ustr
Type[4]: size_t
Explanation:

This function works like comparing ustr_cmp_subustr() against 0.

Function: ustr_cmp_cstr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Explanation:

This function works like comparing ustr_cmp_cstr() against 0.

Function: ustr_cmp_case_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function works like comparing ustr_cmp_case() against 0.

Function: ustr_cmp_case_buf_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to constant bytes, to compare
Type[2]: const void *
Parameter[3]: Length of comparison bytes
Type[3]: size_t
Explanation:

This function works like comparing ustr_cmp_case_buf() against 0.

Function: ustr_cmp_case_subustr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to compare from the Ustr
Type[4]: size_t
Explanation:

This function works like comparing ustr_cmp_case_subustr() against 0.

Function: ustr_cmp_case_cstr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Explanation:

This function works like comparing ustr_cmp_case_cstr() against 0.

Function: ustr_cmp_prefix_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function works like comparing ustr_cmp() against 0, but the comparison is limited to the length of the right hand side.

Function: ustr_cmp_prefix_buf_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to constant bytes, to compare
Type[2]: const void *
Parameter[3]: Length of comparison bytes
Type[3]: size_t
Explanation:

This function works like comparing ustr_cmp_buf() against 0, but the comparison is limited to the length of the right hand side (Parameter[3]).

Function: ustr_cmp_prefix_cstr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Explanation:

This function works like comparing ustr_cmp_cstr() against 0, but the comparison is limited to the length of the right hand side.

Function: ustr_cmp_prefix_subustr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to compare from the Ustr
Type[4]: size_t
Explanation:

This function works like comparing ustr_cmp_subustr() against 0, but the comparison is limited to the given length (Parameter[4]).

Function: ustr_cmp_case_prefix_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function works like comparing ustr_cmp_case() against 0, but the comparison is limited to the length of the right hand side.

Function: ustr_cmp_case_prefix_buf_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to constant bytes, to compare
Type[2]: const void *
Parameter[3]: Length of comparison bytes
Type[3]: size_t
Explanation:

This function works like comparing ustr_cmp_case_buf() against 0, but the comparison is limited to the length of the right hand side (Parameter[3]).

Function: ustr_cmp_case_prefix_cstr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Explanation:

This function works like comparing ustr_cmp_case_cstr() against 0, but the comparison is limited to the length of the right hand side.

Function: ustr_cmp_case_prefix_subustr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to compare from the Ustr
Type[4]: size_t
Explanation:

This function works like comparing ustr_cmp_case_subustr() against 0, but the comparison is limited to the given length (Parameter[4]).

Function: ustr_cmp_suffix_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function works like ustr_cmp_prefix_eq() but compares the end of the left hand side.

Function: ustr_cmp_suffix_buf_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to constant bytes, to compare
Type[2]: const void *
Parameter[3]: Length of comparison bytes
Type[3]: size_t
Explanation:

This function works like ustr_cmp_prefix_buf_eq() but compares the end of the left hand side.

Function: ustr_cmp_suffix_cstr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Explanation:

This function works like ustr_cmp_prefix_cstr_eq() but compares the end of the left hand side.

Function: ustr_cmp_suffix_subustr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to compare from the Ustr
Type[4]: size_t
Explanation:

This function works like comparing ustr_cmp_subustr() against 0, but compares the end of the left hand side.

Function: ustr_cmp_case_suffix_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Explanation:

This function works like ustr_cmp_case_prefix_eq() but compares the end of the left hand side.

Function: ustr_cmp_case_suffix_buf_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to constant bytes, to compare
Type[2]: const void *
Parameter[3]: Length of comparison bytes
Type[3]: size_t
Explanation:

This function works like ustr_cmp_case_prefix_buf_eq() but compares the end of the left hand side.

Function: ustr_cmp_case_suffix_cstr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant C-style string
Type[2]: const char *
Explanation:

This function works like ustr_cmp_case_prefix_cstr_eq() but compares the end of the left hand side.

Function: ustr_cmp_case_suffix_subustr_eq()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to compare from the Ustr
Type[4]: size_t
Explanation:

This function works like comparing ustr_cmp_case_subustr() against 0, but compares the end of the left hand side.

Searching for data in a Ustr

Function: ustr_srch_chr_fwd()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: Byte data to search for
Type[3]: char
Explanation:

This function searches for the data (Parameter[3]) in the Ustr, skipping an offset (Parameter[2]) number of bytes.

Function: ustr_srch_chr_rev()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: Byte data to search for
Type[3]: char
Explanation:

This function works like ustr_srch_chr_fwd() but it searches from the end of the string to the beginning.

Note:

The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length.

Function: ustr_srch_buf_fwd()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to data to search for
Type[3]: const void *
Parameter[4]: Length of the data to search for
Type[4]: size_t
Explanation:

This function searches for the data (Parameter[3]) of length (Parameter[4]) in the Ustr, skipping an offset (Parameter[2]) number of bytes.

Function: ustr_srch_buf_rev()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to data to search for
Type[3]: const void *
Parameter[4]: Length of the data to search for
Type[4]: size_t
Explanation:

This function works like ustr_srch_buf_fwd() but it searches from the end of the string to the beginning.

Note:

The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length.

Function: ustr_srch_fwd()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string, to search for
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_srch_buf_fwd() but it gets the data pointer by calling ustr_cstr() and the length by calling ustr_len() on the passed Ustr (Parameter[3]).

Function: ustr_srch_rev()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string, to search for
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_srch_fwd() but it searches from the end of the string to the beginning.

Note:

The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length.

Function: ustr_srch_cstr_fwd()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to C-style string data, to search for
Type[3]: const char *
Explanation:

This function works like ustr_srch_buf_fwd() but it gets the length by calling strlen() on the passed data (Parameter[3]).

Function: ustr_srch_cstr_rev()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to C-style string data, to search for
Type[3]: const char *
Explanation:

This function works like ustr_srch_cstr_fwd() but it searches from the end of the string to the beginning.

Note:

The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length.

Function: ustr_srch_subustr_fwd()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string
Type[3]: const struct Ustr *
Parameter[4]: Position in the Ustr
Type[4]: size_t
Parameter[5]: Length of data to search, from the Ustr
Type[5]: size_t
Explanation:

This function works like ustr_srch_fwd() but it moves the data to start at the correct position and limits the length to the value specified.

Function: ustr_srch_subustr_rev()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string
Type[3]: const struct Ustr *
Parameter[4]: Position in the Ustr
Type[4]: size_t
Parameter[5]: Length of data to search, from the Ustr
Type[5]: size_t
Explanation:

This function works like ustr_srch_rev() but it moves the data to start at the correct position and limits the length to the value specified.

Note:

The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length.

Function: ustr_srch_case_chr_fwd()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: Byte data to search for
Type[3]: char
Explanation:

This function works like ustr_srch_chr_fwd(), but treats ASCII uppercase and lowercase as equivalent.

Function: ustr_srch_case_chr_rev()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: Byte data to search for
Type[3]: char
Explanation:

This function works like ustr_srch_chr_fwd(), but treats ASCII uppercase and lowercase as equivalent.

Function: ustr_srch_case_buf_fwd()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to data to search for
Type[3]: const void *
Parameter[4]: Length of the data to search for
Type[4]: size_t
Explanation:

This function works like ustr_srch_buf_fwd(), but treats ASCII uppercase and lowercase as equivalent.

Function: ustr_srch_case_buf_rev()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to data to search for
Type[3]: const void *
Parameter[4]: Length of the data to search for
Type[4]: size_t
Explanation:

This function works like ustr_srch_buf_rev(), but treats ASCII uppercase and lowercase as equivalent.

Function: ustr_srch_case_fwd()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string, to search for
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_srch_fwd(), but treats ASCII uppercase and lowercase as equivalent.

Function: ustr_srch_case_rev()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string, to search for
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_srch_rev(), but treats ASCII uppercase and lowercase as equivalent.

Function: ustr_srch_case_cstr_fwd()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to C-style string data, to search for
Type[3]: const char *
Explanation:

This function works like ustr_srch_cstr_fwd(), but treats ASCII uppercase and lowercase as equivalent.

Function: ustr_srch_case_cstr_rev()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to C-style string data, to search for
Type[3]: const char *
Explanation:

This function works like ustr_srch_cstr_rev(), but treats ASCII uppercase and lowercase as equivalent.

Function: ustr_srch_case_subustr_fwd()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string
Type[3]: const struct Ustr *
Parameter[4]: Position in the Ustr
Type[4]: size_t
Parameter[5]: Length of data to search, from the Ustr
Type[5]: size_t
Explanation:

This function works like ustr_srch_subustr_fwd(), but treats ASCII uppercase and lowercase as equivalent.

Function: ustr_srch_case_subustr_rev()
Returns: Position in the Ustr, or zero if not found
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start searching at
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string
Type[3]: const struct Ustr *
Parameter[4]: Position in the Ustr
Type[4]: size_t
Parameter[5]: Length of data to search, from the Ustr
Type[5]: size_t
Explanation:

This function works like ustr_srch_subustr_rev(), but treats ASCII uppercase and lowercase as equivalent.

Span lengths of data in a Ustr

Function: ustr_spn_chr_fwd()
Returns: Number of bytes in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start spanning from
Type[2]: size_t
Parameter[3]: Byte data
Type[3]: char
Explanation:

This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes.

Function: ustr_spn_chr_rev()
Returns: Number of bytes in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start spanning from
Type[2]: size_t
Parameter[3]: Byte data
Type[3]: char
Explanation:

This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes.

Function: ustr_spn_chrs_fwd()
Returns: Number of bytes in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start spanning from
Type[2]: size_t
Parameter[3]: Array of byte data, for spanning
Type[3]: const char *
Parameter[4]: Length of byte data, for spanning
Type[4]: size_t
Explanation:

This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes.

Function: ustr_spn_chrs_rev()
Returns: Number of bytes in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start spanning from
Type[2]: size_t
Parameter[3]: Array of byte data
Type[3]: const char *
Parameter[4]: Length of byte data
Type[4]: size_t
Explanation:

This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes.

Function: ustr_spn_fwd()
Returns: Number of bytes in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string, containing spanning bytes
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_spn_buf_fwd() but passing ustr_cstr() and ustr_len()

Function: ustr_spn_rev()
Returns: Number of bytes in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string, containing spanning bytes
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_spn_buf_rev() but passing ustr_cstr() and ustr_len()

Function: ustr_spn_cstr_fwd()
Returns: Number of bytes in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string, containing spanning bytes
Type[3]: const char *
Explanation:

This function works like ustr_spn_buf_fwd() but passing strlen() for the length.

Function: ustr_spn_cstr_rev()
Returns: Number of bytes in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string, containing spanning bytes
Type[3]: const char *
Explanation:

This function works like ustr_spn_buf_rev() but passing strlen() for the length.

Function: ustr_cspn_chr_fwd()
Returns: Number of bytes not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start compliment spanning from
Type[2]: size_t
Parameter[3]: Byte data
Type[3]: char
Explanation:

This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are not equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes.

Function: ustr_cspn_chr_rev()
Returns: Number of bytes not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start compliment spanning from
Type[2]: size_t
Parameter[3]: Byte data
Type[3]: char
Explanation:

This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are not equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes.

Function: ustr_cspn_chrs_fwd()
Returns: Number of bytes not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start compliment spanning from
Type[2]: size_t
Parameter[3]: Array of byte data
Type[3]: const char *
Parameter[4]: Length of byte data
Type[4]: size_t
Explanation:

This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are not equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes.

Function: ustr_cspn_chrs_rev()
Returns: Number of bytes not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start compliment spanning from
Type[2]: size_t
Parameter[3]: Array of byte data
Type[3]: const char *
Parameter[4]: Length of byte data
Type[4]: size_t
Explanation:

This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are not equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes.

Function: ustr_cspn_fwd()
Returns: Number of bytes not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start compliment spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string, containing spanning bytes
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_cspn_buf_fwd() but passing ustr_cstr() and ustr_len()

Function: ustr_cspn_rev()
Returns: Number of bytes not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start compliment spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string, containing spanning bytes
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_cspn_buf_rev() but passing ustr_cstr() and ustr_len()

Function: ustr_cspn_cstr_fwd()
Returns: Number of bytes not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start compliment spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string, containing spanning bytes
Type[3]: const char *
Explanation:

This function works like ustr_cspn_buf_fwd() but passing strlen() for the length.

Function: ustr_cspn_cstr_rev()
Returns: Number of bytes not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string, containing spanning bytes
Type[3]: const char *
Explanation:

This function works like ustr_cspn_buf_rev() but passing strlen() for the length.

Function: ustr_utf8_spn_chrs_fwd()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style UTF-8 string
Type[3]: const char *
Parameter[4]: Length of the C-style UTF-8 string
Type[4]: size_t
Explanation:

This function works like ustr_spn_chrs_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_spn_chrs_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes.

Function: ustr_utf8_spn_chrs_rev()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style UTF-8 string
Type[3]: const char *
Parameter[4]:
Type[4]: size_t
Explanation:

This function works like ustr_spn_chrs_rev() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_spn_chrs_rev() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes.

Function: ustr_utf8_spn_fwd()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr UTF-8 string
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_spn_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_spn_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes.

Function: ustr_utf8_spn_rev()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr UTF-8 string
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_spn_rev() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_spn_rev() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes.

Function: ustr_utf8_spn_cstr_fwd()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style UTF-8 string
Type[3]: const char *
Explanation:

This function works like ustr_spn_cstr_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_spn_cstr_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes.

Function: ustr_utf8_spn_cstr_rev()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style UTF-8 string
Type[3]: const char *
Explanation:

This function works like ustr_spn_cstr_rev() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_spn_cstr_rev() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes.

Function: ustr_utf8_cspn_chrs_fwd()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style UTF-8 string
Type[3]: const char *
Parameter[4]: Length of the C-style UTF-8 string
Type[4]: size_t
Explanation:

This function works like ustr_cspn_chrs_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_cspn_chrs_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes.

Function: ustr_utf8_cspn_chrs_rev()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style UTF-8 string
Type[3]: const char *
Parameter[4]: Length of the C-style UTF-8 string
Type[4]: size_t
Explanation:

This function works like ustr_cspn_chrs_rev() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_cspn_chrs_rev() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes.

Function: ustr_utf8_cspn_fwd()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr UTF-8 string, containing spanning data
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_cspn_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_cspn_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes.

Function: ustr_utf8_cspn_rev()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from
Type[2]: size_t
Parameter[3]: A pointer to constant Ustr UTF-8 string data, containing spanning data
Type[3]: const struct Ustr *
Explanation:

This function works like ustr_cspn_rev() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_cspn_rev() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes.

Function: ustr_utf8_cspn_cstr_fwd()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from
Type[2]: size_t
Parameter[3]: A pointer to constant C-style UTF-8 string data, containing spanning data
Type[3]: const char *
Explanation:

This function works like ustr_cspn_cstr_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_cspn_cstr_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes.

Function: ustr_utf8_cspn_cstr_rev()
Returns: Number of UTF-8 characters not in the span
Type: size_t
Parameter[1]: A pointer to a constant Ustr UTF-8 string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from
Type[2]: size_t
Parameter[3]: A pointer to C-style UTF-8 string data, containing spanning data
Type[3]: const char *
Explanation:

This function works like ustr_cspn_cstr_rev() but the return value, offset, and length all use UTF-8 characters and not bytes.

Note:

This is much slower than ustr_spn_cstr_rev() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes.

Doing IO from or to a Ustr

Function: ustr_io_get()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a C file object
Type[2]: FILE *
Parameter[3]: Number of bytes to read
Type[3]: size_t
Parameter[4]: Returned number of bytes read
Type[4]: size_t *
Explanation:

This function tries to read a minimum number of bytes from the file object, into the Ustr string. The exact number read is returned, unless (Parameter[4]) is NULL.

Function: ustr_io_getfile()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a C file object
Type[2]: FILE *
Explanation:

This function calls ustr_io_get() rpeatedly until EOF is encountered.

Note:

The errno value when this function ends could either be from fopen(), fread(), or if both of the those succeeded from fclose().

Function: ustr_io_getfilename()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A C-style string of a filename
Type[2]: const char *
Explanation:

This function opens a specified file, and then calls ustr_io_getfile(). Finally closing the FILE * object.

Function: ustr_io_getdelim()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a C file object
Type[2]: FILE *
Parameter[3]: A delimiter byte to stop reading at
Type[3]: char
Explanation:

This function reads bytes from the file until it hits the delimiter byte.

Note:

The delimiter is included, use ustr_del() to remove 1 byte from the end if you don't want it.

This function assumes a delimiter will happen every 80 bytes or so.

Function: ustr_io_getline()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a C file object
Type[2]: FILE *
Explanation:

This function works like calling ustr_io_getdelim() with '\n' as the delimiter.

Function: ustr_io_put()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a C file object
Type[2]: FILE *
Parameter[3]: Number of bytes to write
Type[3]: size_t
Explanation:

This function is the opposite of ustr_io_get(), taking bytes from the beginning of the Ustr and writting them to the file.

Note:

Deleting bytes from the begining of a Ustr string is the most inefficient thing to do, so it is recommended to use ustr_io_putfile().

Function: ustr_io_putline()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a C file object
Type[2]: FILE *
Parameter[3]: Number of bytes to write
Type[3]: size_t
Explanation:

This function works like calling ustr_io_put(), and then writting a '\n' to the file.

Note:

This doesn't write a line from the Ustr to the file, if you want that call ustr_io_put() directly, using the return from ustr_srch_chr_fwd() (with a '\n') as the number of bytes argument.

Function: ustr_io_putfile()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a C file object
Type[2]: FILE *
Explanation:

This function works like calling ustr_io_put() with ustr_len() as the number of bytes.

Function: ustr_io_putfileline()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a C file object
Type[2]: FILE *
Explanation:

This function works like calling ustr_io_putline() with ustr_len() as the number of bytes.

Function: ustr_io_putfilename()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A C-style string of a filename
Type[2]: const char *
Parameter[3]: A C-style string of a filemode (the second argument to fopen)
Type[3]: const char *
Explanation:

This function opens a specified file, and then calls ustr_io_putfile(). Finally closing the FILE * object.

Note:

The errno value when this function ends could either be from fopen(), fwrite(), or if both of the those succeeded from fclose().

String substitution/replacement

Function: ustr_sub_undef()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of undefined data
Type[3]: size_t
Explanation:

The Ustr string is expanded as required (possibly reallocated) so that it can contain length (Parameter[2]) data, from the required position. If the length is not zero the Ustr will be writable. Or it'll return USTR_FALSE (zero) on failure.

Note:

You can think of the operation as two seperate tasks, one which makes the current data in the Ustr undefined and the second which adds undefined data to the ustr to accomodate the desired length.

Function: ustr_sub_buf()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Buffer containing substitution string
Type[3]: const void *
Parameter[4]: Length of buffer
Type[4]: size_t
Explanation:

This function works as if you had called ustr_sub_undef() and then copied the data into the new undefined space.

Function: ustr_sub_cstr()
Returns: success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: A pointer to a constant C-style string, which is the substitution
Type[3]: const char *
Explanation:

This function works like ustr_sub_buf() but the length is worked out automatically by strlen().

Function: USTR_SUB_OSTR()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: A constant C-style string
Type[3]: const char []
Explanation:

This function works as if you had called ustr_sub_buf() and passed sizeof() - 1 as the length.

Function: USTR_SUB_OBJ()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: A symbol
Type[3]: ...
Explanation:

This function works as if you had called ustr_sub_buf() and passed sizeof() as the length.

Note:

In most cases you'll want to use USTR_SUB_OSTR().

Function: ustr_sub()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string
Type[3]: const struct Ustr *
Explanation:

This function works as if you had called ustr_sub_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added. The exception being if you substitute a ustr into itself, while only having a single reference count, the simple method could access a free'd ustr data, but this function just works.

Function: ustr_sub_subustr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: A pointer to a constant Ustr string
Type[3]: const struct Ustr *
Parameter[4]: Position in the Ustr
Type[4]: size_t
Parameter[5]: Length to substitute from the Ustr
Type[5]: size_t
Explanation:

This function mostly as if you had called ustr_sub_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be insed. The exception being if you insert a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works.

Function: ustr_sc_sub_undef()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: Length of undefined data
Type[4]: size_t
Explanation:

This function works as if you had done ustr_del_subustr() followed by ustr_ins_undef(), however it is significantly more efficient.

Function: ustr_sc_sub_buf()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: Buffer containting substitute data
Type[4]: const void *
Parameter[5]: Length of Buffer
Type[5]: size_t
Explanation:

This function will substitute a specific number of characters in a Ustr with the data from a buffer, this function does the job of one or more of ustr_add_buf(), ustr_sub_buf() and ustr_del().

Function: ustr_sc_sub_cstr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr
Type[1]: struct Ustr **
Parameter[2]: Position where to start replacement
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: A pointer to a constant C-style string, containing spanning bytes
Type[4]: const char *
Explanation:

This function works like ustr_sc_sub_buf() but the length is worked out automatically by strlen().

Function: ustr_sc_sub()
Returns: success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: Pointer to a Ustr containing the substitute string
Type[4]: const struct Ustr *
Explanation:

This function works as if you had called ustr_sc_sub_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added. The exception being if you substitute a ustr into itself, while only having a single reference count, the simple method could access a free'd ustr data, but this function just works.

Function: ustr_sc_sub_subustr()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: A pointer to a constant Ustr string
Type[4]: const struct Ustr *
Parameter[5]: Position in the Ustr
Type[5]: size_t
Parameter[6]: Length to substitute from the Ustr
Type[6]: size_t
Explanation:

This function mostly as if you had called ustr_sc_sub_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be insed. The exception being if you insert a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works.

Function: USTR_SC_SUB_OSTR()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: A constant C-style string
Type[4]: const char []
Explanation:

This function works as if you had called ustr_sc_sub_buf() and passed sizeof() - 1 as the length.

Function: USTR_SC_SUB_OBJ()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Position where to start substitution
Type[2]: size_t
Parameter[3]: Length of substitution
Type[3]: size_t
Parameter[4]: A symbol
Type[4]: ...
Explanation:

This function works as if you had called ustr_sc_sub_buf() and passed sizeof() as the length.

Note:

In most cases you'll want to use USTR_SUB_OSTR().

Function: ustr_replace_buf()
Returns: Number of tokens replaced
Type: size_t
Parameter[1]: Pointer to a pointer to a Ustr (haystack)
Type[1]: struct Ustr **
Parameter[2]: Buffer containting search data
Type[2]: const void *
Parameter[3]: Length of search buffer
Type[3]: size_t
Parameter[4]: Buffer containting replacement data
Type[4]: const void *
Parameter[5]: Length of replacement buffer
Type[5]: size_t
Parameter[6]: Maximum number of matches to replace (0 for unlimited)
Type[6]: size_t
Explanation:

This function scans the "haystack" (Parameter[1]) for "needle" (Parameter[2]) and replaces max_replacements (Parameter[6]) matches with the "replacement" (Parameter[4]).

Note:

If max_replacements (Parameter[6]) is 0, this function will replace ALL occurrences.

Function: ustr_replace_cstr()
Returns: Number of tokens replaced
Type: size_t
Parameter[1]: Pointer to a pointer to a Ustr (haystack)
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant C-style string, containing search bytes
Type[2]: const char *
Parameter[3]: A pointer to a constant C-style string, containing replacement bytes
Type[3]: const char *
Parameter[4]: Maximum number of matches to replace (0 for unlimited)
Type[4]: size_t
Explanation:

This function works like ustr_replace_buf() but gets the lengths for the buffer automatically from strlen().

Function: ustr_replace()
Returns: Number of tokens replaced
Type: int
Parameter[1]: Pointer to a pointer to a Ustr (haystack)
Type[1]: struct Ustr **
Parameter[2]: Ustr to search for (needle)
Type[2]: const struct Ustr *
Parameter[3]: Ustr to replace needle with
Type[3]: const struct Ustr *
Parameter[4]: Maximum number of matches to replace (0 for unlimited)
Type[4]: size_t
Explanation:

This function works like ustr_replace_buf() but gets the lengths from the ustr automatically.

Function: ustr_replace_rep_chr()
Returns: number of replacements made
Type: size_t
Parameter[1]: pointer to a pointer to a Ustr to be modified
Type[1]: struct Ustr **ps1
Parameter[2]: character to replace
Type[2]: char
Parameter[3]: number of characters to replace
Type[3]: size_t
Parameter[4]: character to replace with
Type[4]: char
Parameter[5]: number of characters to replace with
Type[5]: size_t nlen
Parameter[6]: maximum number of replacements to make (use 0 for unlimited)
Type[6]: size_t lim
Explanation:

This function replaces a repeating sequence of characters with another repeating sequence of characters. For example...

  Ustr *data = ustr_dup_cstr("xxxBxxCxDxxx");
  ustr_replace_rep_chr(&data,'x',2,'y',1, 0)

...would change data to be "yxByCxDyx".

Note:

Changing the same letter the same number of times is considered a No-op since it is a vast performance improvement this way. So passing in (&data,'y',2,'y',2 ,0) will have a return value of 0 and the string will be unchanged.

Splitting a Ustr

Function: ustr_split_buf()
Returns: pointer to a Ustr representing the next token
Type: struct Ustr *
Parameter[1]: Pointer to a constant Ustr to be split
Type[1]: const struct Ustr *
Parameter[2]: Pointer to an offset
Type[2]: size_t *
Parameter[3]: Buffer to use as split search pattern
Type[3]: const void *
Parameter[4]: Length of buffer
Type[4]: size_t
Parameter[5]: Pointer to a Ustr to be used as the return value
Type[5]: struct Ustr *
Parameter[6]: Flags with the prefix USTR_FLAG_SPLIT_
Type[6]: unsigned int
Explanation:

This function works in a manner similar to strtok(). Each time the function is called, the string inside of the buffer (Parameter[3]) is used as a search pattern at which to split. If the pattern is not found, the entire string will be returned. A USTR_NULL return value indicates there are no more tokens remaining.

Parameter[5] is a a pointer to a Ustr where the return value will be placed. Passing a USTR_NULL to this parameter will cause the string to be allocated and MUST be freed manually. If, however, you pass in a non-null Ustr to this parameter, each call to ustr_split_buf() will free what is in this pointer and place the new token there (when USTR_NULL is returned, nothing needs to be free'd). For example, given...

  Ustr *data = ...;
  Ustr *tok = USTR_NULL;
  const char *sep = ",";
  size_t off = 0;
  unsigned int flags = USTR_FLAGS_SPLIT_DEF;

...there are two options...

  while ((tok = ustr_split_buf(data, &off, sep, strlen(sep), tok, flags)))
  {
    /* Do something with tok -- but next iteration of the loop will free
     * and overwrite tok, so you must ustr_dup() if you want to keep it */
  }
  /* tok is now NULL again after the loop */

...or...

  while ((tok = ustr_split_buf(data, &off, sep, strlen(sep), USTR_NULL, flags)))
  {
    /* Do something with tok, and it will NOT be freed in the next iteration of
     * the loop */
      ustr_free(tok); /* have to free to avoid mem leaks */
  }

...the former of which being the safer option.

Note:

There are several flags that will alter the behaviour of this function, all of which have a common with the default being USTR_FLAG_SPLIT_DEF.

If you are calling this function directly, it is very likely that you'd want to use ustr_split_cstr() instead.

Function: ustr_split()
Returns: Pointer to a Ustr representing the next token
Type: struct Ustr *
Parameter[1]: Pointer to a constant Ustr to be split
Type[1]: const struct Ustr *
Parameter[2]: Pointer to an offset variable
Type[2]: size_t *
Parameter[3]: Pointer to a constant Ustr to use as the split search pattern
Type[3]: const struct Ustr *
Parameter[4]: Pointer to a Ustr where the return value will be placed
Type[4]: struct Ustr *
Parameter[5]: Flags
Type[5]: unsigned int
Explanation:

Works like ustr_split_buf() but takes a Ustr as the split search pattern

instead.

Function: ustr_split_cstr()
Returns: Pointer to a Ustr representing the next token
Type: struct Ustr *
Parameter[1]: Pointer to a constant Ustr to be split
Type[1]: const struct Ustr *
Parameter[2]: Pointer to an offset variable
Type[2]: size_t *
Parameter[3]: C string to use as split search pattern
Type[3]: const char *
Parameter[4]: Pointer to a Ustr where the return value will be placed
Type[4]: struct Ustr *
Parameter[5]: Flags
Type[5]: unsigned int
Explanation:

Works like ustr_split_buf() but takes a C string as the split search pattern, and so gets the length via. strlen().

Function: ustr_split_spn_chrs()
Returns: Pointer to a Ustr representing the next token
Type: struct Ustr *
Parameter[1]: Pointer to a Ustr to be split
Type[1]: const struct Ustr *
Parameter[2]: Pointer to an offset variable
Type[2]: size_t *
Parameter[3]: String representing a set of bytes to use as split chars
Type[3]: const char *
Parameter[4]: Length of the string of set of bytes
Type[4]: size_t
Parameter[5]: Pointer to a Ustr where the return value will be placed
Type[5]: struct Ustr *
Parameter[6]: flags
Type[6]: unsigned int
Explanation:

Works like ustr_split_buf() but uses the individual ASCII bytes in the separator string (Parameter[3]) as search patterns. It will split if ANY of these individual characters are matched (much like strtok()). For example: if splitting "this, is,a test" with the separator string ", " the tokens returned would be {"this" "is" "a" "test"};

Note:

If you are calling this function directly, it is very likely that you'd want to use ustr_split_spn_cstr() instead.

Function: ustr_split_spn_cstr()
Returns: Pointer to a Ustr representing the next token
Type: struct Ustr *
Parameter[1]: Pointer to a Ustr to be split
Type[1]: const struct Ustr *
Parameter[2]: Pointer to an offset variable
Type[2]: size_t *
Parameter[3]: String representing a set of bytes to use as split chars
Type[3]: const char *
Parameter[4]: Pointer to a Ustr where the return value will be placed
Type[4]: struct Ustr *
Parameter[5]: flags
Type[5]: unsigned int
Explanation:

Works like ustr_split_spn_chrs() but gets the length automatically via. strlen().

Function: ustr_split_spn()
Returns: Pointer to a Ustr representing the next token
Type: struct Ustr *
Parameter[1]: Pointer to a constant Ustr to be split
Type[1]: const struct Ustr *
Parameter[2]: Pointer to an offset variable
Type[2]: size_t *
Parameter[3]: Pointer to a constant Ustr to use as the split search pattern
Type[3]: const struct Ustr *
Parameter[4]: Pointer to a Ustr where the return value will be placed
Type[4]: struct Ustr *
Parameter[5]: Flags
Type[5]: unsigned int
Explanation:

Works like ustr_split_spn_chrs() but takes a Ustr as the split chars instead.

Dealing with UTF-8 in a Ustr

Function: ustr_utf8_valid()
Returns: A boolean flag of either USTR_TRUE or USTR_FALSE
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function tries it's best to find out if the string is a valid utf-8 string.

Function: ustr_utf8_len()
Returns: The number of the utf-8 characters in the Ustr
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function counts the number of utf-8 characters inn the Ustr.

Note:

This function gives undefined answers on strings that aren't utf-8 valid.

Function: ustr_utf8_width()
Returns: ssize_t
Type: ssize_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Explanation:

This function returns the visible width of the string, assuming it is a valid utf-8 string. This is like converting to wide characters and using wcwidth().

Function: ustr_utf8_chars2bytes()
Returns: Length of span in bytes
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Position of a span in utf-8 characters
Type[2]: size_t
Parameter[3]: Length of a span in utf-8 characters
Type[3]: size_t
Parameter[4]: Returns the position of the span in bytes
Type[4]: size_t *
Explanation:

This function converts a span, in utf-8 characters, to the same span in bytes.

Function: ustr_utf8_bytes2chars()
Returns: Returns the position of a span in utf-8 characters
Type: size_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Position of a span in bytes
Type[2]: size_t
Parameter[3]: Length of a span in bytes
Type[3]: size_t
Parameter[4]: Returns length of a span in utf-8 characters
Type[4]: size_t *
Explanation:

This function converts a span, in bytes, to the same span in utf-8 characters.

Note:

Because a byte span can start or end within a utf-8 character, converting the return values back into bytes via. ustr_utf8_chars2bytes() may make the span be slightly bigger (position slightly earlier, and the length slightly longer).

Function: ustr_sc_utf8_reverse()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function reverses the utf-8 characters in the Ustr string, assuming it is a valid utf-8 string, so the last one becomes the first and the second to last becomes the second etc.

Parsing ASCII integer numbers from a Ustr

Function: ustr_parse_uintmaxx()
Returns: Parsed number, or zero on error
Type: uintmax_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_
Type[3]: unsigned int
Parameter[4]: Absolute minimum value
Type[4]: uintmax_t
Parameter[5]: Absolute maximum value
Type[5]: uintmax_t
Parameter[6]: Thousands separator
Type[6]: const char *
Parameter[7]: Return length of parsed number
Type[7]: size_t *
Parameter[8]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_
Type[8]: unsigned int *
Explanation:

This function parses an ASCII representation of a number from a Ustr (Parameter[1]) starting at the offset (Parameter[2]).

Note:

If stdint.h isn't available this function won't be available.

Function: ustr_parse_uintmax()
Returns: Parsed number, or zero on error
Type: uintmax_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_
Type[3]: unsigned int
Parameter[4]: Return length of parsed number
Type[4]: size_t *
Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_
Type[5]: unsigned int *
Explanation:

This function works like ustr_parse_uintmaxx() with the minimum and maximum values taken as 0 and UINTMAX_MAX, and the thousands separator as "_".

Note:

If stdint.h isn't available this function won't be available.

Function: ustr_parse_intmax()
Returns: Parsed number, or zero on error
Type: intmax_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_
Type[3]: unsigned int
Parameter[4]: Return length of parsed number
Type[4]: size_t *
Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_
Type[5]: unsigned int *
Explanation:

This function works like ustr_parse_uintmaxx() with the minimum and maximum values taken as -INTMAX_MIN and INTMAX_MAX, and the thousands separator as "_".

Note:

If stdint.h isn't available this function won't be available.

Function: ustr_parse_ulongx()
Returns: Parsed number, or zero on error
Type: unsigned long
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_
Type[3]: unsigned int
Parameter[4]: Absolute minimum value
Type[4]: unsigned long
Parameter[5]: Absolute maximum value
Type[5]: unsigned long
Parameter[6]: Thousands separator
Type[6]: const char *
Parameter[7]: Return length of parsed number
Type[7]: size_t *
Parameter[8]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_
Type[8]: unsigned int *
Explanation:

This function works like ustr_parse_uintmaxx() but returns an unsigned long, it is always available even when stdint.h isn't.

Function: ustr_parse_ulong()
Returns: Parsed number, or zero on error
Type: unsigned long
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_
Type[3]: unsigned int
Parameter[4]: Return length of parsed number
Type[4]: size_t *
Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_
Type[5]: unsigned int *
Explanation:

This function works like ustr_parse_ulongx() with the minimum and maximum values taken as 0 and ULONG_MAX, and the thousands separator as "_".

Function: ustr_parse_long()
Returns: Parsed number, or zero on error
Type: long
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_
Type[3]: unsigned int
Parameter[4]: Return length of parsed number
Type[4]: size_t *
Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_
Type[5]: unsigned int *
Explanation:

This function works like ustr_parse_ulongx() with the minimum and maximum values taken as -LONG_MIN and LONG_MAX, and the thousands separator as "_".

Function: ustr_parse_uint()
Returns: Parsed number, or zero on error
Type: unsigned int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_
Type[3]: unsigned int
Parameter[4]: Return length of parsed number
Type[4]: size_t *
Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_
Type[5]: unsigned int *
Explanation:

This function works like ustr_parse_ulongx() with the minimum and maximum values taken as 0 and UINT_MAX, and the thousands separator as "_".

Function: ustr_parse_int()
Returns: Parsed number, or zero on error
Type: int
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_
Type[3]: unsigned int
Parameter[4]: Return length of parsed number
Type[4]: size_t *
Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_
Type[5]: unsigned int *
Explanation:

This function works like ustr_parse_ulongx() with the minimum and maximum values taken as -INT_MIN and INT_MAX, and the thousands separator as "_".

Function: ustr_parse_ushort()
Returns: Parsed number, or zero on error
Type: unsigned short
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_
Type[3]: unsigned int
Parameter[4]: Return length of parsed number
Type[4]: size_t *
Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_
Type[5]: unsigned int *
Explanation:

This function works like ustr_parse_ulongx() with the minimum and maximum values taken as 0 and USHRT_MAX, and the thousands separator as "_".

Function: ustr_parse_short()
Returns: Parsed number, or zero on error
Type: short
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_
Type[3]: unsigned int
Parameter[4]: Return length of parsed number
Type[4]: size_t *
Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_
Type[5]: unsigned int *
Explanation:

This function works like ustr_parse_ulongx() with the minimum and maximum values taken as -SHRT_MIN and SHRT_MAX, and the thousands separator as "_".

Misc shortcut helper functions for Ustrs

Function: ustr_sc_ensure_owner()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function makes sure that the Ustr string is owned when it returns (Ie. ustr_owner() returns USTR_TRUE), or it fails to allocate.

Function: ustr_sc_wstr()
Returns: Writable pointer to the start of data in the Ustr, or NULL
Type: char *
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function works like calling ustr_sc_ensure_owner(), to make sure the Ustr string is writable, and if that succeeds it returns ustr_wstr(). On failure it returns NULL.

Function: ustr_sc_export_subustr()
Returns: A pointer to newly allocated block of memory
Type: char *
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Position in the Ustr
Type[2]: size_t
Parameter[3]: Length to export from the Ustr
Type[3]: size_t
Parameter[4]: Allocation function (like malloc)
Type[4]: void *(*)(size_t)
Explanation:

This function allocates a block of memory of size Length (Parameter[3]) + 1 using the provided allocation function (Parameter[4]) and copies the data starting from Position (Parameter[2]) within the ustr.

Function: ustr_sc_export()
Returns: A pointer to newly allocated block of memory
Type: char *
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Allocation function (like malloc)
Type[2]: void *(*)(size_t)
Explanation:

This function works like calling ustr_sc_export_subustr() with a position of 1 and a length of ustr_len().

Function: ustrp_sc_export_subustrp()
Returns: A pointer to newly allocated block of memory
Type: char *
Parameter[1]: Pointer to a Ustr pool object
Type[1]: struct Ustr_pool *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Position in the Ustr
Type[3]: size_t
Parameter[4]: Length to export from the Ustr
Type[4]: size_t
Parameter[5]: Allocation function (like malloc), or NULL
Type[5]: void *(*)(size_t)
Explanation:

This function allocates a block of memory of size Length (Parameter[4]) + 1 using either the provided allocation function (Parameter[5]), or from the pool object if the allocation function is NUL, and copies the data starting from Position (Parameter[3]) within the ustr.

Function: ustrp_sc_export()
Returns: A pointer to newly allocated block of memory
Type: char *
Parameter[1]: Pointer to a Ustr pool object
Type[1]: struct Ustr_pool *
Parameter[2]: A pointer to a constant Ustr string
Type[2]: const struct Ustr *
Parameter[3]: Allocation function (like malloc)
Type[3]: void *(*)(size_t)
Explanation:

This function works like calling ustrp_sc_export_subustrp() with a position of 1 and a length of ustrp_len().

Function: ustr_sc_reverse()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function reverses all the bytes in the Ustr string, so the last one becomes the first and the second to last becomes the second etc.

Function: ustr_sc_tolower()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function changes any ASCII upper case bytes into ASCII lower case bytes.

Function: ustr_sc_toupper()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Explanation:

This function changes any ASCII lower case bytes into ASCII upper case bytes.

Function: ustr_sc_ltrim_chrs()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Array of bytes, containing trimming data
Type[2]: const char *
Parameter[3]: Length of byte data
Type[3]: size_t
Explanation:

This function deletes the bytes at the begining of the Ustr (Parameter[1]) that are in the span (Parameter[2]) of the specificed length (parameter[2]).

Function: ustr_sc_ltrim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant Ustr string, containing trimming bytes
Type[2]: const struct Ustr *
Explanation:

This function works as if you had called ustr_sc_ltrim_chrs() and passed ustr_cstr() and ustr_len() values of the Ustr string (Parameter[2]).

Function: ustr_sc_ltrim_cstr()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant C-style string, containing trimming bytes
Type[2]: const char *
Explanation:

This function works as if you had called ustr_sc_ltrim_chrs() and passed strlen() as the length.

Function: ustr_sc_rtrim_chrs()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Array of bytes, containing trimming data
Type[2]: const char *
Parameter[3]: Length of byte data
Type[3]: size_t
Explanation:

This function deletes the bytes at the end of the Ustr (Parameter[1]) that are in the span (Parameter[2]) of the specificed length (parameter[2]).

Function: ustr_sc_rtrim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant Ustr string, containing trimming bytes
Type[2]: const struct Ustr *
Explanation:

This function works as if you had called ustr_sc_rtrim_chrs() and passed ustr_cstr() and ustr_len() values of the Ustr string (Parameter[2]).

Function: ustr_sc_rtrim_cstr()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant C-style string, containing trimming bytes
Type[2]: const char *
Explanation:

This function works as if you had called ustr_sc_rtrim_chrs() and passed strlen() as the length.

Function: ustr_sc_trim_chrs()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Array of bytes, containing trimming data
Type[2]: const char *
Parameter[3]: Length of byte data
Type[3]: size_t
Explanation:

This function deletes the bytes at the begining or end of the Ustr (Parameter[1]) that are in the span (Parameter[2]) of the specificed length (parameter[2]).

Note:

Calling this function is much more efficient than calling ustr_sc_rtrim_chrs() and then ustr_sc_ltrim_chrs(), as both ends are trimmed in a single pass.

Function: ustr_sc_trim()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant Ustr string, containing trimming bytes
Type[2]: const struct Ustr *
Explanation:

This function works as if you had called ustr_sc_trim_chrs() and passed ustr_cstr() and ustr_len() values of the Ustr string (Parameter[2]).

Function: ustr_sc_trim_cstr()
Returns: Success or failure
Type: int
Parameter[1]: A pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: A pointer to a constant C-style string, containing trimming bytes
Type[2]: const char *
Explanation:

This function works as if you had called ustr_sc_trim_chrs() and passed strlen() as the length.

Adding binary data to a Ustr

Function: ustr_add_b_uint16()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Binary value to add to the Ustr
Type[2]: uint_least16_t
Explanation:

This function adds a binary representation of a value (Parameter[2]) to the Ustr (Parameter[1]).

Function: ustr_add_b_uint32()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Binary value to add to the Ustr
Type[2]: uint_least32_t
Explanation:

This function adds a binary representation of a value (Parameter[2]) to the Ustr (Parameter[1]).

Function: ustr_add_b_uint64()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Binary value to add to the Ustr
Type[2]: uint_least64_t
Explanation:

This function adds a binary representation of a value (Parameter[2]) to the Ustr (Parameter[1]).

Parsing binary data from a Ustr

Function: ustr_parse_b_uint16()
Returns: uint_least16_t
Type: uint_least16_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Explanation:

This function parses a binary representation from a Ustr (Parameter[1]) starting at the offset (Parameter[2]).

Function: ustr_parse_b_uint32()
Returns: uint_least32_t
Type: uint_least32_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Explanation:

This function parses a binary representation from a Ustr (Parameter[1]) starting at the offset (Parameter[2]).

Function: ustr_parse_b_uint64()
Returns: uint_least64_t
Type: uint_least64_t
Parameter[1]: A pointer to a constant Ustr string
Type[1]: const struct Ustr *
Parameter[2]: Offset within string to start parsing at
Type[2]: size_t
Explanation:

This function parses a binary representation from a Ustr (Parameter[1]) starting at the offset (Parameter[2]).

Misc. functions

Function: ustr_realloc()
Returns: Success or failure
Type: int
Parameter[1]: Pointer to a pointer to a Ustr string
Type[1]: struct Ustr **
Parameter[2]: Size of allocation
Type[2]: size_t
Explanation:

This function is re-sizes the Ustr to the specified size (Parameter[2]).

This is mostly used to shrink a sized Ustr that is now significantly smaller than it once was. Although this function can also grow a Ustr.

Note:

To have a size that isn't implied from the length the Ustr must store a size value as well as a length (ustr_sized() must return USTR_TRUE).

Function: ustr_cntl_opt()
Returns: Success or failure
Type: int
Parameter[1]: Optional value starting with USTR_CNTL_OPT_
Type[1]: int
Parameter[2]: Arugments to option
Type[2]: ...
Explanation:

This function views and/or changes global Ustr options, like whether ustr's have an implicit or explicit size (USTR_CNTL_OPT_GET_HAS_SIZE).

Simple Ustr pool API

Function: ustr_pool_ll_make()
Returns: Pointer to a Ustr pool object
Type: struct Ustr_pool *
Parameter[1]: Nothing
Type[1]: void
Explanation:

This allocates a new pool using the "linked list" strategy, each allocation in the pool is added to a linked list ... and any allocations not freed directly are freed by the pool when it is cleared or freed.

Function: ustr_pool_make_subpool()
Returns: Pointer to a Ustr pool object
Type: struct Ustr_pool *
Parameter[1]: struct Ustr_pool *
Type[1]: struct Ustr_pool *
Explanation:

This allocates a new pool as a child of the passed in pool (Parameter[1]), The pool can be freed and cleared independantly of the parent pool however free and clear operations on the parent pool are automatically applied to all child pools.

Function: ustr_pool_free()
Returns: Nothing
Type: void
Parameter[1]: Pointer to a Ustr pool object
Type[1]: struct Ustr_pool *
Explanation:

This deallocates a pool, and all sub-pools.

Note:

This also operates on all sub-pools.

Function: ustr_pool_clear()
Returns: Nothing
Type: void
Parameter[1]: Pointer to a Ustr pool object
Type[1]: struct Ustr_pool *
Explanation:

This allows all the data in the pool to be reused, it may also free some/all of the data in the pool, from the pool API.

Note:

This also operates on all sub-pools.

ustr-1.0.4/Documentation/ustr_const.30000644000076400007640000005036610763530041016612 0ustar jamesjames.TH ustr_const 3 "05-Mar-2008" "Ustr 1.0.4" "Ustr String Library" .SH "NAME" ustr_const \- ustr string library constants .SH "SYNOPSIS" .in \w' 'u #include "ustr.h" .sp .sp .br .ti \w' 'u \fBUSTR_CONF_INCLUDE_CODEONLY_HEADERS\fR .br .ti \w' 'u \fBUSTR_CONF_USE_EOS_MARK\fR .br .ti \w' 'u \fBUSTR_CONF_USE_ASSERT\fR .br .ti \w' 'u \fBUSTR_CONF_COMPILE_USE_ATTRIBUTES\fR .br .ti \w' 'u \fBUSTR_CONF_COMPILE_TYPEDEF\fR .br .ti \w' 'u \fBUSTR_CONF_COMPILE_USE_INLINE\fR .sp .br .ti \w' 'u \fBUSTR_BEG_CONST1\fR .br .ti \w' 'u \fBUSTR_BEG_CONST2\fR .br .ti \w' 'u \fBUSTR_BEG_CONST4\fR .br .ti \w' 'u \fBUSTR_BEG_FIXED1\fR .br .ti \w' 'u \fBUSTR_BEG_FIXED2\fR .br .ti \w' 'u \fBUSTR_BEG_FIXED4\fR .br .ti \w' 'u \fBUSTR_BEG_FIXED8\fR .br .ti \w' 'u \fBUSTR_END_ALOCDx\fR .br .ti \w' 'u \fBUSTR_END_CONSTx\fR .br .ti \w' 'u \fBUSTR_END_FIXEDx\fR .sp .br .ti \w' 'u \fBUSTR_FLAG_PARSE_NUM_DEF\fR .br .ti \w' 'u \fBUSTR_FLAG_PARSE_NUM_SEP\fR .br .ti \w' 'u \fBUSTR_FLAG_PARSE_NUM_OVERFLOW\fR .br .ti \w' 'u \fBUSTR_FLAG_PARSE_NUM_SPACE\fR .br .ti \w' 'u \fBUSTR_FLAG_PARSE_NUM_NO_BEG_ZERO\fR .br .ti \w' 'u \fBUSTR_FLAG_PARSE_NUM_NO_BEG_PM\fR .br .ti \w' 'u \fBUSTR_FLAG_PARSE_NUM_NO_NEGATIVE\fR .br .ti \w' 'u \fBUSTR_FLAG_PARSE_NUM_EXACT\fR .br .ti \w' 'u \fBUSTR_TYPE_PARSE_NUM_ERR_NONE\fR .br .ti \w' 'u \fBUSTR_TYPE_PARSE_NUM_ERR_ONLY_S\fR .br .ti \w' 'u \fBUSTR_TYPE_PARSE_NUM_ERR_ONLY_SPM\fR .br .ti \w' 'u \fBUSTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX\fR .br .ti \w' 'u \fBUSTR_TYPE_PARSE_NUM_ERR_OOB\fR .br .ti \w' 'u \fBUSTR_TYPE_PARSE_NUM_ERR_OVERFLOW\fR .br .ti \w' 'u \fBUSTR_TYPE_PARSE_NUM_ERR_NEGATIVE\fR .br .ti \w' 'u \fBUSTR_TYPE_PARSE_NUM_ERR_BEG_ZERO\fR .sp .br .ti \w' 'u \fBUSTR_FLAG_SPLIT_DEF\fR .br .ti \w' 'u \fBUSTR_FLAG_SPLIT_RET_SEP\fR .br .ti \w' 'u \fBUSTR_FLAG_SPLIT_RET_NON\fR .br .ti \w' 'u \fBUSTR_FLAG_SPLIT_KEEP_CONFIG\fR .sp .br .ti \w' 'u \fBUSTR_NULL\fR .br .ti \w' 'u \fBUSTR_POOL_NULL\fR .br .ti \w' 'u \fBUSTR_TRUE\fR .br .ti \w' 'u \fBUSTR_FALSE\fR .sp .br .ti \w' 'u \fBUSTR_CNTL_OPT_GET_REF_BYTES\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_SET_REF_BYTES\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_GET_HAS_SIZE\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_SET_HAS_SIZE\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_GET_EXACT_BYTES\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_SET_EXACT_BYTES\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_GET_MEM\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_SET_MEM\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_GET_MC_M_SCRUB\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_SET_MC_M_SCRUB\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_GET_MC_F_SCRUB\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_SET_MC_F_SCRUB\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_GET_MC_R_SCRUB\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_SET_MC_R_SCRUB\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_GET_FMT\fR .br .ti \w' 'u \fBUSTR_CNTL_OPT_SET_FMT\fR .sp .br .ti \w' 'u \fBUSTR_POOL_LL_CNTL_GET_FREE_CMP\fR .br .ti \w' 'u \fBUSTR_POOL_LL_CNTL_SET_FREE_CMP\fR .br .ti \w' 'u \fBUSTR_POOL_LL_CNTL_GET_REALLOC\fR .br .ti \w' 'u \fBUSTR_POOL_LL_CNTL_SET_REALLOC\fR .ti .SH "DESCRIPTION" .SH Compile switch constants .br \fBConstant: \fR USTR_CONF_INCLUDE_CODEONLY_HEADERS .br \fBExplanation:\fR .br This switch controls whether all the code will be included as inline functions. Having this be non\-zero means that you don't have to link against the library. .br \fBConstant: \fR USTR_CONF_USE_EOS_MARK .br \fBExplanation:\fR .br This switch turns on End of String markers, so any bounds overflow will be noticed by ustr_assert_valid(). .sp \fBNote:\fR .br Changing this will not do anything useful unless USTR_CONF_INCLUDE_CODEONLY_HEADERS is non\-zero. .br \fBConstant: \fR USTR_CONF_USE_ASSERT .br \fBExplanation:\fR .br This switch turns USTR_ASSERT() calls on, so the code within them will be evaluated. Note that there are many calls to ustr_assert_valid() within USTR_ASSERT() macros and that call is relatively expensive. .sp \fBNote:\fR .br Changing this will not do anything useful unless USTR_CONF_INCLUDE_CODEONLY_HEADERS is non\-zero. .br \fBConstant: \fR USTR_CONF_COMPILE_USE_ATTRIBUTES .br \fBExplanation:\fR .br This switch controls whether gcc type __attribute__() statements are used in the public headers headers for the library. If the value is 1 then if they are supported by the compiler that built the library they will be used, if the value is 0 they won't be used at all. .br \fBConstant: \fR USTR_CONF_COMPILE_TYPEDEF .br \fBExplanation:\fR .br This switch controls whether typedef will be used for the structs in the public headers for the library. If the value is 1 then they will be used, if the value is 0 they won't be used at all (and your code will have to use struct tags instead \-\- note all libraries using ustr should compile without this option set). .br \fBConstant: \fR USTR_CONF_COMPILE_USE_INLINE .br \fBExplanation:\fR .br This switch controls whether inline functions will be used in a few cases where the function bodies are very small. .sp \fBNote:\fR .br In some cases this is used so that GCC can eliminate calls to strlen(), for the *_cstr() functions. .SH Constants to created fixed/read\-only Ustr's .br \fBConstant: \fR USTR_BEG_CONST1 .br \fBExplanation:\fR .br This macro is a constant C\-style string of the first byte of a constant/read\-only Ustr that has a length in the range 0\-255. .br \fBConstant: \fR USTR_BEG_CONST2 .br \fBExplanation:\fR .br This macro is a constant C\-style string of the first byte of a constant/read\-only Ustr that has a length in the range 0\-65535. .br \fBConstant: \fR USTR_BEG_CONST4 .br \fBExplanation:\fR .br This macro is a constant C\-style string of the first byte of a constant/read\-only Ustr that has a length in the range 0\-4294967295. .br \fBConstant: \fR USTR_BEG_FIXED1 .br \fBExplanation:\fR .br This macro is a constant C\-style string of the first byte of a fixed Ustr that has a length in the range 0\-255. .br \fBConstant: \fR USTR_BEG_FIXED2 .br \fBExplanation:\fR .br This macro is a constant C\-style string of the first byte of a fixed Ustr that has a length in the range 0\-65535. .br \fBConstant: \fR USTR_BEG_FIXED4 .br \fBExplanation:\fR .br This macro is a constant C\-style string of the first byte of a fixed Ustr that has a length in the range 0\-4294967295. .br \fBConstant: \fR USTR_BEG_FIXED8 .br \fBExplanation:\fR .br This macro is a constant C\-style string of the first byte of a fixed Ustr that has a length in the range 0\-18446744073709551615. .sp \fBNote:\fR .br This macro is only available if the Ustr code was compiled in a 64bit environment. .br \fBConstant: \fR USTR_END_ALOCDx .br \fBExplanation:\fR .br This macro is a constant C\-style string of the last bytes of an allocated Ustr. .sp \fBNote:\fR .br Unless USTR_CONF_USE_EOS_MARK is non\-zero, this is just the NIL byte. .br \fBConstant: \fR USTR_END_CONSTx .br \fBExplanation:\fR .br This macro is a constant C\-style string of the last bytes of a constant/read\-only Ustr. .sp \fBNote:\fR .br Unless USTR_CONF_USE_EOS_MARK is non\-zero, this is just the NIL byte. .br \fBConstant: \fR USTR_END_FIXEDx .br \fBExplanation:\fR .br This macro is a constant C\-style string of the last bytes of a fixed Ustr. .sp \fBNote:\fR .br Unless USTR_CONF_USE_EOS_MARK is non\-zero, this is just the NIL byte. .SH Constants to use with parsing numbers: ustr_parse_uintmaxx, etc. .br \fBConstant: \fR USTR_FLAG_PARSE_NUM_DEF .br \fBExplanation:\fR .br Default flags, this is merely 0 but can be used as live documentation. .br \fBConstant: \fR USTR_FLAG_PARSE_NUM_SEP .br \fBExplanation:\fR .br This flag allows the parsing (and ignoring) of the seperator character, at arbitrary pointers in the number, so "1234" and "1_234" would both parse the same (assuming "_" is the seperator). .br \fBConstant: \fR USTR_FLAG_PARSE_NUM_OVERFLOW .br \fBExplanation:\fR .br This flag turns on the overflow checking, in other words without it USTR_TYPE_PARSE_NUM_ERR_OVERFLOW will never be returned as an error code. .br \fBConstant: \fR USTR_FLAG_PARSE_NUM_SPACE .br \fBExplanation:\fR .br This flag allows one or more ' ' (Space) characters before the number or number prefix (Plus Sign, Hyphen). .sp \fBNote:\fR .br Other forms of whitespace don't count, this just affects ' '. .br \fBConstant: \fR USTR_FLAG_PARSE_NUM_NO_BEG_ZERO .br \fBExplanation:\fR .br This flag disallows one or more '0' (Digit Zero) characters before the number. .br \fBConstant: \fR USTR_FLAG_PARSE_NUM_NO_BEG_PM .br \fBExplanation:\fR .br This flag disallows a plus or a minus character before the number. .br \fBConstant: \fR USTR_FLAG_PARSE_NUM_NO_NEGATIVE .br \fBExplanation:\fR .br This flag disallows negative values. .br \fBConstant: \fR USTR_FLAG_PARSE_NUM_EXACT .br \fBExplanation:\fR .br This flag makes the parsing functions return an error if the entire string doesn't contain the number being parsed. .br \fBConstant: \fR USTR_TYPE_PARSE_NUM_ERR_NONE .br \fBExplanation:\fR .br This error code has the value 0, and means that no error occurred parsing the number. .br \fBConstant: \fR USTR_TYPE_PARSE_NUM_ERR_ONLY_S .br \fBExplanation:\fR .br This error code means that the Ustr string consisted only of spaces. .br \fBConstant: \fR USTR_TYPE_PARSE_NUM_ERR_ONLY_SPM .br \fBExplanation:\fR .br This error code means that the Ustr string consisted only spaces, and a plus or minus sign. .br \fBConstant: \fR USTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX .br \fBExplanation:\fR .br This error code means that the Ustr string consisted of only spaces, a plus or minus sign and a "0x" base 16 prefix. .br \fBConstant: \fR USTR_TYPE_PARSE_NUM_ERR_OOB .br \fBExplanation:\fR .br This error code means that the Ustr string had characters in it that where out of bounds from the working base. .sp \fBNote:\fR .br Without the USTR_FLAG_PARSE_NUM_EXACT, this error is ignored as soon as any number is parsed. .br This out of bounds includes the Ustr string "++" as well as "4A", when parsing in a base less than 11. .br \fBConstant: \fR USTR_TYPE_PARSE_NUM_ERR_OVERFLOW .br \fBExplanation:\fR .br This error code means that the number parsed from the Ustr string would overflow the type it is being parsed into, this is only returned when the USTR_FLAG_PARSE_NUM_OVERFLOW flag was passed to the parse function. .br \fBConstant: \fR USTR_TYPE_PARSE_NUM_ERR_NEGATIVE .br \fBExplanation:\fR .br This error code means that the number parsed from the Vstr string starts with a '\-' (Hyphen) character when it is supposed to be an unsigned number. .br \fBConstant: \fR USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO .br \fBExplanation:\fR .br This error code means that the number parsed from the Vstr string starts with a '0' (Digit Zero) character, when the USTR_FLAG_PARSE_NUM_NO_BEG_ZERO flag was passed to the parse function. .SH Constants to pass to ustr_split* .br \fBConstant: \fR USTR_FLAG_SPLIT_DEF .br \fBExplanation:\fR .br Default flags, this is merely 0 but can be used as live documentation. .br \fBConstant: \fR USTR_FLAG_SPLIT_RET_SEP .br \fBExplanation:\fR .br Return the separator along with the tokens. For example splitting "a,b," using separator "," will return the tokens "a," and "b," whereas without this flag only "a" and "b" would be returned. .br .br \fBConstant: \fR USTR_FLAG_SPLIT_RET_NON .br \fBExplanation:\fR .br Return empty tokens. For example: splitting "a,,b" with separator "," will return the tokens {"a" "" "b"}. .br \fBConstant: \fR USTR_FLAG_SPLIT_KEEP_CONFIG .br \fBExplanation:\fR .br Force the returned Ustr's to have same configuration parameters as the Ustr string that is being split. .SH Misc constants to use in code .br \fBConstant: \fR USTR_NULL .br \fBExplanation:\fR .br This macro is merely 0 cast to (struct Ustr *), and can be used anywhere NULL would be but "returns" the correct type. .br \fBConstant: \fR USTR_POOL_NULL .br \fBExplanation:\fR .br This macro is merely 0 cast to (struct Ustr_pool *), and can be used anywhere NULL would be but "returns" the correct type. .br \fBConstant: \fR USTR_TRUE .br \fBExplanation:\fR .br This macro is 1, but shows the intent that a boolean value is expected and not a number. .br \fBConstant: \fR USTR_FALSE .br \fBExplanation:\fR .br This macro is 0, but shows the intent that a boolean value is expected and not a number. .SH Constants passed to ustr_cntl_opt() .br \fBConstant: \fR USTR_CNTL_OPT_GET_REF_BYTES .br Parameter\fB[1]\fR: Number of bytes for default reference count in Ustr .br Type\fB[1]\fR: size_t * .br \fBExplanation:\fR .br This option will get the default number of bytes used for a reference count when creating Ustr's. .br \fBConstant: \fR USTR_CNTL_OPT_SET_REF_BYTES .br Parameter\fB[1]\fR: Number of bytes for default reference count in Ustr .br Type\fB[1]\fR: size_t .br \fBExplanation:\fR .br This option will set the default number of bytes used for a reference count when creating Ustr's. .sp \fBNote:\fR .br For a single instance, the ustr_dupx_*() functions can be used. .br \fBConstant: \fR USTR_CNTL_OPT_GET_HAS_SIZE .br Parameter\fB[1]\fR: Default flag for whether to include an explicit size in a Ustr .br Type\fB[1]\fR: int * .br \fBExplanation:\fR .br This option will get the default flag for whether to store an explicit size in created Ustr's. .br \fBConstant: \fR USTR_CNTL_OPT_SET_HAS_SIZE .br Parameter\fB[1]\fR: Default flag for whether to include an explicit size in a Ustr .br Type\fB[1]\fR: int .br \fBExplanation:\fR .br This option will set the default flag for whether to store an explicit size in created Ustr's. .sp \fBNote:\fR .br For a single instance, the ustr_dupx_*() functions can be used. .br \fBConstant: \fR USTR_CNTL_OPT_GET_EXACT_BYTES .br Parameter\fB[1]\fR: Default flag for whether to exactly allocate memory .br Type\fB[1]\fR: int * .br \fBExplanation:\fR .br This option will get the default flag for whether to exactly allocate memory when a Ustr needs to be resized. .br \fBConstant: \fR USTR_CNTL_OPT_SET_EXACT_BYTES .br Parameter\fB[1]\fR: Default flag for whether to exactly allocate memory .br Type\fB[1]\fR: int .br \fBExplanation:\fR .br This option will set the default flag for whether to exactly allocate memory when a Ustr needs to be resized. .sp \fBNote:\fR .br For a single instance, the ustr_dupx_*() functions can be used. .br \fBConstant: \fR USTR_CNTL_OPT_GET_MEM .br Parameter\fB[1]\fR: Pointer to colleciton of function pointers for system allocation .br Type\fB[1]\fR: struct Ustr_cntl_mem * .br \fBExplanation:\fR .br This option will get the "system" allocation functions (malloc, realloc, free) for allocated Ustr's. .sp \fBNote:\fR .br As you would expect the default values are: malloc, realloc, free. .br \fBConstant: \fR USTR_CNTL_OPT_SET_MEM .br Parameter\fB[1]\fR: Pointer to colleciton of function pointers for system allocation .br Type\fB[1]\fR: const struct Ustr_cntl_mem * .br \fBExplanation:\fR .br This option will set the "system" allocation functions (malloc, realloc, free) for allocated Ustr's. .sp \fBNote:\fR .br If this option is set after a Ustr has been created, then when freeing or reallocating the existing Ustr the given functions will be used. So they must either be compatible with the default or you must ensure that nothing is allocated before they are set. .br \fBConstant: \fR USTR_CNTL_OPT_GET_MC_M_SCRUB .br Parameter\fB[1]\fR: Flag for whether to include an explicit size in a Ustr .br Type\fB[1]\fR: int * .br \fBExplanation:\fR .br This option will get the flag for whether to "scrub" data allocated via. malloc check. .sp \fBNote:\fR .br Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. .br \fBConstant: \fR USTR_CNTL_OPT_SET_MC_M_SCRUB .br Parameter\fB[1]\fR: Flag for whether to include an explicit size in a Ustr .br Type\fB[1]\fR: int .br \fBExplanation:\fR .br This option will set the flag for whether to "scrub" data allocated via. malloc check. .sp \fBNote:\fR .br Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. .br \fBConstant: \fR USTR_CNTL_OPT_GET_MC_F_SCRUB .br Parameter\fB[1]\fR: Flag for whether to include an explicit size in a Ustr .br Type\fB[1]\fR: int * .br \fBExplanation:\fR .br This option will get the flag for whether to "scrub" data freed via. malloc check. .sp \fBNote:\fR .br Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. .br \fBConstant: \fR USTR_CNTL_OPT_SET_MC_F_SCRUB .br Parameter\fB[1]\fR: Flag for whether to include an explicit size in a Ustr .br Type\fB[1]\fR: int .br \fBExplanation:\fR .br This option will set the flag for whether to "scrub" data freed via. malloc check. .sp \fBNote:\fR .br Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. .br \fBConstant: \fR USTR_CNTL_OPT_GET_MC_R_SCRUB .br Parameter\fB[1]\fR: Flag for whether to include an explicit size in a Ustr .br Type\fB[1]\fR: int * .br \fBExplanation:\fR .br This option will get the flag for whether to "scrub" data reallocated via. malloc check. This is done by turning all reallocations into a malloc() and free(), and so is even more costly than normal scrubbing. .sp \fBNote:\fR .br Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. .br \fBConstant: \fR USTR_CNTL_OPT_SET_MC_R_SCRUB .br Parameter\fB[1]\fR: Flag for whether to include an explicit size in a Ustr .br Type\fB[1]\fR: int .br \fBExplanation:\fR .br This option will set the flag for whether to "scrub" data reallocated via. malloc check. This is done by turning all reallocations into a malloc() and free(), and so is even more costly than normal scrubbing. .sp \fBNote:\fR .br Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive. .br \fBConstant: \fR USTR_CNTL_OPT_GET_FMT .br Parameter\fB[1]\fR: Pointer to colleciton of function pointers for system formating .br Type\fB[1]\fR: struct Ustr_cntl_fmt * .br \fBExplanation:\fR .br This option will get the system formatting functions (vsnprintf) for Ustr's. .br There are two functions, the first is always called and the second is likely called (always with the exact same arguments) if the length passed to the first call was not big enough. .sp \fBNote:\fR .br As you would expect the default values are: vsnprintf and vsnprintf .br \fBConstant: \fR USTR_CNTL_OPT_SET_FMT .br Parameter\fB[1]\fR: Pointer to colleciton of function pointers for system formatting .br Type\fB[1]\fR: const struct Ustr_cntl_fmt * .br \fBExplanation:\fR .br This option will set the system formatting functions (vsnprintf) for Ustr's. .SH Constants passed to ustr_pool_ll_cntl() .br \fBConstant: \fR USTR_POOL_LL_CNTL_GET_FREE_CMP .br Parameter\fB[1]\fR: Number of pointers to compare to in the pool .br Type\fB[1]\fR: unsigned int * .br \fBExplanation:\fR .br This option will get the number of comparisons done on a pool free operation. .br \fBConstant: \fR USTR_POOL_LL_CNTL_SET_FREE_CMP .br Parameter\fB[1]\fR: Number of pointers to compare to in the pool .br Type\fB[1]\fR: unsigned int .br \fBExplanation:\fR .br This option will set the number of comparisons done on a pool free operation. .sp \fBNote:\fR .br The default is a small non\-zero value, as it's significantly common to have very short lived ustr's ... however this doesn't mean that you can't forget to take references even with pool allocated ustrs. .br \fBConstant: \fR USTR_POOL_LL_CNTL_GET_REALLOC .br Parameter\fB[1]\fR: Flag for if we should call realloc() .br Type\fB[1]\fR: int * .br \fBExplanation:\fR .br This option will get the flag for if we call realloc() to make data bigger, or revert to just allocating anew each time. .br \fBConstant: \fR USTR_POOL_LL_CNTL_SET_REALLOC .br Parameter\fB[1]\fR: Flag for if we should call realloc() .br Type\fB[1]\fR: int .br \fBExplanation:\fR .br This option will set the flag for if we call realloc() to make data bigger, or revert to just allocating anew each time. .sp \fBNote:\fR .br As with USTR_POOL_LL_CNTL_SET_FREE_CMP this option means you can't assume that pool allocated data is never freed until ustr_pool_free() is called, and again it is due to there being significant speed improvements for not making that assumption. Instead of disabling this option, just take areference (which will also make sure the ustr isn't modified behind your back). .SH "SEE ALSO" .BR ustr (3) ustr-1.0.4/Documentation/structs.html0000644000076400007640000001041010763663475016724 0ustar jamesjames Ustr - 1.0.4 reference documentation -- structs

Ustr - 1.0.4 reference documentation -- structs (3)

Index of sections

Index of sections, and their contents

Members of Ustr_pool

Function: pool_sys_malloc()
Returns: Allocated data
Type: void *
Parameter[1]: Ustr pool object
Type[1]: void *
Parameter[2]: Length of new allocation
Type[2]: size_t
Explanation:

This is a callback to provide a similar usage to malloc().

This works like malloc() but allocates at least size (Parameter[2]) memory from the pool (Parameter[1]), or it returns NULL on failure.

Function: pool_sys_realloc()
Returns: Re-allocated data
Type: void *
Parameter[1]: Ustr pool object
Type[1]: void *
Parameter[2]: Pointer to the old data
Type[2]: void *
Parameter[3]: Length of old allocation
Type[3]: size_t
Parameter[4]: Length of new allocation
Type[4]: size_t
Explanation:

This is a callback to provide a similar usage to realloc().

The Ustr ustr_pool_make() varient works like realloc() but allocates at least size (Parameter[4]) memory from the pool (Parameter[1]) and copies the old data into it, or it returns NULL on failure.

Note:

If the old data was the last thing allocated from the pool, it might be resized on success.

If the old data was larger than the new data, the pointer to the old data is always returned.

Function: pool_sys_free()
Returns: Nothing
Type: void
Parameter[1]: Ustr pool object
Type[1]: void *
Parameter[2]: Pointer to the data
Type[2]: void *
Explanation:

This is a callback to provide a similar usage to free().

The Ustr ustr_pool_make() varient free's the data, if it was the last thing allocated from the pool. Otherwise it does nothing.

ustr-1.0.4/Documentation/functions.txt0000644000076400007640000046564610762453107017115 0ustar jamesjamesSection: Creating read-only Ustr functions Function: USTR() Returns: Ustr string Type: struct Ustr * Parameter[1]: Pointer to Ustr data Type[1]: void * Explanation: This macro function is normally used with the empty string "". Note: There is basically just a simple cast behind the macro. Function: USTRP() Returns: Ustrp string Type: struct Ustrp * Parameter[1]: Pointer to Ustrp data Type[1]: void * Explanation: This macro function is normally used with the empty string "". Note: There is basically just a simple cast behind the macro. Function: USTR1() Returns: Ustr string Type: struct Ustr * Parameter[1]: Encoded number of the length of Ustr string Type[1]: symbol Parameter[2]: Data for Ustr string Type[2]: const char[] Explanation: This macro function simplifies the creation of read-only Ustr string's. And is normally used like... USTR1(\x4, "abcd") ...it is worth pointing out that running with debugging turned on (USTR_CONF_USE_ASSERT) will complain if the length isn't encoded correctly, as in... USTR1(\x3, "abcd") ...here ustr_assert_valid() will fail, which is called before most functions do anything in debugging mode. Note also that extra debugging (USTR_CONF_USE_EOS_MARK) will still catch cases like... USTR1(\x3, "abc\0d") ...at least using debugging is esp. important if you are putting UTF-8 characters into the strings. Note: Having ustr_ro() return true means that the Ustr cannot be written to without be reallocated into allocation space ... not that ustr_add() etc. will fail. There is now USTR1_CHK() which performs a compile time check so you can never have an invalid ustr. Function: USTR2() Returns: Ustr string Type: struct Ustr * Parameter[1]: Encoded 2nd byte of number of the length of Ustr string Type[1]: symbol Parameter[2]: Encoded 1st byte of number of the length of Ustr string Type[2]: symbol Parameter[3]: Data for Ustr string Type[3]: const char[] Explanation: This function works in the same way as USTR1() but takes two length bytes, so the read-only string can be upto 65,535 (2**16 - 1) bytes in length. Function: USTR4() Returns: Ustr string Type: struct Ustr * Parameter[1]: Encoded 4th byte of number of the length of Ustr string Type[1]: symbol Parameter[2]: Encoded 3rd byte of number of the length of Ustr string Type[2]: symbol Parameter[3]: Encoded 2nd byte of number of the length of Ustr string Type[3]: symbol Parameter[4]: Encoded 1st byte of number of the length of Ustr string Type[4]: symbol Parameter[5]: Data for Ustr string Type[5]: const char[] Explanation: This function works in the same way as USTR1() but takes four length bytes, so the read-only string can be upto 2**32 - 1 bytes in length. Function: USTR1_CHK() Returns: Ustr string Type: struct Ustr * Parameter[1]: Encoded number of the length of Ustr string Type[1]: symbol Parameter[2]: Data for Ustr string Type[2]: const char[] Explanation: This function works in the same way as USTR1() but it does a check against the length of (Parameter[2]) using sizeof() - 1. Note: If the check fails the returned Ustr * will be "", so you can check ustr_len() to see if you screwed something up. Function: USTR2_CHK() Returns: Ustr string Type: struct Ustr * Parameter[1]: Encoded 2nd byte of number of the length of Ustr string Type[1]: symbol Parameter[2]: Encoded 1st byte of number of the length of Ustr string Type[2]: symbol Parameter[3]: Data for Ustr string Type[3]: const char[] Explanation: This function works in the same way as USTR2() but it does a check against the length of (Parameter[2]) using sizeof() - 1. Note: If the check fails the returned Ustr * will be "". Function: USTR4_CHK() Returns: Ustr string Type: struct Ustr * Parameter[1]: Encoded 4th byte of number of the length of Ustr string Type[1]: symbol Parameter[2]: Encoded 3rd byte of number of the length of Ustr string Type[2]: symbol Parameter[3]: Encoded 2nd byte of number of the length of Ustr string Type[3]: symbol Parameter[4]: Encoded 1st byte of number of the length of Ustr string Type[4]: symbol Parameter[5]: Data for Ustr string Type[5]: const char[] Explanation: This function works in the same way as USTR4() but it does a check against the length of (Parameter[2]) using sizeof() - 1. Note: If the check fails the returned Ustr * will be "". Function: USTRP1() Returns: Ustr string Type: struct Ustr * Parameter[1]: Encoded number of the length of Ustr string Type[1]: symbol Parameter[2]: Data for Ustr string Type[2]: const char[] Explanation: This function works like USTR1(), but returns a Ustrp instead. Function: USTRP2() Returns: Ustr string Type: struct Ustr * Parameter[1]: Encoded 2nd byte of number of the length of Ustr string Type[1]: symbol Parameter[2]: Encoded 1st byte of number of the length of Ustr string Type[2]: symbol Parameter[3]: Data for Ustr string Type[3]: const char[] Explanation: This function works like USTR4(), but returns a Ustrp instead. Function: USTRP4() Returns: Ustrp string Type: struct Ustrp * Parameter[1]: Encoded 4th byte of number of the length of Ustrp string Type[1]: symbol Parameter[2]: Encoded 3rd byte of number of the length of Ustrp string Type[2]: symbol Parameter[3]: Encoded 2nd byte of number of the length of Ustrp string Type[3]: symbol Parameter[4]: Encoded 1st byte of number of the length of Ustrp string Type[4]: symbol Parameter[5]: Data for Ustr string Type[5]: const char[] Explanation: This function works like USTR2(), but returns a Ustrp instead. Function: USTRP1_CHK() Returns: Ustr string Type: struct Ustr * Parameter[1]: Encoded number of the length of Ustr string Type[1]: symbol Parameter[2]: Data for Ustr string Type[2]: const char[] Explanation: This function works like USTR1_CHK(), but returns a Ustrp instead. Function: USTRP2_CHK() Returns: Ustr string Type: struct Ustr * Parameter[1]: Encoded 2nd byte of number of the length of Ustr string Type[1]: symbol Parameter[2]: Encoded 1st byte of number of the length of Ustr string Type[2]: symbol Parameter[3]: Data for Ustr string Type[3]: const char[] Explanation: This function works like USTR4_CHK(), but returns a Ustrp instead. Function: USTRP4_CHK() Returns: Ustrp string Type: struct Ustrp * Parameter[1]: Encoded 4th byte of number of the length of Ustrp string Type[1]: symbol Parameter[2]: Encoded 3rd byte of number of the length of Ustrp string Type[2]: symbol Parameter[3]: Encoded 2nd byte of number of the length of Ustrp string Type[3]: symbol Parameter[4]: Encoded 1st byte of number of the length of Ustrp string Type[4]: symbol Parameter[5]: Data for Ustr string Type[5]: const char[] Explanation: This function works like USTR2_CHK(), but returns a Ustrp instead. Section: Creating fixed Ustr functions Function: USTR_SIZE_FIXED() Returns: Size of area of memory Type: size_t Parameter[1]: Size of area of memory Type[1]: size_t Explanation: This macro function is replaced by a static conversion from the max length desired (Parameter[1]) to the storage size needed. In other words it works out what ustr_size_overhead() will be, and adds that value. Note: This is useful is you want a small fixed size allocation, as you can declare it like so: char buf[USTR_SIZE_FIXED(4)]; ...to give you exactly 4 bytes as a maximum, this is esp. useful if you want a limited (ustr_limited() == USTR_TRUE) Ustr string. Function: ustr_init_fixed() Returns: Ustr string Type: struct Ustr * Parameter[1]: Pointer to area of memory to use as a Ustr string Type[1]: void * Parameter[2]: Size of area of memory Type[2]: size_t Parameter[3]: Whether the fixed size Ustr should be limited Type[3]: int Parameter[4]: The initial length of the Ustr Type[4]: size_t Explanation: This creates a new Ustr string, which is "fixed". This means the Ustr storage is managed outside of the ustr_* API, it is often used for stack allocated strings. As you add data to the Ustr past the size allowed via. the fixed storge the Ustr will automatically be converted into an allocated Ustr. So if this is possible you should always call ustr_free(), as this does nothing if given a fixed size Ustr. Note: For simplicity you probably want to use USTR_SC_INIT_AUTO() or USTR_SC_INIT_AUTO() when possible. Function: USTR_SC_INIT_AUTO() Returns: Ustr string Type: struct Ustr * Parameter[1]: Area of memory to use as a Ustr string Type[1]: char[] Parameter[2]: Whether the fixed size Ustr should be limited Type[2]: int Parameter[3]: The initial length of the Ustr Type[3]: size_t Explanation: This calls ustr_init_fixed() with sizeof() the area of memory (Parameter[1]) as the second argument. Note: This does mean that the first argument must be the correct size, as far as sizeof() is concerned, as in... char buf_sz[1024]; Ustr *s1 = USTR_SC_INIT_AUTO(buf_sz, USTR_FALSE, 0); ...so passing pointers to memory from malloc() will probably just return NULL. Function: USTR_SC_INIT_AUTO_OSTR() Returns: Ustr string Type: struct Ustr * Parameter[1]: Area of memory to use as a Ustr string Type[1]: char[] Parameter[2]: Whether the fixed size Ustr should be limited Type[2]: int Parameter[3]: The initial string in the buffer, as a constant string Type[3]: size_t Explanation: This calls ustr_init_fixed() with sizeof() the area of memory (Parameter[1]) as the second argument, given as an "object string". Note: This does mean that the first argument must be the correct size, as far as sizeof() is concerned, as in... char buf_sz[1024] = USTR_BEG_FIXED2 "abcd"; Ustr *s1 = USTR_SC_INIT_AUTO_OSTR(buf_sz, USTR_FALSE, "abcd"); ...so passing pointers to memory from malloc() will probably just return NULL. Section: Debugging functions Function: ustr_assert_valid() Returns: Success or failure Type: int Parameter[1]: Pointer to a Ustr string Type[1]: Ustr * Explanation: This function asserts a few internal consistency checks, and can help point out when a Ustr is invalid. Note: This calls ustr_assert_ret() so that when USTR_DEBUG if off the checks are still performed and the result is returned. Function: ustr_assert_valid_subustr() Returns: Success or failure Type: int Parameter[1]: Pointer to a Ustr string Type[1]: Ustr * Parameter[2]: Position in the Ustr Type[2]: size_t Parameter[3]: Length to delete from the Ustr Type[3]: size_t Explanation: This function calls ustr_assert_valid() and also checks that the position and length are within the Ustr. If they aren't valid it returns 0, if they are valid it returns ustr_len(). Function: USTR_CNTL_MALLOC_CHECK_BEG() Returns: Success or failure Type: int Parameter[1]: Condition for begin malloc checking or not Type[1]: int Explanation: This function begins malloc checking, meaning all ustr allocations will go through the malloc check routines, but it fails if the condition check (Parameter[1]) fails. Note: Turning malloc checking on after one or more allocations has happened will lead to false failures unless you really known what you are doing. You can automatically turn malloc checking on by giving the USTR_CNTL_MC environment variable the value of "1", "yes" or "on". Function: USTR_CNTL_MALLOC_CHECK_LVL() Returns: Level of current malloc check Type: int Parameter[1]: Nothing Type[1]: void Explanation: This function returns the current "level" of the malloc check, with 0 indicating that malloc check isn't enabled. The level goes up by one whenever USTR_CNTL_MALLOC_CHECK_BEG() or USTR_CNTL_MALLOC_CHECK_ADD() returns success, and goes down by one whenever USTR_CNTL_MALLOC_CHECK_DEL() or USTR_CNTL_MALLOC_CHECK_END() returns success. Function: USTR_CNTL_MALLOC_CHECK_MEM() Returns: Success or failure Type: int Parameter[1]: Pointer returned from malloc check Type[1]: void * Explanation: This function asserts that the pointer (Parameter[1]) was allocated from malloc checking. Note: Unless you are doing something special, or using a builtin Ustr_pool it is very likely you want to just call USTR_CNTL_MALLOC_CHECK_MEM_USTR(). Function: USTR_CNTL_MALLOC_CHECK_MEM_SZ() Returns: Success or failure Type: int Parameter[1]: Pointer returned from malloc check Type[1]: void * Parameter[2]: Length of allocated memory Type[2]: size_t Explanation: This function asserts that the pointer (Parameter[1]) was allocated from malloc checking, and has the specified size (Parameter[2]). Note: Unless you are doing something special, or using a builtin Ustr_pool it is very likely you want to just call USTR_CNTL_MALLOC_CHECK_MEM_USTR(). Function: USTR_CNTL_MALLOC_CHECK_MEM_MINSZ() Returns: Success or failure Type: int Parameter[1]: Pointer returned from malloc check Type[1]: void * Parameter[2]: Length of allocated memory Type[2]: size_t Explanation: This function asserts that the pointer (Parameter[1]) was allocated from malloc checking, and has at least the specified size (Parameter[2]). Note: Unless you are doing something special, or using a builtin Ustr_pool it is very likely you want to just call USTR_CNTL_MALLOC_CHECK_MEM_USTR(). Function: USTR_CNTL_MALLOC_CHECK_MEM_USTR() Returns: Success or failure Type: int Parameter[1]: Pointer to a Ustr string Type[1]: Ustr * Explanation: This function asserts that the pointer (Parameter[1]) is a Ustr allocated from malloc checking, if the Ustr is allocated (if not it returns TRUE). Note: Because of the layering between the Ustr code and the pool code, if you allocate an implicity sized Ustrp from a pool and then delete some data from it (which fails) the Ustr layer will think it has an implicit less than the actual size so this function will fail. This is what USTR_CNTL_MALLOC_CHECK_MEM_USTRP() is for. Function: USTR_CNTL_MALLOC_CHECK_MEM_USTRP() Returns: Success or failure Type: int Parameter[1]: Pointer to a Ustrp string Type[1]: Ustrp * Explanation: This function asserts that the pointer (Parameter[1]) is a Ustr allocated from a builtin pool using malloc checking, if the Ustr is allocated (if not it returns TRUE). Function: USTR_CNTL_MALLOC_CHECK_END() Returns: Success or failure Type: int Parameter[1]: Nothing Type[1]: void Explanation: This macro will cleanup any memory used by malloc check, and assert that no memory is left allocated. Note: If any memory is left allocated, each one found is output to stderr with the file/line/function of the level it was allocated from. Function: USTR_CNTL_MALLOC_CHECK_ADD() Returns: Success or failure Type: int Parameter[1]: Condition to begin malloc checking or not Type[1]: int Explanation: This function works like USTR_CNTL_MALLOC_CHECK_END() but it fails if the condition check (Parameter[1]) fails, or if USTR_CNTL_MALLOC_CHECK_LVL() is zero. Function: USTR_CNTL_MALLOC_CHECK_DEL() Returns: Success or failure Type: int Parameter[1]: Condition to end malloc checking or not Type[1]: int Explanation: This function works like USTR_CNTL_MALLOC_CHECK_END() but it fails if the condition check (Parameter[1]) fails, or if USTR_CNTL_MALLOC_CHECK_LVL() is one. Note: The condition (Parameter[1]) to this macro should almost certainly be the return value from USTR_CNTL_MALLOC_CHECK_ADD(). Section: Creating allocated Ustr functions Function: ustr_init_size() Returns: Size that needs to be allocated Type: size_t Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: Length of data in the Ustr Type[4]: size_t Explanation: This function finds out the exact size of memory needed to store the specified Ustr of the given configuration. Function: ustr_init_alloc() Returns: Ustr string Type: struct Ustr * Parameter[1]: Pointer to area of memory to use as a Ustr string Type[1]: void * Parameter[2]: Size of area of memory Type[2]: size_t Parameter[3]: Whether Ustr should store the size Type[3]: size_t Parameter[4]: Number of bytes to use for references Type[4]: size_t Parameter[5]: Whether the Ustr should use exact allocations Type[5]: int Parameter[6]: Whether the Ustr should have the "enomem" flag set Type[6]: int Parameter[7]: The initial length of the Ustr Type[7]: size_t Explanation: This creates a new Ustr string, you should have allocated the data via. USTR_CONF_MALLOC() or bad things will happen if the Ustr string is ever free'd or reallocated. Function: ustr_dupx_empty() Returns: Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocation flag Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Explanation: This function creates an empty Ustr, owned by you, that is allocated from system memory, or it returns NULL. The size is the desired allocation size for the entire Ustr, including overhead for metadata. This value will be rounded up, if it's too small, so passing 1 as the size means you want a stored size but to allocate the smallest amount of memory possible. The exact memory allocation flag says if the Ustr should round allocations up to the nearest half power of two or should be no more than needed. The ENOMEM memory error flag sets the iniital state of the user visible flag for memory allocation errors. Eg. ustr_enomem(), ustr_setf_enomem_clr() and ustr_setf_enomem_err() Note: The reference byte count can only be one of the following values: 0, 1, 2 or 4, or 8 (on environments with a 64bit size_t). It can be useful to ensure that the Ustr is in system memory, so that you can add things to it and check for errors with ustr_enomem(). If you chose to store the allocated size in the Ustr then the number of bytes allocated for the reference count will be a minimum of 2. Function: ustr_dup_empty() Returns: Ustr string Type: struct Ustr * Parameter[1]: Nothing Type[1]: void Explanation: This function is the same as calling ustr_dupx_empty() with the current set of default options. Function: ustr_dupx_undef() Returns: Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: Length of new undefined data Type[5]: size_t Explanation: This function works like you called ustr_dupx_empty() and then ustr_add_undef(). Function: ustr_dup_undef() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Length of new undefined data Type[1]: size_t Explanation: This function is the same as calling ustr_dupx_undef() with the current set of default options. Function: ustr_dup() Returns: A pointer to a Ustr string Type: struct Ustr * Parameter[1]: Pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function tries to increase the reference count on the passed Ustr string, and if that succeeds returns that as an argument. If that fails it tries creates a new Ustr string that looks identical to the old Ustr string, apart from the reference count. Note: Because the new Ustr string is configured identically to the old Ustr string this means the result can be very different to what you get if you call ustr_dup_buf() with ustr_cstr() and ustr_len() from the original string where the configuration would be whatever the default is. Esp. worth of note is that if you ustr_dup() a Ustr string with an explicit size of 900 but a length of 1, and the reference count is full the returned Ustr string will have a size of 900 bytes and so will have allocated a little over that. ustr_dup_buf(), even with a sized configuration would only allocate about 12 bytes and have a size a little less than that. Function: ustr_dupx() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: Pointer to a constant Ustr string Type[5]: const struct Ustr * Explanation: This function tries to add a reference if the value of the size, reference bytes, exact memory allocations and ENOMEM are the same as those in the passed Ustr string (Parameter[5]). If the comparison fails or the addition of a reference fails it works like ustr_dupx_buf() using ustr_cstr() and ustr_len(). Function: ustr_sc_dup() Returns: A pointer to a Ustr string Type: struct Ustr * Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function works like calling ustr_dup(), but if the reference count is maxed out then and so a new Ustr string has been allocated then that is stored in the passed argument (Parameter[1]) and the "old" Ustr string is returned. Note: The reason to use this is that if you have a "main" Ustr string pointer that a lot of things are getting references too then when the reference count maxes out you'll degrade into worst case behaviour which acts as though there are no reference counts. This function stops that problem. As an example, if you have a 1 byte reference count and have 255 * 2 references then using ustr_dup() will create 256 Ustr strings using this function will create 4 Ustr strings. Function: ustr_sc_dupx() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: A pointer to a pointer to a Ustr string Type[5]: struct Ustr ** Explanation: This function works like calling ustr_dupx(), but if the reference count is maxed out then and so a new Ustr string is allocated then that is stored in the passed argument (Parameter[1]) and the "old" Ustr string is returned. If the configurations of the new Ustr string and the old Ustr string are not the same, this function works identically to ustr_dupx(). Note: The reason to use this is that if you have a "main" Ustr string pointer that a lot of things are getting references too then when the reference count maxes out you'll degrade into worst case behaviour which acts as though there are no reference counts. This function stops that problem. As an example, if you have a 1 byte reference count and have 255 * 2 references then using ustr_dupx() will create 256 Ustr strings using this function will create 4 Ustr strings. Function: ustr_dup_buf() Returns: A pointer to a Ustr string Type: struct Ustr * Parameter[1]: Pointer to data Type[1]: const void * Parameter[2]: Length of data Type[2]: size_t Explanation: This function works as if you had called ustr_dup_undef() and then copied the data into the new undefined space. Function: ustr_dupx_buf() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: Pointer to data Type[5]: const void * Parameter[6]: Length of data Type[6]: size_t Explanation: This function works as if you had called ustr_dupx_undef() and then copied the data into the new undefined space. Function: ustr_dup_cstr() Returns: A pointer to a Ustr string Type: struct Ustr * Parameter[1]: Pointer to constant C-style string Type[1]: const char * Explanation: This function works as if you had called ustr_dup_buf() and passed strlen() as the length. Function: ustr_dupx_cstr() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: Pointer to constant C-style string Type[5]: const char * Explanation: This function works as if you had called ustr_dupx_buf() and passed strlen() as the length. Function: USTR_DUP_OSTR() Returns: A pointer to a Ustr string Type: struct Ustr * Parameter[1]: A constant C-style string Type[1]: const char [] Explanation: This function works as if you had called ustr_dup_buf() and passed sizeof() - 1 as the length. Function: USTR_DUP_OBJ() Returns: A pointer to a Ustr string Type: struct Ustr * Parameter[1]: A symbol Type[1]: ... Explanation: This function works as if you had called ustr_dup_buf() and passed sizeof() as the length. Note: In most cases you'll want to use USTR_DUP_OSTR(). Function: ustr_dup_subustr() Returns: A pointer to a Ustr string Type: struct Ustr * Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Position in the Ustr Type[2]: size_t Parameter[3]: Length to add from the Ustr Type[3]: size_t Explanation: This function mostly works as if you had called ustr_dup_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be added. Note: If the position is 1 and the length is the length of the Ustr string then it just calls ustr_dup(). Function: ustr_dupx_subustr() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: A pointer to a constant Ustr string Type[5]: const struct Ustr * Parameter[6]: Position in the Ustr Type[6]: size_t Parameter[7]: Length to add from the Ustr Type[7]: size_t Explanation: This function mostly works as if you had called ustr_dupx_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be added. Note: If the position is 1 and the length is the length of the Ustr string then it just calls ustr_dupx(). Function: ustr_dup_rep_chr() Returns: A pointer to a Ustr string Type: struct Ustr * Parameter[1]: Byte value of data Type[1]: char Parameter[2]: Length of bytes as data Type[2]: size_t Explanation: This function works as if you had called ustr_dup_undef() and then copied the byte value to each position. Function: ustr_dupx_rep_chr() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: Byte value of data Type[5]: char Parameter[6]: Length of bytes as data Type[6]: size_t Explanation: This function works as if you had called ustr_dupx_undef() and then copied the byte value to each position. Function: ustr_sc_vjoin() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Separator to go between Ustr strings Type[1]: const struct Ustr * Parameter[2]: A pointer to the first constant Ustr string Type[2]: const struct Ustr * Parameter[3]: A pointer to the second constant Ustr string Type[3]: const struct Ustr * Parameter[4]: Variable argument list variable, from va_start() Type[4]: va_list Explanation: This function works as if you called ustr_dup() on the first Ustr string (Parameter[2]), and then ustr_add() on the separator (Parameter[1]) followed by ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached. Note: This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually. Function: ustr_sc_join() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Separator to go between Ustr strings Type[1]: const struct Ustr * Parameter[2]: A pointer to the first constant Ustr string Type[2]: const struct Ustr * Parameter[3]: A pointer to the second constant Ustr string Type[3]: const struct Ustr * Parameter[4]: Zero or more pointers to constant Ustr strings and then USTR_NULL Type[4]: ... Explanation: This function calls va_start() to get a variable argument list and then calls ustr_sc_vjoin(). Note: This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually. Function: ustr_sc_vjoinx() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: Separator to go between Ustr strings Type[5]: const struct Ustr * Parameter[6]: A pointer to the first constant Ustr string Type[6]: const struct Ustr * Parameter[7]: A pointer to the second constant Ustr string Type[7]: const struct Ustr * Parameter[8]: Variable argument list variable, from va_start() Type[8]: va_list Explanation: This function works as if you called ustr_dupx() on the first Ustr string (Parameter[2]), and then ustr_add() on the separator (Parameter[1]) followed by ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached. Note: This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually. Function: ustr_sc_joinx() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: Separator to go between Ustr strings Type[5]: const struct Ustr * Parameter[6]: A pointer to the first constant Ustr string Type[6]: const struct Ustr * Parameter[7]: A pointer to the second constant Ustr string Type[7]: const struct Ustr * Parameter[8]: Zero or more pointers to constant Ustr strings and then USTR_NULL Type[8]: ... Explanation: This function calls va_start() to get a variable argument list and then calls ustr_sc_vjoinx(). Function: ustr_sc_vconcat() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: A pointer to the first constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Variable argument list variable, from va_start() Type[2]: va_list Explanation: This function works as if you called ustr_dup() on the first Ustr string (Parameter[1]), and then ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached. Note: This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually. Function: ustr_sc_concat() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: A pointer to the first constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Zero or more pointers to constant Ustr strings and then USTR_NULL Type[2]: ... Explanation: This function calls va_start() to get a variable argument list and then calls ustr_sc_vconcat(). Function: ustr_sc_vconcatx() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: A pointer to the first constant Ustr string Type[5]: const struct Ustr * Parameter[6]: Variable argument list variable, from va_start() Type[6]: va_list Explanation: This function works as if you called ustr_dupx() on the first Ustr string (Parameter[1]), and then ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached. Note: This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually. Function: ustr_sc_concatx() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: A pointer to the first constant Ustr string Type[5]: const struct Ustr * Parameter[6]: Zero or more pointers to constant Ustr strings and then USTR_NULL Type[6]: ... Explanation: This function calls va_start() to get a variable argument list and then calls ustr_sc_vconcatx(). Section: Deleting a Ustr, or data within a Ustr Function: ustr_free() Returns: Nothing Type: void Parameter[1]: Pointer to a Ustr Type[1]: struct Ustr * Explanation: This function decrements the reference count on a Ustr, if there is one, and free's it if it is allocated and the reference count becomes zero. Note: This function does nothing if passed USTR_NULL. Function: ustrp_free() Returns: Nothing Type: void Parameter[1]: Pointer to a Ustr pool object Type[1]: struct Ustr_pool * Parameter[2]: Pointer to a Ustrp (pool allocated Ustr) Type[2]: struct Ustrp * Explanation: This function works like ustr_free() but calls the pool_free member function of the Ustr_pool (Parameter[1]) instead of the ustr system free. Function: ustr_sc_free() Returns: Nothing Type: void Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function calls ustr_free() and then sets the pointer (Parameter[1]) to USTR_NULL, which is a noop when passed to ustr_free(). This can be used to help prevent "double free" errors. Note: While the point to the pointer must be non-NULL, this function also accepts a NULL ustr and does nothing. So you can pass the same pointer to this function multiple times and only the first one will do anything. Function: ustr_sc_free2() Returns: Nothing Type: void Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Pointer to a Ustr string Type[2]: struct Ustr * Explanation: This function works like ustr_sc_free() but instead of setting the pointer (Parameter[1]) to USTR_NULL it sets it to the Ustr string (Parameter[2]). Note: While the point to the pointer must be non-NULL, this function also accepts a NULL ustr to be free'd and does nothing. So you can pass the same pointer to ustr_sc_free() and then this function safely. The passed value (Parameter[2]) shouldn't be USTR_NULL, and in debugging mode the function will assert() that it isn't. Function: ustr_sc_free_shared() Returns: Nothing Type: void Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function is a simple way to "free" a Ustr string that has been shared (ustr_shared() returns USTR_TRUE), normally ustr_free() is ignored on a shared Ustr string. It just calls ustr_setf_owner() and then ustr_sc_free(). Function: ustr_del() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Length to delete from the Ustr Type[2]: size_t Explanation: This function deletes data from the end of Ustr, possibly re-sizing the Ustr at the same time. Note: The Ustr is never re-sized when the size is stored explicitly, so the pointer never changes. Function: ustr_del_subustr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position in the Ustr Type[2]: size_t Parameter[3]: Length to delete from the Ustr Type[3]: size_t Explanation: This function works like ustr_del() but can delete an arbitrary section of the Ustr. Function: ustr_sc_del() Returns: Nothing Type: void Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function is like calling ustr_del() with ustr_len() as the length, however if that fails it does a ustr_free() and then sets the pointer to USTR(""). Note: While the benifit is that you don't have to check for memory failure errors, if there is a memory failure and you have a non-default configuration the configuration will revert back to the default. Section: Adding data to a Ustr Function: ustr_add_undef() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Length of new undefined data Type[2]: size_t Explanation: The Ustr string is expanded (possibly reallocated) so that it can contain length (Parameter[2]) extra data, if the length is not zero the Ustr will be writable. Or it'll return USTR_FALSE (zero) on failure. Function: ustr_add_buf() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Pointer to data Type[2]: const void * Parameter[3]: Length of data Type[3]: size_t Explanation: This function works as if you had called ustr_add_undef() and then copied the data into the new undefined space. Function: ustr_add_cstr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Pointer to constant C-style string Type[2]: const char * Explanation: This function works as if you had called ustr_add_buf() and passed strlen() as the length. Function: USTR_ADD_OSTR() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A constant C-style string Type[2]: const char [] Explanation: This function works as if you had called ustr_add_buf() and passed sizeof() - 1 as the length. Function: USTR_ADD_OBJ() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A symbol Type[2]: ... Explanation: This function works as if you had called ustr_add_buf() and passed sizeof() as the length. Note: In most cases you'll want to use USTR_ADD_OSTR(). Function: ustr_add() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function mostly works as if you had called ustr_add_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added. Note: If the Ustr string is zero length and isn't writable this function may just add a reference, this is fine for Ustr strings that are "constant" because if the Ustr is read-only then the memory will not be written to. Function: ustr_add_subustr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to add from the Ustr Type[4]: size_t Explanation: This function mostly works as if you had called ustr_add_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be added. The exception being if you add a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr, but this function just works. Note: If the position is 1 and the length is the length of the Ustr string then it just calls ustr_add(). Function: ustr_add_rep_chr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Byte value of data Type[2]: char Parameter[3]: Length of bytes as data Type[3]: size_t Explanation: This function works as if you had called ustr_add_undef() and then copied the byte value to each position. Section: Setting a Ustr to some data Function: ustr_set_undef() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: size_t Type[2]: size_t Explanation: This function works as if you had called ustr_del() for the entire string and the ustr_add_undef(). Function: ustr_set_empty() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function works as if you had called ustr_del() for the entire string, however the string will be allocated if this completes. Function: ustr_set_buf() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Buffer containting data Type[2]: const void * Parameter[3]: Length of Buffer Type[3]: size_t Explanation: This function works as if you had called ustr_del() for the entire string and the ustr_add_buf(). Function: ustr_set_cstr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Explanation: This function works as if you had called ustr_del() for the entire string and then ustr_add_cstr(). Function: USTR_SET_OSTR() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A constant C-style string Type[2]: const char [] Explanation: This function works as if you had called ustr_del() for the entire string and then USTR_ADD_OSTR(). Function: USTR_SET_OBJ() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A symbol Type[2]: ... Explanation: This function works as if you had called ustr_del() for the entire string and then USTR_ADD_OBJ(). Note: In most cases you'll want to use USTR_SET_OSTR(). Function: ustr_set() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function works as if you had called ustr_del() for the entire string and the ustr_add(). Function: ustr_set_subustr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to set from the Ustr Type[4]: size_t Explanation: This function works as if you had called ustr_del() for the entire string and the ustr_add_subustr(). The exception being if you set a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works. Function: ustr_set_rep_chr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Byte value of data Type[2]: char Parameter[3]: Length of bytes as data Type[3]: size_t Explanation: This function works as if you had called ustr_del() for the entire string and the ustr_add_rep_chr(). Section: Inserting data into a Ustr Function: ustr_ins_undef() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[3]: Length of new undefined data Type[3]: size_t Explanation: The Ustr string is expanded (possibly reallocated) so that it can contain length (Parameter[2]) extra data, from after the required position. If the length is not zero the Ustr will be writable. Or it'll return USTR_FALSE (zero) on failure. The data in the Ustr is moved as needed to put the new data at position (Parameter[2]) + 1. Function: ustr_ins_buf() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[3]: Pointer to data Type[3]: const void * Parameter[4]: Length of data Type[4]: size_t Explanation: This function works as if you had called ustr_ins_undef() and then copied the data into the new undefined space. Function: ustr_ins_cstr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[3]: Pointer to constant C-style string Type[3]: const char * Explanation: This function works as if you had called ustr_ins_buf() and passed strlen() as the length. Function: USTR_INS_OSTR() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[3]: A constant C-style string Type[3]: const char [] Explanation: This function works as if you had called ustr_ins_buf() and passed sizeof() - 1 as the length. Function: USTR_INS_OBJ() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[3]: A symbol Type[3]: ... Explanation: This function works as if you had called ustr_ins_buf() and passed sizeof() as the length. Note: In most cases you'll want to use USTR_INS_OSTR(). Function: ustr_ins() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string Type[3]: const struct Ustr * Explanation: This function works as if you had called ustr_ins_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added. Function: ustr_ins_subustr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to ins from the Ustr Type[4]: size_t Explanation: This function mostly as if you had called ustr_ins_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be insed. The exception being if you insert a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works. Function: ustr_ins_rep_chr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[2]: Byte value of data Type[2]: char Parameter[3]: Length of bytes as data Type[3]: size_t Explanation: This function works as if you had called ustr_ins_undef() and then copied the byte value to each position. Section: Adding, duplicating and setting formatted data to a Ustr Function: ustr_add_vfmt_lim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Limit of data to add Type[2]: size_t Parameter[3]: A pointer to a constant C-style string Type[3]: const char * Parameter[4]: Variable argument list variable, from va_start() Type[4]: va_list Explanation: This function works like calling the system vsnprintf() with the limit (Parameter[2]) as the limit to vsnprintf() and then calling ustr_add_buf(). Function: ustr_add_vfmt() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Parameter[3]: Variable argument list variable, from va_start() Type[3]: va_list Explanation: This function works like calling the system vsnprintf() and then calling ustr_add_buf(). Function: ustr_add_fmt_lim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Limit of data to add Type[2]: size_t Parameter[3]: A pointer to a constant C-style string Type[3]: const char * Parameter[4]: Options depending on value of Parameter[3] Type[4]: ... Explanation: This function works like calling the system snprintf() with the limit (Parameter[2]) as the limit to snprintf() and then calling ustr_add_buf(). Function: ustr_add_fmt() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Parameter[3]: Options depending on value of Parameter[2] Type[3]: ... Explanation: This function works like calling the system snprintf() and then calling ustr_add_buf(). Function: ustr_dup_vfmt_lim() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Limit of data to dup Type[1]: size_t Parameter[2]: Pointer to a constant Ustr string Type[2]: const char * Parameter[3]: Variable argument list variable, from va_start() Type[3]: va_list Explanation: This function works like calling the system vsnprintf() with the limit (Parameter[2]) as the limit to vsnprintf() and then calling ustr_dup_buf(). Function: ustr_dup_vfmt() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Limit of data to dup Type[1]: size_t Parameter[2]: Pointer to a constant Ustr string Type[2]: const char * Parameter[3]: Variable argument list variable, from va_start() Type[3]: va_list Explanation: This function works like calling the system vsnprintf() and then calling ustr_dup_buf(). Function: ustr_dup_fmt_lim() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Limit of data to dup Type[1]: size_t Parameter[2]: Pointer to a constant Ustr string Type[2]: const char * Parameter[3]: Options depending on value of Parameter[2] Type[3]: ... Explanation: This function works like calling the system snprintf() with the limit (Parameter[2]) as the limit to snprintf() and then calling ustr_dup_buf(). Function: ustr_dup_fmt() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Pointer to a constant Ustr string Type[1]: const char * Parameter[2]: Options depending on value of Parameter[1] Type[2]: ... Explanation: This function works like calling the system snprintf() and then calling ustr_dup_buf(). Function: ustr_dupx_fmt_lim() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: Limit of data to dup Type[5]: size_t Parameter[6]: Pointer to a constant Ustr string Type[6]: const char * Parameter[7]: Options depending on value of Parameter[6] Type[7]: ... Explanation: This function works like calling the system snprintf() with the limit (Parameter[2]) as the limit to snprintf() and then calling ustr_dupx_buf(). Function: ustr_dupx_fmt() Returns: Pointer to a Ustr string Type: struct Ustr * Parameter[1]: Size of allocated storage Type[1]: size_t Parameter[2]: Number of bytes to use for reference count Type[2]: size_t Parameter[3]: Exact memory allocations Type[3]: int Parameter[4]: ENOMEM, memory error flag Type[4]: int Parameter[5]: Pointer to a constant Ustr string Type[5]: const char * Parameter[6]: Options depending on value of Parameter[5] Type[6]: ... Explanation: This function works like calling the system snprintf() and then calling ustr_dup_bufx(). Function: ustr_set_vfmt_lim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Limit of data to set Type[2]: size_t Parameter[3]: A pointer to a constant C-style string Type[3]: const char * Parameter[4]: Variable argument list variable, from va_start() Type[4]: va_list Explanation: This function works like calling ustr_del() for all the data and then ustr_add_vfmt_lim(). Function: ustr_set_vfmt() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Parameter[3]: Variable argument list variable, from va_start() Type[3]: va_list Explanation: This function works like calling ustr_del() for all the data and then ustr_add_vfmt(). Function: ustr_set_fmt_lim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Limit of data to set Type[2]: size_t Parameter[3]: A pointer to a constant C-style string Type[3]: const char * Parameter[4]: Options depending on value of Parameter[3] Type[4]: ... Explanation: This function works like calling ustr_del() for all the data and then ustr_add_fmt_lim(). Function: ustr_set_fmt() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Parameter[3]: Options depending on value of Parameter[2] Type[3]: ... Explanation: This function works like calling ustr_del() for all the data and then ustr_add_fmt(). Function: ustr_ins_vfmt_lim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[3]: Limit of data to insert Type[3]: size_t Parameter[4]: A pointer to a constant C-style string Type[4]: const char * Parameter[5]: Variable argument list variable, from va_start() Type[5]: va_list Explanation: This function works like calling the system vsnprintf() with the limit (Parameter[3]) as the limit to vsnprintf() and then calling ustr_ins_buf(). Function: ustr_ins_vfmt() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[3]: A pointer to a constant C-style string Type[3]: const char * Parameter[4]: Variable argument list variable, from va_start() Type[4]: va_list Explanation: This function works like calling the system vsnprintf() and then calling ustr_ins_buf(). Function: ustr_ins_fmt_lim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[3]: Limit of data to insert Type[3]: size_t Parameter[4]: A pointer to a constant C-style string Type[4]: const char * Parameter[5]: Options depending on value of Parameter[4] Type[5]: ... Explanation: This function works like calling the system snprintf() with the limit (Parameter[3]) as the limit to snprintf() and then calling ustr_ins_buf(). Function: ustr_ins_fmt() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position after which the data should be added Type[2]: size_t Parameter[3]: A pointer to a constant C-style string Type[3]: const char * Parameter[4]: Options depending on value of Parameter[3] Type[4]: ... Explanation: This function works like calling the system snprintf() and then calling ustr_ins_buf(). Function: ustr_sub_vfmt_lim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Limit of data to substitute Type[3]: size_t Parameter[4]: A pointer to a constant C-style string Type[4]: const char * Parameter[5]: Variable argument list variable, from va_start() Type[5]: va_list Explanation: This function works like calling the system vsnprintf() with the limit (Parameter[3]) as the limit to vsnprintf() and then calling ustr_sub_buf(). Function: ustr_sub_vfmt() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: A pointer to a constant C-style string Type[3]: const char * Parameter[4]: Variable argument list variable, from va_start() Type[4]: va_list Explanation: This function works like calling the system vsnprintf() and then calling ustr_sub_buf(). Function: ustr_sub_fmt_lim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Limit of data to substitute Type[3]: size_t Parameter[4]: A pointer to a constant C-style string Type[4]: const char * Parameter[5]: Options depending on value of Parameter[4] Type[5]: ... Explanation: This function works like calling the system snprintf() with the limit (Parameter[3]) as the limit to snprintf() and then calling ustr_sub_buf(). Function: ustr_sub_fmt() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: A pointer to a constant C-style string Type[3]: const char * Parameter[4]: Options depending on value of Parameter[3] Type[4]: ... Explanation: This function works like calling the system snprintf() and then calling ustr_sub_buf(). Function: ustr_sc_sub_vfmt_lim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: Limit of data to substitute Type[4]: size_t Parameter[5]: A pointer to a constant C-style string Type[5]: const char * Parameter[6]: Variable argument list variable, from va_start() Type[6]: va_list Explanation: This function works like calling the system vsnprintf() with the limit (Parameter[4]) as the limit to vsnprintf() and then calling ustr_sc_sub_buf(). Function: ustr_sc_sub_vfmt() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: A pointer to a constant C-style string Type[4]: const char * Parameter[5]: Variable argument list variable, from va_start() Type[5]: va_list Explanation: This function works like calling the system vsnprintf() and then calling ustr_sc_sub_buf(). Function: ustr_sc_sub_fmt_lim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: Limit of data to substitute Type[4]: size_t Parameter[5]: A pointer to a constant C-style string Type[5]: const char * Parameter[6]: Options depending on value of Parameter[5] Type[6]: ... Explanation: This function works like calling the system snprintf() with the limit (Parameter[3]) as the limit to snprintf() and then calling ustr_sc_sub_buf(). Function: ustr_sc_sub_fmt() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: A pointer to a constant C-style string Type[4]: const char * Parameter[5]: Options depending on value of Parameter[5] Type[5]: ... Explanation: This function works like calling the system snprintf() and then calling ustr_sc_sub_buf(). Section: Accessing the "variables" of a Ustr Function: ustr_len() Returns: The length of the Ustr Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function returns the length of the data within the Ustr, much like strlen() but without getting the value wrong in the case of extra NIL bytes. Function: ustr_cstr() Returns: Read-only pointer to the start of data in the Ustr Type: const char * Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function returns a read-only pointer to the start of the data of the Ustr string. Due to there always being a terminating NIL byte in a Ustr, this is also a valid C-style string. Function: ustr_wstr() Returns: Writable pointer to the start of data in the Ustr, or NULL Type: char * Parameter[1]: A pointer to a constant Ustr string Type[1]: struct Ustr * Explanation: This function returns a writable pointer to the start of the data of the Ustr string. Due to there always being a terminating NIL byte in a Ustr, this is also a valid C-style string. If the ustr is read-only (ustr_ro() == USTR_TRUE) then this function will return NULL. Note: Unless the string is owned (ustr_owner() == USTR_TRUE) it can be a very bad idea to use this to change data, as then all references will be updated. See ustr_sc_wstr(). Function: ustr_alloc() Returns: A boolean flag of either USTR_TRUE or USTR_FALSE Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function says if the Ustr is currently in allocated storage. Function: ustr_exact() Returns: A boolean flag of either USTR_TRUE or USTR_FALSE Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function says if the Ustr is doing exact allocations, so as the Ustr grows it will only have storage allocated exactly as required and not in half powers of two. Note: This will always be USTR_FALSE for read-only Ustr strings (ustr_ro() == USTR_TRUE), even though the default may be to used exact sized allocations when adding data to them etc. Function: ustr_sized() Returns: A boolean flag of either USTR_TRUE or USTR_FALSE Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function says if the Ustr stores an explicit allocation size, if not the size is implied as the next highest half power of two. Function: ustr_ro() Returns: A boolean flag of either USTR_TRUE or USTR_FALSE Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function says if the Ustr is current in read-only storage. Read-only storage is not writable but can be referenced via. ustr_dup() an infinite amount of times. Function: ustr_fixed() Returns: A boolean flag of either USTR_TRUE or USTR_FALSE Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function says if the Ustr is current in fixed size storage. Fixed size storage is writable but cannot be referenced. Note: Fixed size storage always explicitly stores the size of the storage. Function: ustr_enomem() Returns: A boolean flag of either USTR_TRUE or USTR_FALSE Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function just returns the value of the user settable flag in the Ustr. It can be set via. ustr_setf_enomem_err() and cleared by ustr_setf_enomem_clr(). This function is automatically set to on whever a memory allocation failure happens for a Ustr. Note: If a Ustr is referenced multiple times, ustr_setf_enomem_err() will fail. This always fails for Ustr's in read-only storage. Function: ustr_shared() Returns: A boolean flag of either USTR_TRUE or USTR_FALSE Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function says if the Ustr is in the "shared" mode. It can be set via. ustr_setf_shared() and cleared by ustr_setf_owner() on allocated Ustr's. Shared mode means that a Ustr can be referenced and unreferenced an infinite number of times. Note: This always succeeds for Ustr's in read-only storage. This always fails for Ustr's in fixed size storage. Function: ustr_limited() Returns: A boolean flag of either USTR_TRUE or USTR_FALSE Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function says if the Ustr is currently in fixed size storage and cannot move to allocated storage. Note: This always fails for Ustr's in allocated storage. This always fails for Ustr's in read-only storage. Function: ustr_owner() Returns: A boolean flag of either USTR_TRUE or USTR_FALSE Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function says if there is only a single reference to the Ustr string. Note: This always fails for Ustr's in read-only storage. This always succeeds for Ustr's in fixed size storage. Function: ustr_size() Returns: size_t Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function calculates the maximum amount of data that could be stored (Ie. the max ustr_len()) without having to re-size the Ustr string. Function: ustr_size_alloc() Returns: size_t Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function returns the size of the storage for the Ustr. Function: ustr_size_overhead() Returns: size_t Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function returns the difference between the size of the storage and the maximum amount of data that could be stored without having to re-size the Ustr string. Function: ustr_conf() Returns: Nothing Type: void Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Return size allocated number Type[2]: size_t * Parameter[3]: Return number of bytes used in the reference count Type[3]: size_t * Parameter[4]: Return exact allocations flag Type[4]: int * Parameter[5]: Return number of bytes used in the length Type[5]: size_t * Parameter[5]: Return number of references to this Ustr Type[5]: size_t * Explanation: This function gives the configuration of the current Ustr needed to duplicate it via. the ustr_dupx_*() functions. It also gives the number of bytes used for the length and the number of references, which are mainly informational. Note: This function differs from calling the ustr_exact() etc. functions in that it returns the global options if this Ustr isn't allocated, thus telling you what the configuration would be if the Ustr was turned into an allocated Ustr by adding data etc. Zero references for an allocated Ustr with a non-zero number of bytes for a reference count means it's in "shared" mode). Section: Setting the "flags" of a Ustr Function: ustr_setf_enomem_err() Returns: Success or failure Type: int Parameter[1]: A pointer to a Ustr string Type[1]: struct Ustr * Explanation: This function sets the enomem flag, which can be observed via. the ustr_enomem() function. The implication of setting this flag is that a memory error has occured in a previous function call on this Ustr. Note: This function fails if ustr_owner() fails for the Ustr. Function: ustr_setf_enomem_clr() Returns: Success or failure Type: int Parameter[1]: A pointer to a Ustr string Type[1]: struct Ustr * Explanation: This function clears the enomem flag, which can be observed via. the ustr_enomem() function. The implication of this flag being set is that a memory error has occured in a previous function call on this Ustr, so on clearing the flag you should know you have brought the Ustr back to a known state. Note: This function fails if ustr_owner() fails for the Ustr. Function: ustr_setf_share() Returns: Success or failure Type: int Parameter[1]: A pointer to a Ustr string Type[1]: struct Ustr * Explanation: This function sets the shared mode, which can be observed via. the ustr_shared() function. This is used on a Ustr so that it can have more references than it is able to hold in it's reference count. After this call the Ustr can be referenced and unreferenced an infinite number of times. Note: After this call the Ustr will never be deleted until ustr_setf_owner() is called. This function fails if ustr_alloc() fails for the Ustr. Function: ustr_setf_owner() Returns: Success or failure Type: int Parameter[1]: A pointer to a Ustr string Type[1]: struct Ustr * Explanation: This function removes the shared mode, which can be observed via. the ustr_shared() function. This is used so that a Ustr in shared mode can be free'd. Note: This function fails if ustr_alloc() fails for the Ustr. Section: Comparing data in a Ustr Function: ustr_cmp_buf() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to constant bytes, to compare Type[2]: const void * Parameter[3]: Length of comparison bytes Type[3]: size_t Explanation: This function works like memcmp() on the Ustr and the passed data. Function: ustr_cmp() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function works like ustr_cmp_buf() but with the data from ustr_cstr() and the length from ustr_len(). Function: ustr_cmp_subustr() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to compare from the Ustr Type[4]: size_t Explanation: This function works like ustr_cmp() but with a limit on the data and length. Function: ustr_cmp_cstr() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Explanation: This function works like ustr_cmp_buf() but with a length from strlen(). Function: ustr_cmp_fast_buf() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to constant bytes, to compare Type[2]: const void * Parameter[3]: Length of comparison bytes Type[3]: size_t Explanation: This function works like ustr_cmp_buf() but the order of comparison is optimized for speed, but is much less friendly to humans. Function: ustr_cmp_fast() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function works like ustr_cmp_fast_buf() but with the data from ustr_cstr() and the length from ustr_len(). Function: ustr_cmp_fast_subustr() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to compare from the Ustr Type[4]: size_t Explanation: This function works like ustr_cmp_fast() but with a limit on the data and length. Function: ustr_cmp_fast_cstr() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Explanation: This function works like ustr_cmp_fast_buf() but with a length from strlen(). Function: ustr_cmp_case_buf() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to constant bytes, to compare Type[2]: const void * Parameter[3]: Length of comparison bytes Type[3]: size_t Explanation: This function works like ustr_cmp_buf() but the order of comparison ignores ASCII case. Function: ustr_cmp_case() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function works like ustr_cmp_case_buf() but with the data from ustr_cstr() and the length from ustr_len(). Function: ustr_cmp_case_subustr() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to compare from the Ustr Type[4]: size_t Explanation: This function works like ustr_cmp_case() but with a limit on the data and length. Function: ustr_cmp_case_cstr() Returns: Less then zero, zero or greater than zero depending on comparison Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Explanation: This function works like ustr_cmp_case_buf() but with a length from strlen(). Function: ustr_cmp_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function works like comparing ustr_cmp() against 0. Function: ustr_cmp_buf_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to constant bytes, to compare Type[2]: const void * Parameter[3]: Length of comparison bytes Type[3]: size_t Explanation: This function works like comparing ustr_cmp_buf() against 0. Function: ustr_cmp_subustr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to compare from the Ustr Type[4]: size_t Explanation: This function works like comparing ustr_cmp_subustr() against 0. Function: ustr_cmp_cstr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Explanation: This function works like comparing ustr_cmp_cstr() against 0. Function: ustr_cmp_case_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function works like comparing ustr_cmp_case() against 0. Function: ustr_cmp_case_buf_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to constant bytes, to compare Type[2]: const void * Parameter[3]: Length of comparison bytes Type[3]: size_t Explanation: This function works like comparing ustr_cmp_case_buf() against 0. Function: ustr_cmp_case_subustr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to compare from the Ustr Type[4]: size_t Explanation: This function works like comparing ustr_cmp_case_subustr() against 0. Function: ustr_cmp_case_cstr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Explanation: This function works like comparing ustr_cmp_case_cstr() against 0. Function: ustr_cmp_prefix_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function works like comparing ustr_cmp() against 0, but the comparison is limited to the length of the right hand side. Function: ustr_cmp_prefix_buf_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to constant bytes, to compare Type[2]: const void * Parameter[3]: Length of comparison bytes Type[3]: size_t Explanation: This function works like comparing ustr_cmp_buf() against 0, but the comparison is limited to the length of the right hand side (Parameter[3]). Function: ustr_cmp_prefix_cstr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Explanation: This function works like comparing ustr_cmp_cstr() against 0, but the comparison is limited to the length of the right hand side. Function: ustr_cmp_prefix_subustr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to compare from the Ustr Type[4]: size_t Explanation: This function works like comparing ustr_cmp_subustr() against 0, but the comparison is limited to the given length (Parameter[4]). Function: ustr_cmp_case_prefix_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function works like comparing ustr_cmp_case() against 0, but the comparison is limited to the length of the right hand side. Function: ustr_cmp_case_prefix_buf_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to constant bytes, to compare Type[2]: const void * Parameter[3]: Length of comparison bytes Type[3]: size_t Explanation: This function works like comparing ustr_cmp_case_buf() against 0, but the comparison is limited to the length of the right hand side (Parameter[3]). Function: ustr_cmp_case_prefix_cstr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Explanation: This function works like comparing ustr_cmp_case_cstr() against 0, but the comparison is limited to the length of the right hand side. Function: ustr_cmp_case_prefix_subustr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to compare from the Ustr Type[4]: size_t Explanation: This function works like comparing ustr_cmp_case_subustr() against 0, but the comparison is limited to the given length (Parameter[4]). Function: ustr_cmp_suffix_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function works like ustr_cmp_prefix_eq() but compares the end of the left hand side. Function: ustr_cmp_suffix_buf_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to constant bytes, to compare Type[2]: const void * Parameter[3]: Length of comparison bytes Type[3]: size_t Explanation: This function works like ustr_cmp_prefix_buf_eq() but compares the end of the left hand side. Function: ustr_cmp_suffix_cstr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Explanation: This function works like ustr_cmp_prefix_cstr_eq() but compares the end of the left hand side. Function: ustr_cmp_suffix_subustr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to compare from the Ustr Type[4]: size_t Explanation: This function works like comparing ustr_cmp_subustr() against 0, but compares the end of the left hand side. Function: ustr_cmp_case_suffix_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Explanation: This function works like ustr_cmp_case_prefix_eq() but compares the end of the left hand side. Function: ustr_cmp_case_suffix_buf_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to constant bytes, to compare Type[2]: const void * Parameter[3]: Length of comparison bytes Type[3]: size_t Explanation: This function works like ustr_cmp_case_prefix_buf_eq() but compares the end of the left hand side. Function: ustr_cmp_case_suffix_cstr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant C-style string Type[2]: const char * Explanation: This function works like ustr_cmp_case_prefix_cstr_eq() but compares the end of the left hand side. Function: ustr_cmp_case_suffix_subustr_eq() Returns: Success or failure Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to compare from the Ustr Type[4]: size_t Explanation: This function works like comparing ustr_cmp_case_subustr() against 0, but compares the end of the left hand side. Section: Searching for data in a Ustr Function: ustr_srch_chr_fwd() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: Byte data to search for Type[3]: char Explanation: This function searches for the data (Parameter[3]) in the Ustr, skipping an offset (Parameter[2]) number of bytes. Function: ustr_srch_chr_rev() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: Byte data to search for Type[3]: char Explanation: This function works like ustr_srch_chr_fwd() but it searches from the end of the string to the beginning. Note: The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length. Function: ustr_srch_buf_fwd() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to data to search for Type[3]: const void * Parameter[4]: Length of the data to search for Type[4]: size_t Explanation: This function searches for the data (Parameter[3]) of length (Parameter[4]) in the Ustr, skipping an offset (Parameter[2]) number of bytes. Function: ustr_srch_buf_rev() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to data to search for Type[3]: const void * Parameter[4]: Length of the data to search for Type[4]: size_t Explanation: This function works like ustr_srch_buf_fwd() but it searches from the end of the string to the beginning. Note: The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length. Function: ustr_srch_fwd() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string, to search for Type[3]: const struct Ustr * Explanation: This function works like ustr_srch_buf_fwd() but it gets the data pointer by calling ustr_cstr() and the length by calling ustr_len() on the passed Ustr (Parameter[3]). Function: ustr_srch_rev() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string, to search for Type[3]: const struct Ustr * Explanation: This function works like ustr_srch_fwd() but it searches from the end of the string to the beginning. Note: The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length. Function: ustr_srch_cstr_fwd() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to C-style string data, to search for Type[3]: const char * Explanation: This function works like ustr_srch_buf_fwd() but it gets the length by calling strlen() on the passed data (Parameter[3]). Function: ustr_srch_cstr_rev() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to C-style string data, to search for Type[3]: const char * Explanation: This function works like ustr_srch_cstr_fwd() but it searches from the end of the string to the beginning. Note: The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length. Function: ustr_srch_subustr_fwd() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string Type[3]: const struct Ustr * Parameter[4]: Position in the Ustr Type[4]: size_t Parameter[5]: Length of data to search, from the Ustr Type[5]: size_t Explanation: This function works like ustr_srch_fwd() but it moves the data to start at the correct position and limits the length to the value specified. Function: ustr_srch_subustr_rev() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string Type[3]: const struct Ustr * Parameter[4]: Position in the Ustr Type[4]: size_t Parameter[5]: Length of data to search, from the Ustr Type[5]: size_t Explanation: This function works like ustr_srch_rev() but it moves the data to start at the correct position and limits the length to the value specified. Note: The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length. Function: ustr_srch_case_chr_fwd() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: Byte data to search for Type[3]: char Explanation: This function works like ustr_srch_chr_fwd(), but treats ASCII uppercase and lowercase as equivalent. Function: ustr_srch_case_chr_rev() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: Byte data to search for Type[3]: char Explanation: This function works like ustr_srch_chr_fwd(), but treats ASCII uppercase and lowercase as equivalent. Function: ustr_srch_case_buf_fwd() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to data to search for Type[3]: const void * Parameter[4]: Length of the data to search for Type[4]: size_t Explanation: This function works like ustr_srch_buf_fwd(), but treats ASCII uppercase and lowercase as equivalent. Function: ustr_srch_case_buf_rev() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to data to search for Type[3]: const void * Parameter[4]: Length of the data to search for Type[4]: size_t Explanation: This function works like ustr_srch_buf_rev(), but treats ASCII uppercase and lowercase as equivalent. Function: ustr_srch_case_fwd() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string, to search for Type[3]: const struct Ustr * Explanation: This function works like ustr_srch_fwd(), but treats ASCII uppercase and lowercase as equivalent. Function: ustr_srch_case_rev() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string, to search for Type[3]: const struct Ustr * Explanation: This function works like ustr_srch_rev(), but treats ASCII uppercase and lowercase as equivalent. Function: ustr_srch_case_cstr_fwd() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to C-style string data, to search for Type[3]: const char * Explanation: This function works like ustr_srch_cstr_fwd(), but treats ASCII uppercase and lowercase as equivalent. Function: ustr_srch_case_cstr_rev() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to C-style string data, to search for Type[3]: const char * Explanation: This function works like ustr_srch_cstr_rev(), but treats ASCII uppercase and lowercase as equivalent. Function: ustr_srch_case_subustr_fwd() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string Type[3]: const struct Ustr * Parameter[4]: Position in the Ustr Type[4]: size_t Parameter[5]: Length of data to search, from the Ustr Type[5]: size_t Explanation: This function works like ustr_srch_subustr_fwd(), but treats ASCII uppercase and lowercase as equivalent. Function: ustr_srch_case_subustr_rev() Returns: Position in the Ustr, or zero if not found Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start searching at Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string Type[3]: const struct Ustr * Parameter[4]: Position in the Ustr Type[4]: size_t Parameter[5]: Length of data to search, from the Ustr Type[5]: size_t Explanation: This function works like ustr_srch_subustr_rev(), but treats ASCII uppercase and lowercase as equivalent. Section: Span lengths of data in a Ustr Function: ustr_spn_chr_fwd() Returns: Number of bytes in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start spanning from Type[2]: size_t Parameter[3]: Byte data Type[3]: char Explanation: This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes. Function: ustr_spn_chr_rev() Returns: Number of bytes in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start spanning from Type[2]: size_t Parameter[3]: Byte data Type[3]: char Explanation: This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes. Function: ustr_spn_chrs_fwd() Returns: Number of bytes in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start spanning from Type[2]: size_t Parameter[3]: Array of byte data, for spanning Type[3]: const char * Parameter[4]: Length of byte data, for spanning Type[4]: size_t Explanation: This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes. Function: ustr_spn_chrs_rev() Returns: Number of bytes in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start spanning from Type[2]: size_t Parameter[3]: Array of byte data Type[3]: const char * Parameter[4]: Length of byte data Type[4]: size_t Explanation: This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes. Function: ustr_spn_fwd() Returns: Number of bytes in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string, containing spanning bytes Type[3]: const struct Ustr * Explanation: This function works like ustr_spn_buf_fwd() but passing ustr_cstr() and ustr_len() Function: ustr_spn_rev() Returns: Number of bytes in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string, containing spanning bytes Type[3]: const struct Ustr * Explanation: This function works like ustr_spn_buf_rev() but passing ustr_cstr() and ustr_len() Function: ustr_spn_cstr_fwd() Returns: Number of bytes in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant C-style string, containing spanning bytes Type[3]: const char * Explanation: This function works like ustr_spn_buf_fwd() but passing strlen() for the length. Function: ustr_spn_cstr_rev() Returns: Number of bytes in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant C-style string, containing spanning bytes Type[3]: const char * Explanation: This function works like ustr_spn_buf_rev() but passing strlen() for the length. Function: ustr_cspn_chr_fwd() Returns: Number of bytes not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start compliment spanning from Type[2]: size_t Parameter[3]: Byte data Type[3]: char Explanation: This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are not equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes. Function: ustr_cspn_chr_rev() Returns: Number of bytes not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start compliment spanning from Type[2]: size_t Parameter[3]: Byte data Type[3]: char Explanation: This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are not equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes. Function: ustr_cspn_chrs_fwd() Returns: Number of bytes not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start compliment spanning from Type[2]: size_t Parameter[3]: Array of byte data Type[3]: const char * Parameter[4]: Length of byte data Type[4]: size_t Explanation: This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are not equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes. Function: ustr_cspn_chrs_rev() Returns: Number of bytes not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start compliment spanning from Type[2]: size_t Parameter[3]: Array of byte data Type[3]: const char * Parameter[4]: Length of byte data Type[4]: size_t Explanation: This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are not equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes. Function: ustr_cspn_fwd() Returns: Number of bytes not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start compliment spanning from Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string, containing spanning bytes Type[3]: const struct Ustr * Explanation: This function works like ustr_cspn_buf_fwd() but passing ustr_cstr() and ustr_len() Function: ustr_cspn_rev() Returns: Number of bytes not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start compliment spanning from Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string, containing spanning bytes Type[3]: const struct Ustr * Explanation: This function works like ustr_cspn_buf_rev() but passing ustr_cstr() and ustr_len() Function: ustr_cspn_cstr_fwd() Returns: Number of bytes not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start compliment spanning from Type[2]: size_t Parameter[3]: A pointer to a constant C-style string, containing spanning bytes Type[3]: const char * Explanation: This function works like ustr_cspn_buf_fwd() but passing strlen() for the length. Function: ustr_cspn_cstr_rev() Returns: Number of bytes not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant C-style string, containing spanning bytes Type[3]: const char * Explanation: This function works like ustr_cspn_buf_rev() but passing strlen() for the length. Function: ustr_utf8_spn_chrs_fwd() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant C-style UTF-8 string Type[3]: const char * Parameter[4]: Length of the C-style UTF-8 string Type[4]: size_t Explanation: This function works like ustr_spn_chrs_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_spn_chrs_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes. Function: ustr_utf8_spn_chrs_rev() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant C-style UTF-8 string Type[3]: const char * Parameter[4]: Type[4]: size_t Explanation: This function works like ustr_spn_chrs_rev() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_spn_chrs_rev() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes. Function: ustr_utf8_spn_fwd() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant Ustr UTF-8 string Type[3]: const struct Ustr * Explanation: This function works like ustr_spn_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_spn_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes. Function: ustr_utf8_spn_rev() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant Ustr UTF-8 string Type[3]: const struct Ustr * Explanation: This function works like ustr_spn_rev() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_spn_rev() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes. Function: ustr_utf8_spn_cstr_fwd() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant C-style UTF-8 string Type[3]: const char * Explanation: This function works like ustr_spn_cstr_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_spn_cstr_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes. Function: ustr_utf8_spn_cstr_rev() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start spanning from Type[2]: size_t Parameter[3]: A pointer to a constant C-style UTF-8 string Type[3]: const char * Explanation: This function works like ustr_spn_cstr_rev() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_spn_cstr_rev() but given "xy" as a multi-byte UTF-8 character it understands that the span over "xyxz" is 1 UTF-8 character and not 3 bytes. Function: ustr_utf8_cspn_chrs_fwd() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from Type[2]: size_t Parameter[3]: A pointer to a constant C-style UTF-8 string Type[3]: const char * Parameter[4]: Length of the C-style UTF-8 string Type[4]: size_t Explanation: This function works like ustr_cspn_chrs_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_cspn_chrs_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes. Function: ustr_utf8_cspn_chrs_rev() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from Type[2]: size_t Parameter[3]: A pointer to a constant C-style UTF-8 string Type[3]: const char * Parameter[4]: Length of the C-style UTF-8 string Type[4]: size_t Explanation: This function works like ustr_cspn_chrs_rev() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_cspn_chrs_rev() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes. Function: ustr_utf8_cspn_fwd() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from Type[2]: size_t Parameter[3]: A pointer to a constant Ustr UTF-8 string, containing spanning data Type[3]: const struct Ustr * Explanation: This function works like ustr_cspn_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_cspn_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes. Function: ustr_utf8_cspn_rev() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from Type[2]: size_t Parameter[3]: A pointer to constant Ustr UTF-8 string data, containing spanning data Type[3]: const struct Ustr * Explanation: This function works like ustr_cspn_rev() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_cspn_rev() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes. Function: ustr_utf8_cspn_cstr_fwd() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from Type[2]: size_t Parameter[3]: A pointer to constant C-style UTF-8 string data, containing spanning data Type[3]: const char * Explanation: This function works like ustr_cspn_cstr_fwd() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_cspn_cstr_fwd() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes. Function: ustr_utf8_cspn_cstr_rev() Returns: Number of UTF-8 characters not in the span Type: size_t Parameter[1]: A pointer to a constant Ustr UTF-8 string Type[1]: const struct Ustr * Parameter[2]: Offset within string, in UTF-8 characters, to start compliment spanning from Type[2]: size_t Parameter[3]: A pointer to C-style UTF-8 string data, containing spanning data Type[3]: const char * Explanation: This function works like ustr_cspn_cstr_rev() but the return value, offset, and length all use UTF-8 characters and not bytes. Note: This is much slower than ustr_spn_cstr_rev() but given "xy" as a multi-byte UTF-8 character it understands that the compliment span over "xzxy" is 1 UTF-8 character and not 0 bytes. Section: Doing IO from or to a Ustr Function: ustr_io_get() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a C file object Type[2]: FILE * Parameter[3]: Number of bytes to read Type[3]: size_t Parameter[4]: Returned number of bytes read Type[4]: size_t * Explanation: This function tries to read a minimum number of bytes from the file object, into the Ustr string. The exact number read is returned, unless (Parameter[4]) is NULL. Function: ustr_io_getfile() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a C file object Type[2]: FILE * Explanation: This function calls ustr_io_get() rpeatedly until EOF is encountered. Note: The errno value when this function ends could either be from fopen(), fread(), or if both of the those succeeded from fclose(). Function: ustr_io_getfilename() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A C-style string of a filename Type[2]: const char * Explanation: This function opens a specified file, and then calls ustr_io_getfile(). Finally closing the FILE * object. Function: ustr_io_getdelim() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a C file object Type[2]: FILE * Parameter[3]: A delimiter byte to stop reading at Type[3]: char Explanation: This function reads bytes from the file until it hits the delimiter byte. Note: The delimiter is included, use ustr_del() to remove 1 byte from the end if you don't want it. This function assumes a delimiter will happen every 80 bytes or so. Function: ustr_io_getline() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a C file object Type[2]: FILE * Explanation: This function works like calling ustr_io_getdelim() with '\n' as the delimiter. Function: ustr_io_put() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a C file object Type[2]: FILE * Parameter[3]: Number of bytes to write Type[3]: size_t Explanation: This function is the opposite of ustr_io_get(), taking bytes from the beginning of the Ustr and writting them to the file. Note: Deleting bytes from the begining of a Ustr string is the most inefficient thing to do, so it is recommended to use ustr_io_putfile(). Function: ustr_io_putline() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a C file object Type[2]: FILE * Parameter[3]: Number of bytes to write Type[3]: size_t Explanation: This function works like calling ustr_io_put(), and then writting a '\n' to the file. Note: This doesn't write a line from the Ustr to the file, if you want that call ustr_io_put() directly, using the return from ustr_srch_chr_fwd() (with a '\n') as the number of bytes argument. Function: ustr_io_putfile() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a C file object Type[2]: FILE * Explanation: This function works like calling ustr_io_put() with ustr_len() as the number of bytes. Function: ustr_io_putfileline() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a C file object Type[2]: FILE * Explanation: This function works like calling ustr_io_putline() with ustr_len() as the number of bytes. Function: ustr_io_putfilename() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A C-style string of a filename Type[2]: const char * Parameter[3]: A C-style string of a filemode (the second argument to fopen) Type[3]: const char * Explanation: This function opens a specified file, and then calls ustr_io_putfile(). Finally closing the FILE * object. Note: The errno value when this function ends could either be from fopen(), fwrite(), or if both of the those succeeded from fclose(). Section: String substitution/replacement Function: ustr_sub_undef() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of undefined data Type[3]: size_t Explanation: The Ustr string is expanded as required (possibly reallocated) so that it can contain length (Parameter[2]) data, from the required position. If the length is not zero the Ustr will be writable. Or it'll return USTR_FALSE (zero) on failure. Note: You can think of the operation as two seperate tasks, one which makes the current data in the Ustr undefined and the second which adds undefined data to the ustr to accomodate the desired length. Function: ustr_sub_buf() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Buffer containing substitution string Type[3]: const void * Parameter[4]: Length of buffer Type[4]: size_t Explanation: This function works as if you had called ustr_sub_undef() and then copied the data into the new undefined space. Function: ustr_sub_cstr() Returns: success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: A pointer to a constant C-style string, which is the substitution Type[3]: const char * Explanation: This function works like ustr_sub_buf() but the length is worked out automatically by strlen(). Function: USTR_SUB_OSTR() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: A constant C-style string Type[3]: const char [] Explanation: This function works as if you had called ustr_sub_buf() and passed sizeof() - 1 as the length. Function: USTR_SUB_OBJ() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: A symbol Type[3]: ... Explanation: This function works as if you had called ustr_sub_buf() and passed sizeof() as the length. Note: In most cases you'll want to use USTR_SUB_OSTR(). Function: ustr_sub() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string Type[3]: const struct Ustr * Explanation: This function works as if you had called ustr_sub_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added. The exception being if you substitute a ustr into itself, while only having a single reference count, the simple method could access a free'd ustr data, but this function just works. Function: ustr_sub_subustr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: A pointer to a constant Ustr string Type[3]: const struct Ustr * Parameter[4]: Position in the Ustr Type[4]: size_t Parameter[5]: Length to substitute from the Ustr Type[5]: size_t Explanation: This function mostly as if you had called ustr_sub_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be insed. The exception being if you insert a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works. Function: ustr_sc_sub_undef() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: Length of undefined data Type[4]: size_t Explanation: This function works as if you had done ustr_del_subustr() followed by ustr_ins_undef(), however it is significantly more efficient. Function: ustr_sc_sub_buf() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: Buffer containting substitute data Type[4]: const void * Parameter[5]: Length of Buffer Type[5]: size_t Explanation: This function will substitute a specific number of characters in a Ustr with the data from a buffer, this function does the job of one or more of ustr_add_buf(), ustr_sub_buf() and ustr_del(). Function: ustr_sc_sub_cstr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr Type[1]: struct Ustr ** Parameter[2]: Position where to start replacement Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: A pointer to a constant C-style string, containing spanning bytes Type[4]: const char * Explanation: This function works like ustr_sc_sub_buf() but the length is worked out automatically by strlen(). Function: ustr_sc_sub() Returns: success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: Pointer to a Ustr containing the substitute string Type[4]: const struct Ustr * Explanation: This function works as if you had called ustr_sc_sub_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added. The exception being if you substitute a ustr into itself, while only having a single reference count, the simple method could access a free'd ustr data, but this function just works. Function: ustr_sc_sub_subustr() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: A pointer to a constant Ustr string Type[4]: const struct Ustr * Parameter[5]: Position in the Ustr Type[5]: size_t Parameter[6]: Length to substitute from the Ustr Type[6]: size_t Explanation: This function mostly as if you had called ustr_sc_sub_buf() with the ustr_cstr() + position - 1 and length values of the Ustr string to be insed. The exception being if you insert a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works. Function: USTR_SC_SUB_OSTR() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: A constant C-style string Type[4]: const char [] Explanation: This function works as if you had called ustr_sc_sub_buf() and passed sizeof() - 1 as the length. Function: USTR_SC_SUB_OBJ() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Position where to start substitution Type[2]: size_t Parameter[3]: Length of substitution Type[3]: size_t Parameter[4]: A symbol Type[4]: ... Explanation: This function works as if you had called ustr_sc_sub_buf() and passed sizeof() as the length. Note: In most cases you'll want to use USTR_SUB_OSTR(). Function: ustr_replace_buf() Returns: Number of tokens replaced Type: size_t Parameter[1]: Pointer to a pointer to a Ustr (haystack) Type[1]: struct Ustr ** Parameter[2]: Buffer containting search data Type[2]: const void * Parameter[3]: Length of search buffer Type[3]: size_t Parameter[4]: Buffer containting replacement data Type[4]: const void * Parameter[5]: Length of replacement buffer Type[5]: size_t Parameter[6]: Maximum number of matches to replace (0 for unlimited) Type[6]: size_t Explanation: This function scans the "haystack" (Parameter[1]) for "needle" (Parameter[2]) and replaces max_replacements (Parameter[6]) matches with the "replacement" (Parameter[4]). Note: If max_replacements (Parameter[6]) is 0, this function will replace ALL occurrences. Function: ustr_replace_cstr() Returns: Number of tokens replaced Type: size_t Parameter[1]: Pointer to a pointer to a Ustr (haystack) Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant C-style string, containing search bytes Type[2]: const char * Parameter[3]: A pointer to a constant C-style string, containing replacement bytes Type[3]: const char * Parameter[4]: Maximum number of matches to replace (0 for unlimited) Type[4]: size_t Explanation: This function works like ustr_replace_buf() but gets the lengths for the buffer automatically from strlen(). Function: ustr_replace() Returns: Number of tokens replaced Type: int Parameter[1]: Pointer to a pointer to a Ustr (haystack) Type[1]: struct Ustr ** Parameter[2]: Ustr to search for (needle) Type[2]: const struct Ustr * Parameter[3]: Ustr to replace needle with Type[3]: const struct Ustr * Parameter[4]: Maximum number of matches to replace (0 for unlimited) Type[4]: size_t Explanation: This function works like ustr_replace_buf() but gets the lengths from the ustr automatically. Function: ustr_replace_rep_chr() Returns: number of replacements made Type: size_t Parameter[1]: pointer to a pointer to a Ustr to be modified Type[1]: struct Ustr **ps1 Parameter[2]: character to replace Type[2]: char Parameter[3]: number of characters to replace Type[3]: size_t Parameter[4]: character to replace with Type[4]: char Parameter[5]: number of characters to replace with Type[5]: size_t nlen Parameter[6]: maximum number of replacements to make (use 0 for unlimited) Type[6]: size_t lim Explanation: This function replaces a repeating sequence of characters with another repeating sequence of characters. For example... Ustr *data = ustr_dup_cstr("xxxBxxCxDxxx"); ustr_replace_rep_chr(&data,'x',2,'y',1, 0) ...would change data to be "yxByCxDyx". Note: Changing the same letter the same number of times is considered a No-op since it is a vast performance improvement this way. So passing in (&data,'y',2,'y',2 ,0) will have a return value of 0 and the string will be unchanged. Section: Splitting a Ustr Function: ustr_split_buf() Returns: pointer to a Ustr representing the next token Type: struct Ustr * Parameter[1]: Pointer to a constant Ustr to be split Type[1]: const struct Ustr * Parameter[2]: Pointer to an offset Type[2]: size_t * Parameter[3]: Buffer to use as split search pattern Type[3]: const void * Parameter[4]: Length of buffer Type[4]: size_t Parameter[5]: Pointer to a Ustr to be used as the return value Type[5]: struct Ustr * Parameter[6]: Flags with the prefix USTR_FLAG_SPLIT_ Type[6]: unsigned int Explanation: This function works in a manner similar to strtok(). Each time the function is called, the string inside of the buffer (Parameter[3]) is used as a search pattern at which to split. If the pattern is not found, the entire string will be returned. A USTR_NULL return value indicates there are no more tokens remaining. Parameter[5] is a a pointer to a Ustr where the return value will be placed. Passing a USTR_NULL to this parameter will cause the string to be allocated and **MUST** be freed **manually**. If, however, you pass in a non-null Ustr to this parameter, each call to ustr_split_buf() will free what is in this pointer and place the new token there (when USTR_NULL is returned, nothing needs to be free'd). For example, given... Ustr *data = ...; Ustr *tok = USTR_NULL; const char *sep = ","; size_t off = 0; unsigned int flags = USTR_FLAGS_SPLIT_DEF; ...there are two options... while ((tok = ustr_split_buf(data, &off, sep, strlen(sep), tok, flags))) { /* Do something with tok -- but next iteration of the loop will free * and overwrite tok, so you must ustr_dup() if you want to keep it */ } /* tok is now NULL again after the loop */ ...or... while ((tok = ustr_split_buf(data, &off, sep, strlen(sep), USTR_NULL, flags))) { /* Do something with tok, and it will NOT be freed in the next iteration of * the loop */ ustr_free(tok); /* have to free to avoid mem leaks */ } ...the former of which being the safer option. Note: There are several flags that will alter the behaviour of this function, all of which have a common with the default being USTR_FLAG_SPLIT_DEF. If you are calling this function directly, it is very likely that you'd want to use ustr_split_cstr() instead. Function: ustr_split() Returns: Pointer to a Ustr representing the next token Type: struct Ustr * Parameter[1]: Pointer to a constant Ustr to be split Type[1]: const struct Ustr * Parameter[2]: Pointer to an offset variable Type[2]: size_t * Parameter[3]: Pointer to a constant Ustr to use as the split search pattern Type[3]: const struct Ustr * Parameter[4]: Pointer to a Ustr where the return value will be placed Type[4]: struct Ustr * Parameter[5]: Flags Type[5]: unsigned int Explanation: Works like ustr_split_buf() but takes a Ustr as the split search pattern instead. Function: ustr_split_cstr() Returns: Pointer to a Ustr representing the next token Type: struct Ustr * Parameter[1]: Pointer to a constant Ustr to be split Type[1]: const struct Ustr * Parameter[2]: Pointer to an offset variable Type[2]: size_t * Parameter[3]: C string to use as split search pattern Type[3]: const char * Parameter[4]: Pointer to a Ustr where the return value will be placed Type[4]: struct Ustr * Parameter[5]: Flags Type[5]: unsigned int Explanation: Works like ustr_split_buf() but takes a C string as the split search pattern, and so gets the length via. strlen(). Function: ustr_split_spn_chrs() Returns: Pointer to a Ustr representing the next token Type: struct Ustr * Parameter[1]: Pointer to a Ustr to be split Type[1]: const struct Ustr * Parameter[2]: Pointer to an offset variable Type[2]: size_t * Parameter[3]: String representing a set of bytes to use as split chars Type[3]: const char * Parameter[4]: Length of the string of set of bytes Type[4]: size_t Parameter[5]: Pointer to a Ustr where the return value will be placed Type[5]: struct Ustr * Parameter[6]: flags Type[6]: unsigned int Explanation: Works like ustr_split_buf() but uses the individual ASCII bytes in the separator string (Parameter[3]) as search patterns. It will split if **ANY** of these individual characters are matched (much like strtok()). For example: if splitting "this, is,a test" with the separator string ", " the tokens returned would be {"this" "is" "a" "test"}; Note: If you are calling this function directly, it is very likely that you'd want to use ustr_split_spn_cstr() instead. Function: ustr_split_spn_cstr() Returns: Pointer to a Ustr representing the next token Type: struct Ustr * Parameter[1]: Pointer to a Ustr to be split Type[1]: const struct Ustr * Parameter[2]: Pointer to an offset variable Type[2]: size_t * Parameter[3]: String representing a set of bytes to use as split chars Type[3]: const char * Parameter[4]: Pointer to a Ustr where the return value will be placed Type[4]: struct Ustr * Parameter[5]: flags Type[5]: unsigned int Explanation: Works like ustr_split_spn_chrs() but gets the length automatically via. strlen(). Function: ustr_split_spn() Returns: Pointer to a Ustr representing the next token Type: struct Ustr * Parameter[1]: Pointer to a constant Ustr to be split Type[1]: const struct Ustr * Parameter[2]: Pointer to an offset variable Type[2]: size_t * Parameter[3]: Pointer to a constant Ustr to use as the split search pattern Type[3]: const struct Ustr * Parameter[4]: Pointer to a Ustr where the return value will be placed Type[4]: struct Ustr * Parameter[5]: Flags Type[5]: unsigned int Explanation: Works like ustr_split_spn_chrs() but takes a Ustr as the split chars instead. Section: Dealing with UTF-8 in a Ustr Function: ustr_utf8_valid() Returns: A boolean flag of either USTR_TRUE or USTR_FALSE Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function tries it's best to find out if the string is a valid utf-8 string. Function: ustr_utf8_len() Returns: The number of the utf-8 characters in the Ustr Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function counts the number of utf-8 characters inn the Ustr. Note: This function gives undefined answers on strings that aren't utf-8 valid. Function: ustr_utf8_width() Returns: ssize_t Type: ssize_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Explanation: This function returns the visible width of the string, assuming it is a valid utf-8 string. This is like converting to wide characters and using wcwidth(). Function: ustr_utf8_chars2bytes() Returns: Length of span in bytes Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Position of a span in utf-8 characters Type[2]: size_t Parameter[3]: Length of a span in utf-8 characters Type[3]: size_t Parameter[4]: Returns the position of the span in bytes Type[4]: size_t * Explanation: This function converts a span, in utf-8 characters, to the same span in bytes. Function: ustr_utf8_bytes2chars() Returns: Returns the position of a span in utf-8 characters Type: size_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Position of a span in bytes Type[2]: size_t Parameter[3]: Length of a span in bytes Type[3]: size_t Parameter[4]: Returns length of a span in utf-8 characters Type[4]: size_t * Explanation: This function converts a span, in bytes, to the same span in utf-8 characters. Note: Because a byte span can start or end within a utf-8 character, converting the return values back into bytes via. ustr_utf8_chars2bytes() may make the span be slightly bigger (position slightly earlier, and the length slightly longer). Function: ustr_sc_utf8_reverse() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function reverses the utf-8 characters in the Ustr string, assuming it is a valid utf-8 string, so the last one becomes the first and the second to last becomes the second etc. Section: Parsing ASCII integer numbers from a Ustr Function: ustr_parse_uintmaxx() Returns: Parsed number, or zero on error Type: uintmax_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_ Type[3]: unsigned int Parameter[4]: Absolute minimum value Type[4]: uintmax_t Parameter[5]: Absolute maximum value Type[5]: uintmax_t Parameter[6]: Thousands separator Type[6]: const char * Parameter[7]: Return length of parsed number Type[7]: size_t * Parameter[8]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ Type[8]: unsigned int * Explanation: This function parses an ASCII representation of a number from a Ustr (Parameter[1]) starting at the offset (Parameter[2]). Note: If stdint.h isn't available this function won't be available. Function: ustr_parse_uintmax() Returns: Parsed number, or zero on error Type: uintmax_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_ Type[3]: unsigned int Parameter[4]: Return length of parsed number Type[4]: size_t * Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ Type[5]: unsigned int * Explanation: This function works like ustr_parse_uintmaxx() with the minimum and maximum values taken as 0 and UINTMAX_MAX, and the thousands separator as "_". Note: If stdint.h isn't available this function won't be available. Function: ustr_parse_intmax() Returns: Parsed number, or zero on error Type: intmax_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_ Type[3]: unsigned int Parameter[4]: Return length of parsed number Type[4]: size_t * Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ Type[5]: unsigned int * Explanation: This function works like ustr_parse_uintmaxx() with the minimum and maximum values taken as -INTMAX_MIN and INTMAX_MAX, and the thousands separator as "_". Note: If stdint.h isn't available this function won't be available. Function: ustr_parse_ulongx() Returns: Parsed number, or zero on error Type: unsigned long Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_ Type[3]: unsigned int Parameter[4]: Absolute minimum value Type[4]: unsigned long Parameter[5]: Absolute maximum value Type[5]: unsigned long Parameter[6]: Thousands separator Type[6]: const char * Parameter[7]: Return length of parsed number Type[7]: size_t * Parameter[8]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ Type[8]: unsigned int * Explanation: This function works like ustr_parse_uintmaxx() but returns an unsigned long, it is always available even when stdint.h isn't. Function: ustr_parse_ulong() Returns: Parsed number, or zero on error Type: unsigned long Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_ Type[3]: unsigned int Parameter[4]: Return length of parsed number Type[4]: size_t * Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ Type[5]: unsigned int * Explanation: This function works like ustr_parse_ulongx() with the minimum and maximum values taken as 0 and ULONG_MAX, and the thousands separator as "_". Function: ustr_parse_long() Returns: Parsed number, or zero on error Type: long Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_ Type[3]: unsigned int Parameter[4]: Return length of parsed number Type[4]: size_t * Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ Type[5]: unsigned int * Explanation: This function works like ustr_parse_ulongx() with the minimum and maximum values taken as -LONG_MIN and LONG_MAX, and the thousands separator as "_". Function: ustr_parse_uint() Returns: Parsed number, or zero on error Type: unsigned int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_ Type[3]: unsigned int Parameter[4]: Return length of parsed number Type[4]: size_t * Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ Type[5]: unsigned int * Explanation: This function works like ustr_parse_ulongx() with the minimum and maximum values taken as 0 and UINT_MAX, and the thousands separator as "_". Function: ustr_parse_int() Returns: Parsed number, or zero on error Type: int Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_ Type[3]: unsigned int Parameter[4]: Return length of parsed number Type[4]: size_t * Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ Type[5]: unsigned int * Explanation: This function works like ustr_parse_ulongx() with the minimum and maximum values taken as -INT_MIN and INT_MAX, and the thousands separator as "_". Function: ustr_parse_ushort() Returns: Parsed number, or zero on error Type: unsigned short Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_ Type[3]: unsigned int Parameter[4]: Return length of parsed number Type[4]: size_t * Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ Type[5]: unsigned int * Explanation: This function works like ustr_parse_ulongx() with the minimum and maximum values taken as 0 and USHRT_MAX, and the thousands separator as "_". Function: ustr_parse_short() Returns: Parsed number, or zero on error Type: short Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Parameter[3]: Base (2-36) and flags, starting with USTR_FLAG_PARSE_NUM_ Type[3]: unsigned int Parameter[4]: Return length of parsed number Type[4]: size_t * Parameter[5]: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ Type[5]: unsigned int * Explanation: This function works like ustr_parse_ulongx() with the minimum and maximum values taken as -SHRT_MIN and SHRT_MAX, and the thousands separator as "_". Section: Misc shortcut helper functions for Ustrs Function: ustr_sc_ensure_owner() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function makes sure that the Ustr string is owned when it returns (Ie. ustr_owner() returns USTR_TRUE), or it fails to allocate. Function: ustr_sc_wstr() Returns: Writable pointer to the start of data in the Ustr, or NULL Type: char * Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function works like calling ustr_sc_ensure_owner(), to make sure the Ustr string is writable, and if that succeeds it returns ustr_wstr(). On failure it returns NULL. Function: ustr_sc_export_subustr() Returns: A pointer to newly allocated block of memory Type: char * Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Position in the Ustr Type[2]: size_t Parameter[3]: Length to export from the Ustr Type[3]: size_t Parameter[4]: Allocation function (like malloc) Type[4]: void *(*)(size_t) Explanation: This function allocates a block of memory of size Length (Parameter[3]) + 1 using the provided allocation function (Parameter[4]) and copies the data starting from Position (Parameter[2]) within the ustr. Function: ustr_sc_export() Returns: A pointer to newly allocated block of memory Type: char * Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Allocation function (like malloc) Type[2]: void *(*)(size_t) Explanation: This function works like calling ustr_sc_export_subustr() with a position of 1 and a length of ustr_len(). Function: ustrp_sc_export_subustrp() Returns: A pointer to newly allocated block of memory Type: char * Parameter[1]: Pointer to a Ustr pool object Type[1]: struct Ustr_pool * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Position in the Ustr Type[3]: size_t Parameter[4]: Length to export from the Ustr Type[4]: size_t Parameter[5]: Allocation function (like malloc), or NULL Type[5]: void *(*)(size_t) Explanation: This function allocates a block of memory of size Length (Parameter[4]) + 1 using either the provided allocation function (Parameter[5]), or from the pool object if the allocation function is NUL, and copies the data starting from Position (Parameter[3]) within the ustr. Function: ustrp_sc_export() Returns: A pointer to newly allocated block of memory Type: char * Parameter[1]: Pointer to a Ustr pool object Type[1]: struct Ustr_pool * Parameter[2]: A pointer to a constant Ustr string Type[2]: const struct Ustr * Parameter[3]: Allocation function (like malloc) Type[3]: void *(*)(size_t) Explanation: This function works like calling ustrp_sc_export_subustrp() with a position of 1 and a length of ustrp_len(). Function: ustr_sc_reverse() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function reverses all the bytes in the Ustr string, so the last one becomes the first and the second to last becomes the second etc. Function: ustr_sc_tolower() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function changes any ASCII upper case bytes into ASCII lower case bytes. Function: ustr_sc_toupper() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Explanation: This function changes any ASCII lower case bytes into ASCII upper case bytes. Function: ustr_sc_ltrim_chrs() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Array of bytes, containing trimming data Type[2]: const char * Parameter[3]: Length of byte data Type[3]: size_t Explanation: This function deletes the bytes at the begining of the Ustr (Parameter[1]) that are in the span (Parameter[2]) of the specificed length (parameter[2]). Function: ustr_sc_ltrim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant Ustr string, containing trimming bytes Type[2]: const struct Ustr * Explanation: This function works as if you had called ustr_sc_ltrim_chrs() and passed ustr_cstr() and ustr_len() values of the Ustr string (Parameter[2]). Function: ustr_sc_ltrim_cstr() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant C-style string, containing trimming bytes Type[2]: const char * Explanation: This function works as if you had called ustr_sc_ltrim_chrs() and passed strlen() as the length. Function: ustr_sc_rtrim_chrs() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Array of bytes, containing trimming data Type[2]: const char * Parameter[3]: Length of byte data Type[3]: size_t Explanation: This function deletes the bytes at the end of the Ustr (Parameter[1]) that are in the span (Parameter[2]) of the specificed length (parameter[2]). Function: ustr_sc_rtrim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant Ustr string, containing trimming bytes Type[2]: const struct Ustr * Explanation: This function works as if you had called ustr_sc_rtrim_chrs() and passed ustr_cstr() and ustr_len() values of the Ustr string (Parameter[2]). Function: ustr_sc_rtrim_cstr() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant C-style string, containing trimming bytes Type[2]: const char * Explanation: This function works as if you had called ustr_sc_rtrim_chrs() and passed strlen() as the length. Function: ustr_sc_trim_chrs() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Array of bytes, containing trimming data Type[2]: const char * Parameter[3]: Length of byte data Type[3]: size_t Explanation: This function deletes the bytes at the begining or end of the Ustr (Parameter[1]) that are in the span (Parameter[2]) of the specificed length (parameter[2]). Note: Calling this function is much more efficient than calling ustr_sc_rtrim_chrs() and then ustr_sc_ltrim_chrs(), as both ends are trimmed in a single pass. Function: ustr_sc_trim() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant Ustr string, containing trimming bytes Type[2]: const struct Ustr * Explanation: This function works as if you had called ustr_sc_trim_chrs() and passed ustr_cstr() and ustr_len() values of the Ustr string (Parameter[2]). Function: ustr_sc_trim_cstr() Returns: Success or failure Type: int Parameter[1]: A pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: A pointer to a constant C-style string, containing trimming bytes Type[2]: const char * Explanation: This function works as if you had called ustr_sc_trim_chrs() and passed strlen() as the length. Section: Adding binary data to a Ustr Function: ustr_add_b_uint16() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Binary value to add to the Ustr Type[2]: uint_least16_t Explanation: This function adds a binary representation of a value (Parameter[2]) to the Ustr (Parameter[1]). Function: ustr_add_b_uint32() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Binary value to add to the Ustr Type[2]: uint_least32_t Explanation: This function adds a binary representation of a value (Parameter[2]) to the Ustr (Parameter[1]). Function: ustr_add_b_uint64() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Binary value to add to the Ustr Type[2]: uint_least64_t Explanation: This function adds a binary representation of a value (Parameter[2]) to the Ustr (Parameter[1]). Section: Parsing binary data from a Ustr Function: ustr_parse_b_uint16() Returns: uint_least16_t Type: uint_least16_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Explanation: This function parses a binary representation from a Ustr (Parameter[1]) starting at the offset (Parameter[2]). Function: ustr_parse_b_uint32() Returns: uint_least32_t Type: uint_least32_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Explanation: This function parses a binary representation from a Ustr (Parameter[1]) starting at the offset (Parameter[2]). Function: ustr_parse_b_uint64() Returns: uint_least64_t Type: uint_least64_t Parameter[1]: A pointer to a constant Ustr string Type[1]: const struct Ustr * Parameter[2]: Offset within string to start parsing at Type[2]: size_t Explanation: This function parses a binary representation from a Ustr (Parameter[1]) starting at the offset (Parameter[2]). Section: Misc. functions Function: ustr_realloc() Returns: Success or failure Type: int Parameter[1]: Pointer to a pointer to a Ustr string Type[1]: struct Ustr ** Parameter[2]: Size of allocation Type[2]: size_t Explanation: This function is re-sizes the Ustr to the specified size (Parameter[2]). This is mostly used to shrink a sized Ustr that is now significantly smaller than it once was. Although this function can also grow a Ustr. Note: To have a size that isn't implied from the length the Ustr must store a size value as well as a length (ustr_sized() must return USTR_TRUE). Function: ustr_cntl_opt() Returns: Success or failure Type: int Parameter[1]: Optional value starting with USTR_CNTL_OPT_ Type[1]: int Parameter[2]: Arugments to option Type[2]: ... Explanation: This function views and/or changes global Ustr options, like whether ustr's have an implicit or explicit size (USTR_CNTL_OPT_GET_HAS_SIZE). Section: Simple Ustr pool API Function: ustr_pool_ll_make() Returns: Pointer to a Ustr pool object Type: struct Ustr_pool * Parameter[1]: Nothing Type[1]: void Explanation: This allocates a new pool using the "linked list" strategy, each allocation in the pool is added to a linked list ... and any allocations not freed directly are freed by the pool when it is cleared or freed. Function: ustr_pool_make_subpool() Returns: Pointer to a Ustr pool object Type: struct Ustr_pool * Parameter[1]: struct Ustr_pool * Type[1]: struct Ustr_pool * Explanation: This allocates a new pool as a child of the passed in pool (Parameter[1]), The pool can be freed and cleared independantly of the parent pool however free and clear operations on the parent pool are automatically applied to all child pools. Function: ustr_pool_free() Returns: Nothing Type: void Parameter[1]: Pointer to a Ustr pool object Type[1]: struct Ustr_pool * Explanation: This deallocates a pool, and all sub-pools. Note: This also operates on all sub-pools. Function: ustr_pool_clear() Returns: Nothing Type: void Parameter[1]: Pointer to a Ustr pool object Type[1]: struct Ustr_pool * Explanation: This allows all the data in the pool to be reused, it may also free some/all of the data in the pool, from the pool API. Note: This also operates on all sub-pools. ustr-1.0.4/Documentation/txt2html.pl0000755000076400007640000002035610760727104016452 0ustar jamesjames#! /usr/bin/perl -w use strict; use FileHandle; my $docs = undef; if (0) {} elsif (-d "./Documentation") # In main dir... { $docs ="./Documentation"; } elsif (-d "../Documentation") # Probably in the docs dir... { $docs ="../Documentation"; } if (!defined ($docs)) { STDERR->print("Can't find Documentation.\n"); exit (1); } # FIXME: More C&P of VERSION my $name = "Ustr - 1.0.4 reference documentation"; my $html_header = "\n\n\n"; my $html_body = < A:visited { color: #ff4040; } A:hover { color: #20b2aa; } P { text-indent: 1em; } body { background: #FFF; color: #000; } h2.ind { background: #DDF; } td.title { background: #DFD; } td.sect { background: #DDF; } td.obj { background: #DDD; } ul li { list-style-type: lower-roman; } ul li:hover { list-style-type: square; } ul:hover li { list-style-type: decimal; } ul li:hover ul li.obj { list-style-type: decimal; } ul li:hover ul li.obj:hover { list-style-type: square; } EOF my $html_footer = "\n\n"; sub convert_index { my $ftype = shift; my $in_pre_tag = 0; my $txt_indx_ful = "

    \n"; my $txt_indx_min = "
      \n"; my $mem_count = 0; my $mem_tot = 0; my $done = 0; while () { if (/^(Constant|Function|Member): (.*)$/) { my $name = $2; my $uri = $2; $uri =~ s/[^[:alnum:]:_]//g; $txt_indx_ful .= "
    • $name\n"; ++$mem_count; } elsif (/^Section:\s*(.*)$/) { my $section = $1; my $uri = $1; $uri =~ s/\s/_/g; $uri =~ s/[^[:alnum:]:_]//g; if ($done) { $txt_indx_min .= " ($mem_count)\n"; $mem_tot += $mem_count; $mem_count = 0; $txt_indx_ful .= "
    "; } $done = 1; $txt_indx_min .= "
  • $section"; $txt_indx_ful .= "
  • $section\n
      \n"; } } $mem_tot += $mem_count; OUT->print("

      ", "$name -- $ftype ($mem_tot)", "

      ", "\n"); OUT->print("
      \n"); OUT->print("

      Index of sections

      \n"); OUT->print($txt_indx_min . " ($mem_count)\n"); OUT->print("

      Index of sections, and their contents

      \n"); OUT->print($txt_indx_ful . "\n"); } sub conv_html { my $text = shift; if (defined ($text)) { $_ = $text; } s/&/&/g; # must remember to do this one first! s//>/g; # don't close too early s/\"/"/g; # only in embedded tags, i guess return ($_); } my $current_function = undef; sub conv_A_refs { my $params = shift; my $markup = shift; s{(\W|^)(Ustr string)(\W|$)} {$1$2$3}g; s{(\W|^)(Ustrp string)(\W|$)} {$1$2$3}g; s{(\W|^)(Ustr pool)(\W|$)} {$1$2$3}g; s{([^#"_0-9a-z])ustr(p|)_([_0-9a-z]+)\(\)} {$1ustr${2}_$3()}g; s{([^#"_0-9A-Z])USTR(P|)_([_0-9A-Z]+)\(\)} {$1USTR${2}_$3()}g; s{([^#"_0-9A-Z])USTR(P|)([1-4]+)\(\)} {$1USTR$3()}g; if ($params && defined($current_function)) { s{([^#"_0-9A-Z])USTR_([_0-9A-Z]+[*])} {$1USTR_$2}g; } s{([^#"_0-9A-Z])USTR_([_0-9A-Z]+)([^_0-9A-Z(*])} {$1USTR_$2$3}g; s![*]{2}([^*]+)[*]{2}!$1!g if ($markup); } sub convert() { my $in_pre_tag = 0; my $in_const = 0; while () { my $next_in_const = 0; my $beg_replace = <
      EOL if ($in_const) { $beg_replace = qw(
      ); } if ($in_pre_tag) { $beg_replace = "$beg_replace"; } if (s!^(Constant|Function|Member): (.*)$!$beg_replace$1: $2! || s!^ Explanation:\s*$!
      Explanation:

      ! || s!^ Note:\s*$!

      Note:

      ! || s!^Section:\s*(.*)$!

      $1

      ! || 0) { $in_pre_tag = 0; if (defined ($1)) { if ($1 eq "Constant") { my $iduri = $2; my $orig_str = $_; $next_in_const = 1; $iduri =~ s/([^[:alnum:]:_])//g; s!(: )(.*)!$1$2!; $current_function = undef; } elsif ($1 eq "Function") { my $iduri = $2; $iduri =~ s/([^[:alnum:]:_])//g; s!(: )(.*)!$1$2!; $current_function = $iduri; } elsif ($1 eq "Member") { $current_function = undef; } else { # Section... my $uri = $1; my $sect_str = $1; $uri =~ s/([^[:alnum:]:_])/sprintf("%%%02x", ord($1))/eg; if (/Constants passed to /) { # More hacks... s { ([^#"_0-9a-z])(ustr_[_0-9a-z]+)\(\) } { $1\t$2()\n }gx; } s/

      /

      /; s!

      !!; conv_A_refs(0, 0); } } } elsif (m!^ ([A-Z][a-z]+)(\[\d\]|\[ \.\.\. \])?: (.*)$!) { my $attr = $1; my $param_num = $2; my $text = $3; $text = conv_html($text); $_ = conv_html($_); if (defined $param_num) { if ($attr eq "Type") { $_ = "
      $attr$param_num: $text"; } else { $_ = "
      $attr$param_num: $text"; } } else { if ($attr eq "Type" || $attr eq "Returns") { $_ = "
      $attr: $text"; } else { $_ = "
      $attr: $text"; } } conv_A_refs(1, 0); } elsif ( $in_pre_tag && /^ \.\.\./) { if (/\.\.\.$/) { conv_A_refs(1, 1); $_ = "

      $_

      ";
      		$in_pre_tag = 1;
      	      }
      	    else
      	      {
      		conv_A_refs(1, 1);
      		$_ = "

      $_"; $in_pre_tag = 0; } } elsif (/\.\.\.$/) { $_ = conv_html($_); conv_A_refs(1, 1); $_ = "$_

      ";
      	    $in_pre_tag = 1;
      	  }
      	elsif (!$in_pre_tag && /^  /)
      	  {
                  $_ = conv_html($_);
      	    conv_A_refs(1, 1);
      	    $_ = "

      $_"; } elsif (!$in_pre_tag) { conv_A_refs(1, 1); } $in_const = $next_in_const; print OUT; } } open (OUT, "> functions.html") || die "open(functions.html): $!"; print OUT $html_header; print OUT "", "$name -- functions", "", "\n"; print OUT $html_body; print OUT "
      "; open (IN, "< $docs/functions.txt") || die "open(functions.txt): $!"; convert_index("functions"); open (IN, "< $docs/functions.txt") || die "open(functions.txt): $!"; convert(); print OUT $html_footer; open (OUT, "> constants.html") || die "open(constants.html): $!"; print OUT $html_header; print OUT "", "$name -- constants", "", "\n"; print OUT $html_body; print OUT "
      "; open (IN, "< $docs/constants.txt") || die "open(constants.txt): $!"; convert_index("constants"); open (IN, "< $docs/constants.txt") || die "open(constants.txt): $!"; convert(); print OUT $html_footer; if (-r "structs.txt") { open (OUT, "> structs.html") || die "open(struts.html): $!"; print OUT $html_header; print OUT "", "$name -- structs", "", "\n"; print OUT $html_body; print OUT "
      "; open (IN, "< $docs/structs.txt") || die "open(structs.txt): $!"; convert_index("structs"); open (IN, "< $docs/structs.txt") || die "open(structs.txt): $!"; convert(); print OUT $html_footer; } exit 0; ustr-1.0.4/Documentation/ustr - timeline.html0000644000076400007640000002041010763663475020117 0ustar jamesjames ustr a rough timeline, notes on the last 10%

      ustr a rough timeline, notes on the last 10%

      Common software development wisdom says "the last 10%" is often a significant time consumer, if not 50%, of the work. So when I recently created ustr, I thought I had a pretty good candidate to get some real numbers. For a start, in my favour, I'd already created Vstr and so knew most of the interfaces I'd want and roughly how to write them.

      the idea

      I'd had an idea bouncing around in my head that you could enhanced pascal strings (single byte followed by 0 to 255 bytes) to give you a C string type that was both NIL terminated and had a managed length. The initial idea was that the problem with pascal strings is that they are fine > 50% of the time but on those few occasions when you needed more than they could hold, they were worthless. So the solution seemed kind of obvious, have some kind of encoding (like UTF-8) for the length of the string.

      Looking at UTF-8 the obvious choice for the encoding would be to use the top bit of the first byte to say, get more length bits from the next byte and then keep going. So you'd get 7bits of length from every length byte thus for a 32bit size_t, you'd need 5 bytes (only using 4 bits from the last one), and a 64bit size_t you'd need 10 bytes (using 1 from the last byte).

      Of course then you also want a size (bytes allocated, as against used), and maybe a reference count etc. However with a "simple string API" like this you want the function which gives you the pointer to the data as close to constant time as possible, and the above design _might_ be a problem, as you'd need to "walk" the encoded numbers to get to the data. There were also a couple of other obvious problems, for instance one of the reasons for creating a "simple" format like this is so you could easily create strings in the C source code, and while it wasn't obvious how I'd do that it was obvious that having to convert the length into a 7bit encoded number would be painful.

      I'd also already spent about 2 years of my spare time writing Vstr, which worked even though it wasn't a perfect fit for all the uses I put it to, so I wasn't jumping at an opportunity to go write another string API. Which is to say, it stayed an idea for more than a few months.

      the first "90%"

      Then in early 2007 I'd failed to get Vstr usage into yet another project, even though it was the perfect fit, which might not have been so bad but the available alternatives amounted to "just use string.h, and code perfectly". Also a friend was looking for a string API to use, in C, but even with my comparison page basically found nothing available to use for a shared library in Fedora (that cared about malloc failures) and so was forced to write his own. So I decided to give my idea a try, and see what happened.

      I opened a text editor on Monday the 7th of May and wrote the main parts of the first version of ustr (at the time called Simple String lib. with the namespace ss_*) that evening and Wednesday the 9th. Doing a few tweaks on Thursday the 10th I sent a first version out, to see if it would fit my friends needs.

      The initial implementation from the Monday night was roughly 500 lines, mainly dup; dup_buf; dup_cstr and the low allocation code. I knew my friend needed reference counting, so I split the first byte in half and used 4 bits for the number of bytes (0, 1, 2, 4, 8) of the reference count and 4 bits for the same for the length. From the begining USTR("") was a valid Ustr of length zero, as I'd wanted a way to have a "valid" string as an iniitalizer.

      By the time the first other person saw it on Thursday I'd moved to using only 3 bits for the number of bytes (none zero being a power of two, so 3==4 and 4==8) and it had the "exact sized allocations" flag and the "memory error occured flag". As a special case a reference count number of bytes of 2**7 meant the string was a constant string, so you could do USTR1(\4, "abcd"). I'd also done the obvious simple and fast comparing (cmp), per. string configuration (dupx), formatting (fmt), setting (set), searching (srch), spanning (spn). It also had non-trivial unit tests, but the actual "library" itself was all inside one header which was roughly 1,000 wc -l lines. By that weekend I'd split it up into multiple files and done some performance tests.

      On the 24th of May (two weeks later) I sent it out to about 10 people, and by this time it had very close to it's current core feature set as I'd dropped the storage for number of bytes down to 2 bits and added a "was allocated" flag, a "has size stored" flag and a "is in automatic storage" virtual flag (so it could be const, allocated or auto). This had also included moving the bits around to their current position. It also added the Ustrp type, for allocating from a pool, GDB init functions for debugging the build split for opt/dbg builds, functions for working with binary numbers and a bunch of extra "core" functions and unit tests to go with it. I'd made sure it ran on Solaris, including using my custom auto* foo. The documentation had expanded considerably. Oh, and I'd renamespaced everything so it was actually ustr now and not ss.

      That was ustr-0.99.1, written in roughly 9 evenings and 1 Sunday (17 "real time days", 7th => 24th). Stats. were:

         ustr*.[ch] => wc -l == 5,434 sloccount == 4,249
         tst*.[ch]  => wc -l == 1,304 sloccount == 1,046
      

      At the time I knew it wasn't "complete", but I think my main concerns were lack of documentation and wanting 100% code coverage on the unit tests. I might well have said it was "90%" complete, if I didn't think about it too long. Even if I'd have thought about it I'd have likely said it was over 50% complete for 1.0.

      the last "10%"

      The initial GIT import happened a few days after 0.99.1 was released (Wednesday, 1st of June) so there is a pretty precise record of what happened between 0.99.1 and 1.0.0, and when it happened.

      On Friday 13th of July I released ustr-1.0.0, that was 7 weeks after 0.99.1. That's meant that roughly 75% of the "real time days" for 1.0.0 were after the "90%" mark, so even if I worked twice as hard before 0.99.1 as I did after I was only at 40%. Also 1.0.0 had a couple of errors, although mostly in building, install and ustr-import. I also knew when I released ustr-1.0.0 that ustr-1.0.1 was going to have quite a few new interfaces due to an external contributor. So it's probably fair to say 1.0.0 was "rushed" out to some extent just to have a stable release. Stats. were:

         ustr*.[ch] => wc -l == 8,962 sloccount == 7,079
         tst*.[ch]  => wc -l == 3,855 sloccount == 3,198
      

      ...and five example files (none were in 0.99.1), and a significant amount of the functions documented. The main changes, apart from tests, documentation and example files was the addition of io helper functions, utf-8 functions, parse functions for getting numbers from Ustr's and re-working a lot of APIs to add an offset parameter. The lack of the offset from the start was proably an overreaction from Vstr where all functions take a position and a length, my assumption with ustr was that pretty much 100% of the time you'd be operating on an entire ustr as one unit but this had some very bad properties for things like parsing a path or a csv, unless you wanted to revert to using strchr() etc.

      On Saturday August 4th I released ustr-1.0.1, the big additions here were insert (ins), split, substitution (sub) and replacement. While this was "only" an extra three weeks or so, that was by two people one of whom was doing it for their job (although that wasn't me :). Stats. were:

         ustr*.[ch] => wc -l == 10,954 sloccount == 8,820
         tst*.[ch]  => wc -l ==  4,991 sloccount == 4,214
      

      ...with an extra example program.


      James Antill
      Last modified: Thu Oct 4 00:32:40 EDT 2007 ustr-1.0.4/Documentation/constants.html0000644000076400007640000011367110763663475017246 0ustar jamesjames Ustr - 1.0.4 reference documentation -- constants

      Ustr - 1.0.4 reference documentation -- constants (60)

      Index of sections

      Index of sections, and their contents

      Compile switch constants

      Constant: USTR_CONF_INCLUDE_CODEONLY_HEADERS
      Explanation:

      This switch controls whether all the code will be included as inline functions. Having this be non-zero means that you don't have to link against the library.

      Constant: USTR_CONF_USE_EOS_MARK
      Explanation:

      This switch turns on End of String markers, so any bounds overflow will be noticed by ustr_assert_valid().

      Note:

      Changing this will not do anything useful unless USTR_CONF_INCLUDE_CODEONLY_HEADERS is non-zero.

      Constant: USTR_CONF_USE_ASSERT
      Explanation:

      This switch turns USTR_ASSERT() calls on, so the code within them will be evaluated. Note that there are many calls to ustr_assert_valid() within USTR_ASSERT() macros and that call is relatively expensive.

      Note:

      Changing this will not do anything useful unless USTR_CONF_INCLUDE_CODEONLY_HEADERS is non-zero.

      Constant: USTR_CONF_COMPILE_USE_ATTRIBUTES
      Explanation:

      This switch controls whether gcc type __attribute__() statements are used in the public headers headers for the library. If the value is 1 then if they are supported by the compiler that built the library they will be used, if the value is 0 they won't be used at all.

      Constant: USTR_CONF_COMPILE_TYPEDEF
      Explanation:

      This switch controls whether typedef will be used for the structs in the public headers for the library. If the value is 1 then they will be used, if the value is 0 they won't be used at all (and your code will have to use struct tags instead -- note all libraries using ustr should compile without this option set).

      Constant: USTR_CONF_COMPILE_USE_INLINE
      Explanation:

      This switch controls whether inline functions will be used in a few cases where the function bodies are very small.

      Note:

      In some cases this is used so that GCC can eliminate calls to strlen(), for the *_cstr() functions.

      Constants to created fixed/read-only Ustr's

      Constant: USTR_BEG_CONST1
      Explanation:

      This macro is a constant C-style string of the first byte of a constant/read-only Ustr that has a length in the range 0-255.

      Constant: USTR_BEG_CONST2
      Explanation:

      This macro is a constant C-style string of the first byte of a constant/read-only Ustr that has a length in the range 0-65535.

      Constant: USTR_BEG_CONST4
      Explanation:

      This macro is a constant C-style string of the first byte of a constant/read-only Ustr that has a length in the range 0-4294967295.

      Constant: USTR_BEG_FIXED1
      Explanation:

      This macro is a constant C-style string of the first byte of a fixed Ustr that has a length in the range 0-255.

      Constant: USTR_BEG_FIXED2
      Explanation:

      This macro is a constant C-style string of the first byte of a fixed Ustr that has a length in the range 0-65535.

      Constant: USTR_BEG_FIXED4
      Explanation:

      This macro is a constant C-style string of the first byte of a fixed Ustr that has a length in the range 0-4294967295.

      Constant: USTR_BEG_FIXED8
      Explanation:

      This macro is a constant C-style string of the first byte of a fixed Ustr that has a length in the range 0-18446744073709551615.

      Note:

      This macro is only available if the Ustr code was compiled in a 64bit environment.

      Constant: USTR_END_ALOCDx
      Explanation:

      This macro is a constant C-style string of the last bytes of an allocated Ustr.

      Note:

      Unless USTR_CONF_USE_EOS_MARK is non-zero, this is just the NIL byte.

      Constant: USTR_END_CONSTx
      Explanation:

      This macro is a constant C-style string of the last bytes of a constant/read-only Ustr.

      Note:

      Unless USTR_CONF_USE_EOS_MARK is non-zero, this is just the NIL byte.

      Constant: USTR_END_FIXEDx
      Explanation:

      This macro is a constant C-style string of the last bytes of a fixed Ustr.

      Note:

      Unless USTR_CONF_USE_EOS_MARK is non-zero, this is just the NIL byte.

      Constants to use with parsing numbers: ustr_parse_uintmaxx, etc.

      Constant: USTR_FLAG_PARSE_NUM_DEF
      Explanation:

      Default flags, this is merely 0 but can be used as live documentation.

      Constant: USTR_FLAG_PARSE_NUM_SEP
      Explanation:

      This flag allows the parsing (and ignoring) of the seperator character, at arbitrary pointers in the number, so "1234" and "1_234" would both parse the same (assuming "_" is the seperator).

      Constant: USTR_FLAG_PARSE_NUM_OVERFLOW
      Explanation:

      This flag turns on the overflow checking, in other words without it USTR_TYPE_PARSE_NUM_ERR_OVERFLOW will never be returned as an error code.

      Constant: USTR_FLAG_PARSE_NUM_SPACE
      Explanation:

      This flag allows one or more ' ' (Space) characters before the number or number prefix (Plus Sign, Hyphen).

      Note:

      Other forms of whitespace don't count, this just affects ' '.

      Constant: USTR_FLAG_PARSE_NUM_NO_BEG_ZERO
      Explanation:

      This flag disallows one or more '0' (Digit Zero) characters before the number.

      Constant: USTR_FLAG_PARSE_NUM_NO_BEG_PM
      Explanation:

      This flag disallows a plus or a minus character before the number.

      Constant: USTR_FLAG_PARSE_NUM_NO_NEGATIVE
      Explanation:

      This flag disallows negative values.

      Constant: USTR_FLAG_PARSE_NUM_EXACT
      Explanation:

      This flag makes the parsing functions return an error if the entire string doesn't contain the number being parsed.

      Constant: USTR_TYPE_PARSE_NUM_ERR_NONE
      Explanation:

      This error code has the value 0, and means that no error occurred parsing the number.

      Constant: USTR_TYPE_PARSE_NUM_ERR_ONLY_S
      Explanation:

      This error code means that the Ustr string consisted only of spaces.

      Constant: USTR_TYPE_PARSE_NUM_ERR_ONLY_SPM
      Explanation:

      This error code means that the Ustr string consisted only spaces, and a plus or minus sign.

      Constant: USTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX
      Explanation:

      This error code means that the Ustr string consisted of only spaces, a plus or minus sign and a "0x" base 16 prefix.

      Constant: USTR_TYPE_PARSE_NUM_ERR_OOB
      Explanation:

      This error code means that the Ustr string had characters in it that where out of bounds from the working base.

      Note:

      Without the USTR_FLAG_PARSE_NUM_EXACT, this error is ignored as soon as any number is parsed.

      This out of bounds includes the Ustr string "++" as well as "4A", when parsing in a base less than 11.

      Constant: USTR_TYPE_PARSE_NUM_ERR_OVERFLOW
      Explanation:

      This error code means that the number parsed from the Ustr string would overflow the type it is being parsed into, this is only returned when the USTR_FLAG_PARSE_NUM_OVERFLOW flag was passed to the parse function.

      Constant: USTR_TYPE_PARSE_NUM_ERR_NEGATIVE
      Explanation:

      This error code means that the number parsed from the Vstr string starts with a '-' (Hyphen) character when it is supposed to be an unsigned number.

      Constant: USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO
      Explanation:

      This error code means that the number parsed from the Vstr string starts with a '0' (Digit Zero) character, when the USTR_FLAG_PARSE_NUM_NO_BEG_ZERO flag was passed to the parse function.

      Constants to pass to ustr_split*

      Constant: USTR_FLAG_SPLIT_DEF
      Explanation:

      Default flags, this is merely 0 but can be used as live documentation.

      Constant: USTR_FLAG_SPLIT_RET_SEP
      Explanation:

      Return the separator along with the tokens. For example splitting "a,b," using separator "," will return the tokens "a," and "b," whereas without this flag only "a" and "b" would be returned.

      Constant: USTR_FLAG_SPLIT_RET_NON
      Explanation:

      Return empty tokens. For example: splitting "a,,b" with separator "," will return the tokens {"a" "" "b"}.

      Constant: USTR_FLAG_SPLIT_KEEP_CONFIG
      Explanation:

      Force the returned Ustr's to have same configuration parameters as the Ustr string that is being split.

      Misc constants to use in code

      Constant: USTR_NULL
      Explanation:

      This macro is merely 0 cast to (struct Ustr *), and can be used anywhere NULL would be but "returns" the correct type.

      Constant: USTR_POOL_NULL
      Explanation:

      This macro is merely 0 cast to (struct Ustr_pool *), and can be used anywhere NULL would be but "returns" the correct type.

      Constant: USTR_TRUE
      Explanation:

      This macro is 1, but shows the intent that a boolean value is expected and not a number.

      Constant: USTR_FALSE
      Explanation:

      This macro is 0, but shows the intent that a boolean value is expected and not a number.

      Constants passed to ustr_cntl_opt()

      Constant: USTR_CNTL_OPT_GET_REF_BYTES
      Parameter[1]: Number of bytes for default reference count in Ustr
      Type[1]: size_t *
      Explanation:

      This option will get the default number of bytes used for a reference count when creating Ustr's.

      Constant: USTR_CNTL_OPT_SET_REF_BYTES
      Parameter[1]: Number of bytes for default reference count in Ustr
      Type[1]: size_t
      Explanation:

      This option will set the default number of bytes used for a reference count when creating Ustr's.

      Note:

      For a single instance, the ustr_dupx_*() functions can be used.

      Constant: USTR_CNTL_OPT_GET_HAS_SIZE
      Parameter[1]: Default flag for whether to include an explicit size in a Ustr
      Type[1]: int *
      Explanation:

      This option will get the default flag for whether to store an explicit size in created Ustr's.

      Constant: USTR_CNTL_OPT_SET_HAS_SIZE
      Parameter[1]: Default flag for whether to include an explicit size in a Ustr
      Type[1]: int
      Explanation:

      This option will set the default flag for whether to store an explicit size in created Ustr's.

      Note:

      For a single instance, the ustr_dupx_*() functions can be used.

      Constant: USTR_CNTL_OPT_GET_EXACT_BYTES
      Parameter[1]: Default flag for whether to exactly allocate memory
      Type[1]: int *
      Explanation:

      This option will get the default flag for whether to exactly allocate memory when a Ustr needs to be resized.

      Constant: USTR_CNTL_OPT_SET_EXACT_BYTES
      Parameter[1]: Default flag for whether to exactly allocate memory
      Type[1]: int
      Explanation:

      This option will set the default flag for whether to exactly allocate memory when a Ustr needs to be resized.

      Note:

      For a single instance, the ustr_dupx_*() functions can be used.

      Constant: USTR_CNTL_OPT_GET_MEM
      Parameter[1]: Pointer to colleciton of function pointers for system allocation
      Type[1]: struct Ustr_cntl_mem *
      Explanation:

      This option will get the "system" allocation functions (malloc, realloc, free) for allocated Ustr's.

      Note:

      As you would expect the default values are: malloc, realloc, free.

      Constant: USTR_CNTL_OPT_SET_MEM
      Parameter[1]: Pointer to colleciton of function pointers for system allocation
      Type[1]: const struct Ustr_cntl_mem *
      Explanation:

      This option will set the "system" allocation functions (malloc, realloc, free) for allocated Ustr's.

      Note:

      If this option is set after a Ustr has been created, then when freeing or reallocating the existing Ustr the given functions will be used. So they must either be compatible with the default or you must ensure that nothing is allocated before they are set.

      Constant: USTR_CNTL_OPT_GET_MC_M_SCRUB
      Parameter[1]: Flag for whether to include an explicit size in a Ustr
      Type[1]: int *
      Explanation:

      This option will get the flag for whether to "scrub" data allocated via. malloc check.

      Note:

      Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive.

      Constant: USTR_CNTL_OPT_SET_MC_M_SCRUB
      Parameter[1]: Flag for whether to include an explicit size in a Ustr
      Type[1]: int
      Explanation:

      This option will set the flag for whether to "scrub" data allocated via. malloc check.

      Note:

      Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive.

      Constant: USTR_CNTL_OPT_GET_MC_F_SCRUB
      Parameter[1]: Flag for whether to include an explicit size in a Ustr
      Type[1]: int *
      Explanation:

      This option will get the flag for whether to "scrub" data freed via. malloc check.

      Note:

      Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive.

      Constant: USTR_CNTL_OPT_SET_MC_F_SCRUB
      Parameter[1]: Flag for whether to include an explicit size in a Ustr
      Type[1]: int
      Explanation:

      This option will set the flag for whether to "scrub" data freed via. malloc check.

      Note:

      Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive.

      Constant: USTR_CNTL_OPT_GET_MC_R_SCRUB
      Parameter[1]: Flag for whether to include an explicit size in a Ustr
      Type[1]: int *
      Explanation:

      This option will get the flag for whether to "scrub" data reallocated via. malloc check. This is done by turning all reallocations into a malloc() and free(), and so is even more costly than normal scrubbing.

      Note:

      Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive.

      Constant: USTR_CNTL_OPT_SET_MC_R_SCRUB
      Parameter[1]: Flag for whether to include an explicit size in a Ustr
      Type[1]: int
      Explanation:

      This option will set the flag for whether to "scrub" data reallocated via. malloc check. This is done by turning all reallocations into a malloc() and free(), and so is even more costly than normal scrubbing.

      Note:

      Malloc check has to be enabled for this to mean anything, Ie. USTR_CNTL_MALLOC_LVL() must be positive.

      Constant: USTR_CNTL_OPT_GET_FMT
      Parameter[1]: Pointer to colleciton of function pointers for system formating
      Type[1]: struct Ustr_cntl_fmt *
      Explanation:

      This option will get the system formatting functions (vsnprintf) for Ustr's.

      There are two functions, the first is always called and the second is likely called (always with the exact same arguments) if the length passed to the first call was not big enough.

      Note:

      As you would expect the default values are: vsnprintf and vsnprintf

      Constant: USTR_CNTL_OPT_SET_FMT
      Parameter[1]: Pointer to colleciton of function pointers for system formatting
      Type[1]: const struct Ustr_cntl_fmt *
      Explanation:

      This option will set the system formatting functions (vsnprintf) for Ustr's.

      Constants passed to ustr_pool_ll_cntl()

      Constant: USTR_POOL_LL_CNTL_GET_FREE_CMP
      Parameter[1]: Number of pointers to compare to in the pool
      Type[1]: unsigned int *
      Explanation:

      This option will get the number of comparisons done on a pool free operation.

      Constant: USTR_POOL_LL_CNTL_SET_FREE_CMP
      Parameter[1]: Number of pointers to compare to in the pool
      Type[1]: unsigned int
      Explanation:

      This option will set the number of comparisons done on a pool free operation.

      Note:

      The default is a small non-zero value, as it's significantly common to have very short lived ustr's ... however this doesn't mean that you can't forget to take references even with pool allocated ustrs.

      Constant: USTR_POOL_LL_CNTL_GET_REALLOC
      Parameter[1]: Flag for if we should call realloc()
      Type[1]: int *
      Explanation:

      This option will get the flag for if we call realloc() to make data bigger, or revert to just allocating anew each time.

      Constant: USTR_POOL_LL_CNTL_SET_REALLOC
      Parameter[1]: Flag for if we should call realloc()
      Type[1]: int
      Explanation:

      This option will set the flag for if we call realloc() to make data bigger, or revert to just allocating anew each time.

      Note:

      As with USTR_POOL_LL_CNTL_SET_FREE_CMP this option means you can't assume that pool allocated data is never freed until ustr_pool_free() is called, and again it is due to there being significant speed improvements for not making that assumption. Instead of disabling this option, just take areference (which will also make sure the ustr isn't modified behind your back).

      ustr-1.0.4/Documentation/ustr-import.10000644000076400007640000000735310763523347016723 0ustar jamesjames.TH ustr 1 "03-Aug-2007" "ustr\-import 1.0.4" "Ustr String Library, tools" .SH "NAME" ustr\-import \- ustr string library import tool .SH "SYNOPSIS" .ad l .hy 0 .HP 5 \fBustr\-import\fR [\-\-32|\-\-64] [\-d][d] [\-c] [\-b x] [\-e 1|0] [\-s 1|0] section .sp .ti .SH "DESCRIPTION" This tool lets you use the Ustr string library without incuring dependancies on the library itself, so API/ABI compatability is 100% (nothing changes unless you do it) and installing your application doesn't require the library to be pre\-installed\&. .SH "OPTIONS" .TP \-\-32 If you installed with multilib, this runs the 32 bit varient (and installs the variable multilib build code as ustr\-conf.h)\&. .TP \-\-64 If you installed with multilib, this runs the 64 bit varient (and installs the variable multilib build code as ustr\-conf.h)\&. .TP \-d Turn debugging on, USTR_ASSERT() now runs code etc\&. .TP \-d Turn extra debugging on, including End of String (EOS) markers that takeup space\&. Note that you can do \-dd to add both at once\&. .TP \-c Use C files, this requires that you alter the build system to compile the C files and link them into your application\&. The default is to just provide headers that you can just include\&. .TP \-b Specify the default reference count byte size: 0, 1, 2 or 4 (or 8 on 64 bit platforms)\&. Note that 2 bytes is the minimum if you have explicit size storage\&. .TP \-e Specify the default exact sized allocations flag, without this flag allocations are rounded up to the neared half power of two\&. .TP \-s Specify the default explicit size storage flag, without this flag allocations have an implicit size based on their length with it a size value is stored with the string (thus taking significantly larger space for small strings, but this doesn't require reallocating the string when growing and shrinking the string)\&. Note that turning this on also increases the minimum sizes for length and reference count storage\&. .SH "SECTIONS" .TP all All of the following sections are included\&. .TP b Working with binary numbers in NBO format\&. .TP cmp Comparing, strcmp() for Ustr's, although the Ustr versions are safer and much faster\&. .TP cntl Control options dynamically\&. .TP fmt Formatted output, sprintf() for Ustr's\&. .TP gdb Copy just the \&.gdbinit file to the local dir\&. .TP io Input Output\&. .TP ins Inserting data\&. .TP main The core functions, including strcat(), strdup() and delete for Ustr's. Always safer and often much faster\&. .TP parse Parsing integers, Ie. Nice versions of strtol()\&. .TP pool A bundled memory pool API, to use with the ustrp functions\&. .TP replace Replacing all occurances of data\&. .TP sc Shortcut functions for Ustr's\&. .TP set Setting data, strcpy() for Ustr's\&. .TP split Slit the data, strtok() / strsep() for Ustr's\&. .TP spn Spanning, strspn() / strcspn() for Ustr's\&. .TP srch Searching, strchr() / strrchr() / strstr() for Ustr's, although the Ustr versions are safer and much faster\&. .TP sub Substituting data\&. .TP utf8 Working with UTF8\&. .SH "FILES" .TP \fI/ustr/include/ustr\-conf\&.h\fR \fI/ustr/include/ustr\-conf\-debug\&.h\fR In multilib. this is the header to choose the correct conf\&.h header based on the byte size\&. .TP \fI/ustr/include/ustr*\&.h\fR The default "extern" header files\&. .TP \fI/usr/share/ustr\-*/ustr\-*\-internal\&.h\fR Internal functions, used the implement the public interfaces\&. .TP \fI/usr/share/ustr\-*/ustr\-*\-code\&.h\fR The code behind the public interfaces\&. .TP \fI/usr/share/ustr\-*/ustr\-*\-code\&.c\fR The C files, which use the code header files to create objects\&. .TP \fI/usr/share/ustr\-*/\&.gdbinit\fR The GDB init file containing macros to help inspect Ustr's in the debugger\&. .SH "SEE ALSO" .BR ustr (3), ustr_const (3) ustr-1.0.4/Documentation/index.html0000644000076400007640000010675610763663475016347 0ustar jamesjames µstr - Micro String API - for C

      µstr - Micro String API - for C

      Download - Version µstr-1.0.4

      You can get the stable release of 1.0.x here (ftp), it still doesn't have 100% documentation but it's pretty close. You can get the current git tree here.

      About

      A few years ago now I wrote a very extensive String API for C, called Vstr, it was designed to perform extremely well for IO like patterns as that was my planned usage (for instance And-httpd, my Web server). It works very well, for that usage.

      Also due to the extensivness of the API I basically used it everywhere, even though there are some things it is somewhat "overkill" for, and I wanted other people to use it so I didn't have to resort to using string.h when creating patches for their code. However more than a few C coders I speak to have one of a few reasons why they don't want to use Vstr. The ustr API should solve all of these problems, and hopefully fill in all the gaps where Vstr is the 500lb hammer.

      There is an introduction to using the ustr API, as a guided tutorial of example code. You can see the developers design documentation here. Also here's the file of GDB init functions (or: ustr-import gdb), to help with debugging. There are API references for functions and constants. The unit testing coverage data is available. And the here are links to TODO, NEWS, THANKS, AUTHORS and the "LICENSE", such as it is.

      List of problems with String APIs, in C

      These are the primary reasons I've seen given why developers don't want to put "any" string API into their code:

      • It's "too hard", politically, to put into an existing projects build system.
      • String ADTs take up too much memory.
      • It's too hard to integrate into existing code/APIs that uses plain C-style strings significantly.
      • We can "often" use stack space for a string, if we do it ourself, which (we understand) is much faster.
      • Need/want to initialize strings as they are declared.
      • License isn't compatible with our code.
      • The current code may be unsafe and hard to audit, but it's "optimized" to use the C-style string format/design.
      • While development might be harder "debugging is easier".

      So instead of using a String ADT (any String ADT), the common solution is to just try and get by using (char *)'s and string.h. With "certain bits" using strdup() and/or some size_t's with a stored length. This ad hoc approach is very bad, for everybody. Needless to say, ustr solves all of the above problems while being significantly faster and safer than just using string.h.

      List of solutions to problems with String APIs, in C

      Solving the build problem

      To use ustr with all of the shipped modules, you can just (after install ustr) goto your source dir. and run:

      ustr-import all
      

      And include the following line in any source files you want to use ustr from:

      #include "ustr.h"
      

      You do not have to worry about linking with anything or having symbols appear in your library that you don't want ... it will "just work". If you don't want copies of each function you are using to appear in each file it is used from you can pass the "-c" option to ustr-import and compile the .c files. You can also link against the ustr shared library, if you don't mind adding a very simple dependency (it is much simpler than Vstr, for example, and so is very likely to just run anywhere your code does).

      Note that if you wish to look at some ustr using code now, you can see some example code or look at the distributed example/unit-test code at the end of this page.

      Solving the memory overhead problem

      This is best illistrated by example. Say you build a "simple" string API, it just has the basics: automatic grow and shrink and reference counts for zero copy duplication. The default assumption is that as you are adding data to the string you don't want to spend all your time in realloc() so you also expand the size of the string by powers of 2.

      This is about the most common string API that people implement on their own, a rough structure would look like:

      struct Simple_str
      {
        char *ptr;
        size_t reference_count;
        size_t length;
        size_t size;
      };
      

      However this strucutre itself is 16 bytes (in a 32bit environment) or 32bytes (in a 64bit environment), and to allocate a new string requires two allocations (one for the string, and one for the data in the ->ptr argument).

      This means that to create a new string containing one byte you have to do two allocations and allocate roughly 34bytes ... giving a 1700% increase over plain strdup().

      By comparison ustr does one allocation of 6bytes by default, in a both 32bit and 64bit environments, and it can drop that down to 4 bytes, again even in a 64bit environment (and, in a 64bit environment, you can have a > 4GB ustr so you aren't losing any features).

      Although, to be fair, by default ustr only allocates 2bytes for it's reference count. However that's 65,535 references to the same string -- and ustr has a helper function so that if you need 70,000 references to a string it'll only need to allocate 2 strings, and has another helper function so that you can mark a string as "shared" so it will act like a read-only string until it has been set back to "owned".

      For a Gnumeric spreadsheet comparing all string length values upto 260 between strdup(), ustr and a "Simple str" click here. I've also listed of some common "small" string lengths below with their percentage overhead vs. strdup().

      Ave. range of string sizes Ave. Simple_str - 32bit overhead Ave. Simple_str - 64bit overhead Ave. ustr overhead
      1-9 bytes 327.27% 618.18% 85.45%
      1-19 bytes 194.76% 347.14% 55.24%
      1-29 bytes 239.57% 236.34% 45.81%
      1-39 bytes 123.78% 201.83% 41.22%
      1-79 bytes 87.01% 126.51% 32.53%
      1-89 bytes 83.13% 118.29% 28.3%
      1-198 bytes 62.23% 78.23% 23.85%

      Here is a list of the first 18 string lengths, and some later ones using the different options for ustr:

      String Alloc. C-string Alloc./Used Ustr, ref==4 Alloc./Used Ustr, ref==2 Alloc./Used Ustr, ref==1 Alloc./Used Ustr, ref==0
      "" 1 byte 0/0 0/0 0/0 0/0
      "1" 2 bytes 8/8 6/6 6/5 4/4
      "12" 3 bytes 12/9 8/7 6/6 6/5
      "123" 4 bytes 12/10 8/8 8/7 6/6
      "1234" 5 bytes 12/11 12/9 8/8 8/7
      "12345" 6 bytes 12/12 12/10 12/9 8/8
      "123456" 7 bytes 16/13 12/11 12/10 12/9
      "1234567" 8 bytes 16/14 12/12 12/11 12/10
      "12345678" 9 bytes 16/15 16/13 12/12 12/11
      "123456789" 10 bytes 16/16 16/14 16/13 12/12
      "123456789 " 11 bytes 24/17 16/15 16/14 16/13
      "123456789 1" 12 bytes 24/18 16/16 16/15 16/14
      "123456789 12" 13 bytes 24/19 24/17 16/16 16/15
      "123456789 123" 14 bytes 24/20 24/18 24/17 16/16
      "123456789 1234" 15 bytes 24/21 24/19 24/18 24/17
      "123456789 12345" 16 bytes 24/22 24/20 24/19 24/18
      "123456789 123456" 17 bytes 24/23 24/21 24/20 24/19
      "123456789 1234567" 18 bytes 24/24 24/22 24/21 24/20
      "123456789 12345678" 19 bytes 32/25 24/23 24/22 24/21
      "123456789 123456789" 20 bytes 32/26 24/24 24/23 24/22
      "123456789 1234...45" 26 bytes 32/32 32/30 32/29 32/28
      "123456789 1234...56" 27 bytes 48/33 32/31 32/32 32/31
      "123456789 1234...78" 28 bytes 48/34 32/32 32/31 32/30
      "123456789 1234...89" 29 bytes 48/35 48/33 32/32 32/31
      "123456789 1234...9 " 30 bytes 48/36 48/34 48/33 32/32
      "123456789 1234... 1" 42 bytes 48/48 48/46 48/45 48/44
      "123456789 1234...12" 43 bytes 64/49 48/47 48/46 48/45
      "123456789 1234...23" 44 bytes 64/50 48/48 48/47 48/46
      "123456789 1234...34" 45 bytes 64/51 64/49 48/48 48/47
      "123456789 1234...45" 46 bytes 64/52 64/50 64/49 48/48
      "123456789 1234...89" 60 bytes 96/66 64/64 64/63 64/62
      "123456789 1234...9 " 61 bytes 96/67 96/65 64/64 64/63
      "123456789 1234... 1" 62 bytes 96/68 96/66 96/65 64/64
      "123456789 1234...23" 124 bytes 192/130 128/128 128/127 128/126
      "123456789 1234...34" 125 bytes 192/131 192/129 128/128 128/127
      "123456789 1234...45" 126 bytes 192/132 192/130 192/129 128/128
      "123456789 1234... 1" 232 bytes 256/256 256/254 256/253 256/252
      "123456789 1234...12" 233 bytes 256/256 256/254 256/253 256/252
      "123456789 1234...89" 250 bytes 256/256 256/254 256/253 256/252
      "123456789 1234...9 " 251 bytes 384/258 256/255 256/254 256/253
      "123456789 1234...45" 256 bytes 384/263 384/261 384/260 384/259
      "123456789 1234...56" 257 bytes 384/265 384/263 384/262 384/261

      Solving the integration problem

      This problem is mostly solved by having ustr's store their data as a valid C-style string at all times (although it can have NIL bytes in it, which will confuse other APIs if you only pass the ustr_cstr() value.

      Also as you will see below it is trivial to "port" designs using common methods to use ustr.

      Solving the stack allocation problem

      There is a simple solution to this problem, ustr strings can be allocated on the stack. For example:

      char buf_store[USTR_SIZE_FIXED(1024)];
      Ustr *s1 = USTR_SC_INIT_AUTO(buf_store, FALSE, 0);
      

      The second argument says if the ustr should should be of limited size (and so fail if too much data is added to it) or not and thus it should automatically be converted to heap based storage if you try and add too much data to it (and thus needing to be ustr_free()d). So you can still do that, if you think you need to ... and it'll now be managed, faster and safer.

      You can call ustr_free() on ustr's on the stack, and they will not be passed to free. Also if they get duplicated the duplication comes from the heap (you cannot create references to a fixed ustr).

      Solving the initialization problem

      There is a simple solution to this problem, ustr strings can be constant C-strings. For example:

      Ustr *s1 = USTR("");
      Ustr *s2 = USTR1(\xF, "123456789 12345");
      Ustr *s3 = USTR1(\x18, "123456789 123456789 1234");      /* 24 byte length */
      Ustr *s4 = USTR2(\x1, \x44, "1234589 12" ... "89 1234"); /* 324 byte length */
      

      As with the stack based ustr's, calling ustr_free() doesn't actually free these strings. Also as they are read-only strings, calling ustr_dup() on them will just return the pointer itself (Ie. no allocations happen). Apart from that they act as ustr's in every way. This means that you can initialize things to default values in other structs/arrays, and then add/delete/alter data in them like normal ustr's.

      Note that although the length is specified manually above when ustr is running in debugging mode it will validate all strings, and will instantly spot a badly defined read-only ustr ... allowing you to fix the problem.

      Solving the LICENSE problem

      The License for the code is MIT, new-BSD, LGPL, etc. ... if you need another license to help compatibility, just ask for it. It's basically public domain, without all the legal problems for everyone that trying to make something public domain entails.

      The "optimization" of string.h usage

      With ustr, due to it keeping the data as a valid C-style string all the time, you can just call ustr_cstr(), to get a (const char *), or ustr_wstr(), to get a (char *), at any time. Use whatever algorithm you need to.

      If you are worried about the "inefficiency" of growing the string to the correct size you can also pre-allocate a ustr of the size you think you need, thus using a single malloc() call (and memcpy()'s to add the data). This is basically as fast is it could be made to go by hand ... and it'll now be managed and safer.

      One point worth highlighting here is that people often assume they know where the performance problems are going to be, however I've seen benchmark runs of C-style string using code where the function that used the most CPU time was strcmp(). For certain workloads general C-style strings are horribly inefficient at answering the question "are these two strings equal", ustr solves that problem with ustr_cmp_eq() and in a similar vein also provides ustr_fast_cmp() for when you need to sort the strings but don't care what order the sort is in.

      GDB macros for easy debugging

      The big problem here is that when you have a core dump you can't call any functions to find out data about the string. Thus. I've written some gdb macros here which mean all you have to do is type "pustr_all s1" etc.

      A Significant example of usage, with comments

      Ustr *s1 = USTR("");          /* == "", always works */
      Ustr *s2 = ustr_dup(s1);      /* == "", always works */
      Ustr *s3 = ustr_dup_cstr(""); /* == "", always works */
      
      ustr_cmp_eq(s1, s2); /* == TRUE */
      ustr_cmp_eq(s1, s3); /* == TRUE */
      
      if (ustr_shared(s2)) /* This is  TRUE, as a constant/read-only string cannot be free'd */
        /* whatever */ ;
      
      if (ustr_ro(s2))    /* This is  TRUE */
        /* whatever */ ;
      
      if (!ustr_add_fmt(&s2, "%s %d %c%d", "x", 4, 0, 8))
        /* error */ ;
      
      if (ustr_owner(s1)) /* This will return FALSE, as noone owns the "" read-only string */
        /* whatever */ ;
      if (ustr_owner(s2)) /* This will return  TRUE, as we've now got allocated memory for s2 */
        /* whatever */ ;
      
      foo_API(ustr_cstr(s1), ustr_len(s1)); /* == "", 0 */
      foo_API(ustr_cstr(s2), ustr_len(s2)); /* == "x 4 \0008", 6 */
      
      s3 = ustr_dup(s2); /* don't need to free s3 as it's empty */
                         /* don't need to check for errors as s2 == s3 */
      
      if (ustr_owner(s2))  /* This will now return FALSE, we've got two references: s2 and s3 */
        /* whatever */ ;
      if (ustr_shared(s2)) /* This is FALSE, it's a non-shared string referenced by both s2 and s3 */
        /* whatever */ ;
      
      ustr_free(s2); /* free'd one reference to the data pointed to by both s2 and s3 */
      
      ustr_setf_share(s2);  /* Make s2/s3 "shared" data,
                               so it always has infinite references */
      
      if (ustr_shared(s2)) /* This is  TRUE */
        /* whatever */ ;
      if (ustr_ro(s2))     /* This is FALSE */
        /* whatever */ ;
      
      s3 = ustr_dup(s2); /* This is the same as s3 = s2; */
      ustr_free(s2);     /* These do nothing */
      ustr_free(s2);
      ustr_free(s2);
      ustr_free(s2);
      
      if (!ustr_add_cstr(&s3, "abcd"))
        /* error */ ;
      
      ustr_add_cstr(&s3, "1234");
      ustr_add_cstr(&s3, "xyz");
      
      if (ustr_enomem(s3)) /* check for errors on the last 2 ustr_add_cstr() functions at once
                              ustr_owner(x) has to be true for this to be reliable,
                              hence the explicit first check */
        /* error */ ;
      
      ustr_setf_owner(s2); /* Make s2 be "non-shared" and have a single owner */
      ustr_setf_owner(s1); /* This fails, as you can't make a read-only string be "non-shared" */
      
      ustr_sc_del(&s2); /* free'd s2 and set s2 = USTR("") */
      
      ustr_cmp_eq(s1, s2); /* == TRUE */
      
      s2 = USTR1(\x0b, "Hello world"); /* Constant string with data */
      
      if (ustr_shared(s2)) /* This is  TRUE */
        /* whatever */ ;
      if (ustr_ro(s2))     /* This is  TRUE */
        /* whatever */ ;
      
      /* don't need to "free" anything else */
      

      You can look at/download the code here or the code for the examples here.


      James Antill
      Last modified: Wed Mar 5 20:55:53 EST 2008 ustr-1.0.4/Documentation/ustr.30000644000076400007640000067244010763530041015407 0ustar jamesjames.TH ustr 3 "05-Mar-2008" "Ustr 1.0.4" "Ustr String Library" .SH "NAME" ustr \- ustr string library functions .SH "SYNOPSIS" .in \w' 'u #include "ustr.h" .sp .sp .br .in \w' struct Ustr *\fBUSTR\fR('u .ti \w' 'u struct Ustr *\fBUSTR\fR(void *); .br .in \w' struct Ustrp *\fBUSTRP\fR('u .ti \w' 'u struct Ustrp *\fBUSTRP\fR(void *); .br .in \w' struct Ustr *\fBUSTR1\fR('u .ti \w' 'u struct Ustr *\fBUSTR1\fR(symbol, const char[]); .br .in \w' struct Ustr *\fBUSTR2\fR('u .ti \w' 'u struct Ustr *\fBUSTR2\fR(symbol, symbol, const char[]); .br .in \w' struct Ustr *\fBUSTR4\fR('u .ti \w' 'u struct Ustr *\fBUSTR4\fR(symbol, symbol, symbol, symbol, const char[]); .br .in \w' struct Ustr *\fBUSTR1_CHK\fR('u .ti \w' 'u struct Ustr *\fBUSTR1_CHK\fR(symbol, const char[]); .br .in \w' struct Ustr *\fBUSTR2_CHK\fR('u .ti \w' 'u struct Ustr *\fBUSTR2_CHK\fR(symbol, symbol, const char[]); .br .in \w' struct Ustr *\fBUSTR4_CHK\fR('u .ti \w' 'u struct Ustr *\fBUSTR4_CHK\fR(symbol, symbol, symbol, symbol, const char[]); .br .in \w' struct Ustr *\fBUSTRP1\fR('u .ti \w' 'u struct Ustr *\fBUSTRP1\fR(symbol, const char[]); .br .in \w' struct Ustr *\fBUSTRP2\fR('u .ti \w' 'u struct Ustr *\fBUSTRP2\fR(symbol, symbol, const char[]); .br .in \w' struct Ustrp *\fBUSTRP4\fR('u .ti \w' 'u struct Ustrp *\fBUSTRP4\fR(symbol, symbol, symbol, symbol, const char[]); .br .in \w' struct Ustr *\fBUSTRP1_CHK\fR('u .ti \w' 'u struct Ustr *\fBUSTRP1_CHK\fR(symbol, const char[]); .br .in \w' struct Ustr *\fBUSTRP2_CHK\fR('u .ti \w' 'u struct Ustr *\fBUSTRP2_CHK\fR(symbol, symbol, const char[]); .br .in \w' struct Ustrp *\fBUSTRP4_CHK\fR('u .ti \w' 'u struct Ustrp *\fBUSTRP4_CHK\fR(symbol, symbol, symbol, symbol, const char[]); .sp .br .in \w' size_t \fBUSTR_SIZE_FIXED\fR('u .ti \w' 'u size_t \fBUSTR_SIZE_FIXED\fR(size_t); .br .in \w' struct Ustr *\fBustr_init_fixed\fR('u .ti \w' 'u struct Ustr *\fBustr_init_fixed\fR(void *, size_t, int, size_t); .br .in \w' struct Ustr *\fBUSTR_SC_INIT_AUTO\fR('u .ti \w' 'u struct Ustr *\fBUSTR_SC_INIT_AUTO\fR(char[], int, size_t); .br .in \w' struct Ustr *\fBUSTR_SC_INIT_AUTO_OSTR\fR('u .ti \w' 'u struct Ustr *\fBUSTR_SC_INIT_AUTO_OSTR\fR(char[], int, size_t); .sp .br .in \w' int \fBustr_assert_valid\fR('u .ti \w' 'u int \fBustr_assert_valid\fR(Ustr *); .br .in \w' int \fBustr_assert_valid_subustr\fR('u .ti \w' 'u int \fBustr_assert_valid_subustr\fR(Ustr *, size_t, size_t); .br .in \w' int \fBUSTR_CNTL_MALLOC_CHECK_BEG\fR('u .ti \w' 'u int \fBUSTR_CNTL_MALLOC_CHECK_BEG\fR(int); .br .in \w' int \fBUSTR_CNTL_MALLOC_CHECK_LVL\fR('u .ti \w' 'u int \fBUSTR_CNTL_MALLOC_CHECK_LVL\fR(void); .br .in \w' int \fBUSTR_CNTL_MALLOC_CHECK_MEM\fR('u .ti \w' 'u int \fBUSTR_CNTL_MALLOC_CHECK_MEM\fR(void *); .br .in \w' int \fBUSTR_CNTL_MALLOC_CHECK_MEM_SZ\fR('u .ti \w' 'u int \fBUSTR_CNTL_MALLOC_CHECK_MEM_SZ\fR(void *, size_t); .br .in \w' int \fBUSTR_CNTL_MALLOC_CHECK_MEM_MINSZ\fR('u .ti \w' 'u int \fBUSTR_CNTL_MALLOC_CHECK_MEM_MINSZ\fR(void *, size_t); .br .in \w' int \fBUSTR_CNTL_MALLOC_CHECK_MEM_USTR\fR('u .ti \w' 'u int \fBUSTR_CNTL_MALLOC_CHECK_MEM_USTR\fR(Ustr *); .br .in \w' int \fBUSTR_CNTL_MALLOC_CHECK_MEM_USTRP\fR('u .ti \w' 'u int \fBUSTR_CNTL_MALLOC_CHECK_MEM_USTRP\fR(Ustrp *); .br .in \w' int \fBUSTR_CNTL_MALLOC_CHECK_END\fR('u .ti \w' 'u int \fBUSTR_CNTL_MALLOC_CHECK_END\fR(void); .br .in \w' int \fBUSTR_CNTL_MALLOC_CHECK_ADD\fR('u .ti \w' 'u int \fBUSTR_CNTL_MALLOC_CHECK_ADD\fR(int); .br .in \w' int \fBUSTR_CNTL_MALLOC_CHECK_DEL\fR('u .ti \w' 'u int \fBUSTR_CNTL_MALLOC_CHECK_DEL\fR(int); .sp .br .in \w' size_t \fBustr_init_size\fR('u .ti \w' 'u size_t \fBustr_init_size\fR(size_t, size_t, int, size_t); .br .in \w' struct Ustr *\fBustr_init_alloc\fR('u .ti \w' 'u struct Ustr *\fBustr_init_alloc\fR(void *, size_t, size_t, size_t, int, int, size_t); .br .in \w' struct Ustr *\fBustr_dupx_empty\fR('u .ti \w' 'u struct Ustr *\fBustr_dupx_empty\fR(size_t, size_t, int, int); .br .in \w' struct Ustr *\fBustr_dup_empty\fR('u .ti \w' 'u struct Ustr *\fBustr_dup_empty\fR(void); .br .in \w' struct Ustr *\fBustr_dupx_undef\fR('u .ti \w' 'u struct Ustr *\fBustr_dupx_undef\fR(size_t, size_t, int, int, size_t); .br .in \w' struct Ustr *\fBustr_dup_undef\fR('u .ti \w' 'u struct Ustr *\fBustr_dup_undef\fR(size_t); .br .in \w' struct Ustr *\fBustr_dup\fR('u .ti \w' 'u struct Ustr *\fBustr_dup\fR(const struct Ustr *); .br .in \w' struct Ustr *\fBustr_dupx\fR('u .ti \w' 'u struct Ustr *\fBustr_dupx\fR(size_t, size_t, int, int, const struct Ustr *); .br .in \w' struct Ustr *\fBustr_sc_dup\fR('u .ti \w' 'u struct Ustr *\fBustr_sc_dup\fR(struct Ustr **); .br .in \w' struct Ustr *\fBustr_sc_dupx\fR('u .ti \w' 'u struct Ustr *\fBustr_sc_dupx\fR(size_t, size_t, int, int, struct Ustr **); .br .in \w' struct Ustr *\fBustr_dup_buf\fR('u .ti \w' 'u struct Ustr *\fBustr_dup_buf\fR(const void *, size_t); .br .in \w' struct Ustr *\fBustr_dupx_buf\fR('u .ti \w' 'u struct Ustr *\fBustr_dupx_buf\fR(size_t, size_t, int, int, const void *, size_t); .br .in \w' struct Ustr *\fBustr_dup_cstr\fR('u .ti \w' 'u struct Ustr *\fBustr_dup_cstr\fR(const char *); .br .in \w' struct Ustr *\fBustr_dupx_cstr\fR('u .ti \w' 'u struct Ustr *\fBustr_dupx_cstr\fR(size_t, size_t, int, int, const char *); .br .in \w' struct Ustr *\fBUSTR_DUP_OSTR\fR('u .ti \w' 'u struct Ustr *\fBUSTR_DUP_OSTR\fR(const char []); .br .in \w' struct Ustr *\fBUSTR_DUP_OBJ\fR('u .ti \w' 'u struct Ustr *\fBUSTR_DUP_OBJ\fR(...); .br .in \w' struct Ustr *\fBustr_dup_subustr\fR('u .ti \w' 'u struct Ustr *\fBustr_dup_subustr\fR(const struct Ustr *, size_t, size_t); .br .in \w' struct Ustr *\fBustr_dupx_subustr\fR('u .ti \w' 'u struct Ustr *\fBustr_dupx_subustr\fR(size_t, size_t, int, int, const struct Ustr *, size_t, size_t); .br .in \w' struct Ustr *\fBustr_dup_rep_chr\fR('u .ti \w' 'u struct Ustr *\fBustr_dup_rep_chr\fR(char, size_t); .br .in \w' struct Ustr *\fBustr_dupx_rep_chr\fR('u .ti \w' 'u struct Ustr *\fBustr_dupx_rep_chr\fR(size_t, size_t, int, int, char, size_t); .br .in \w' struct Ustr *\fBustr_sc_vjoin\fR('u .ti \w' 'u struct Ustr *\fBustr_sc_vjoin\fR(const struct Ustr *, const struct Ustr *, const struct Ustr *, va_list); .br .in \w' struct Ustr *\fBustr_sc_join\fR('u .ti \w' 'u struct Ustr *\fBustr_sc_join\fR(const struct Ustr *, const struct Ustr *, const struct Ustr *, ...); .br .in \w' struct Ustr *\fBustr_sc_vjoinx\fR('u .ti \w' 'u struct Ustr *\fBustr_sc_vjoinx\fR(size_t, size_t, int, int, const struct Ustr *, const struct Ustr *, const struct Ustr *, va_list); .br .in \w' struct Ustr *\fBustr_sc_joinx\fR('u .ti \w' 'u struct Ustr *\fBustr_sc_joinx\fR(size_t, size_t, int, int, const struct Ustr *, const struct Ustr *, const struct Ustr *, ...); .br .in \w' struct Ustr *\fBustr_sc_vconcat\fR('u .ti \w' 'u struct Ustr *\fBustr_sc_vconcat\fR(const struct Ustr *, va_list); .br .in \w' struct Ustr *\fBustr_sc_concat\fR('u .ti \w' 'u struct Ustr *\fBustr_sc_concat\fR(const struct Ustr *, ...); .br .in \w' struct Ustr *\fBustr_sc_vconcatx\fR('u .ti \w' 'u struct Ustr *\fBustr_sc_vconcatx\fR(size_t, size_t, int, int, const struct Ustr *, va_list); .br .in \w' struct Ustr *\fBustr_sc_concatx\fR('u .ti \w' 'u struct Ustr *\fBustr_sc_concatx\fR(size_t, size_t, int, int, const struct Ustr *, ...); .sp .br .in \w' void \fBustr_free\fR('u .ti \w' 'u void \fBustr_free\fR(struct Ustr *); .br .in \w' void \fBustrp_free\fR('u .ti \w' 'u void \fBustrp_free\fR(struct Ustr_pool *, struct Ustrp *); .br .in \w' void \fBustr_sc_free\fR('u .ti \w' 'u void \fBustr_sc_free\fR(struct Ustr **); .br .in \w' void \fBustr_sc_free2\fR('u .ti \w' 'u void \fBustr_sc_free2\fR(struct Ustr **, struct Ustr *); .br .in \w' void \fBustr_sc_free_shared\fR('u .ti \w' 'u void \fBustr_sc_free_shared\fR(struct Ustr **); .br .in \w' int \fBustr_del\fR('u .ti \w' 'u int \fBustr_del\fR(struct Ustr **, size_t); .br .in \w' int \fBustr_del_subustr\fR('u .ti \w' 'u int \fBustr_del_subustr\fR(struct Ustr **, size_t, size_t); .br .in \w' void \fBustr_sc_del\fR('u .ti \w' 'u void \fBustr_sc_del\fR(struct Ustr **); .sp .br .in \w' int \fBustr_add_undef\fR('u .ti \w' 'u int \fBustr_add_undef\fR(struct Ustr **, size_t); .br .in \w' int \fBustr_add_buf\fR('u .ti \w' 'u int \fBustr_add_buf\fR(struct Ustr **, const void *, size_t); .br .in \w' int \fBustr_add_cstr\fR('u .ti \w' 'u int \fBustr_add_cstr\fR(struct Ustr **, const char *); .br .in \w' int \fBUSTR_ADD_OSTR\fR('u .ti \w' 'u int \fBUSTR_ADD_OSTR\fR(struct Ustr **, const char []); .br .in \w' int \fBUSTR_ADD_OBJ\fR('u .ti \w' 'u int \fBUSTR_ADD_OBJ\fR(struct Ustr **, ...); .br .in \w' int \fBustr_add\fR('u .ti \w' 'u int \fBustr_add\fR(struct Ustr **, const struct Ustr *); .br .in \w' int \fBustr_add_subustr\fR('u .ti \w' 'u int \fBustr_add_subustr\fR(struct Ustr **, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_add_rep_chr\fR('u .ti \w' 'u int \fBustr_add_rep_chr\fR(struct Ustr **, char, size_t); .sp .br .in \w' int \fBustr_set_undef\fR('u .ti \w' 'u int \fBustr_set_undef\fR(struct Ustr **, size_t); .br .in \w' int \fBustr_set_empty\fR('u .ti \w' 'u int \fBustr_set_empty\fR(struct Ustr **); .br .in \w' int \fBustr_set_buf\fR('u .ti \w' 'u int \fBustr_set_buf\fR(struct Ustr **, const void *, size_t); .br .in \w' int \fBustr_set_cstr\fR('u .ti \w' 'u int \fBustr_set_cstr\fR(struct Ustr **, const char *); .br .in \w' int \fBUSTR_SET_OSTR\fR('u .ti \w' 'u int \fBUSTR_SET_OSTR\fR(struct Ustr **, const char []); .br .in \w' int \fBUSTR_SET_OBJ\fR('u .ti \w' 'u int \fBUSTR_SET_OBJ\fR(struct Ustr **, ...); .br .in \w' int \fBustr_set\fR('u .ti \w' 'u int \fBustr_set\fR(struct Ustr **, const struct Ustr *); .br .in \w' int \fBustr_set_subustr\fR('u .ti \w' 'u int \fBustr_set_subustr\fR(struct Ustr **, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_set_rep_chr\fR('u .ti \w' 'u int \fBustr_set_rep_chr\fR(struct Ustr **, char, size_t); .sp .br .in \w' int \fBustr_ins_undef\fR('u .ti \w' 'u int \fBustr_ins_undef\fR(struct Ustr **, size_t, size_t); .br .in \w' int \fBustr_ins_buf\fR('u .ti \w' 'u int \fBustr_ins_buf\fR(struct Ustr **, size_t, const void *, size_t); .br .in \w' int \fBustr_ins_cstr\fR('u .ti \w' 'u int \fBustr_ins_cstr\fR(struct Ustr **, size_t, const char *); .br .in \w' int \fBUSTR_INS_OSTR\fR('u .ti \w' 'u int \fBUSTR_INS_OSTR\fR(struct Ustr **, size_t, const char []); .br .in \w' int \fBUSTR_INS_OBJ\fR('u .ti \w' 'u int \fBUSTR_INS_OBJ\fR(struct Ustr **, size_t, ...); .br .in \w' int \fBustr_ins\fR('u .ti \w' 'u int \fBustr_ins\fR(struct Ustr **, size_t, const struct Ustr *); .br .in \w' int \fBustr_ins_subustr\fR('u .ti \w' 'u int \fBustr_ins_subustr\fR(struct Ustr **, size_t, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_ins_rep_chr\fR('u .ti \w' 'u int \fBustr_ins_rep_chr\fR(struct Ustr **, size_t, char, size_t); .sp .br .in \w' int \fBustr_add_vfmt_lim\fR('u .ti \w' 'u int \fBustr_add_vfmt_lim\fR(struct Ustr **, size_t, const char *, va_list); .br .in \w' int \fBustr_add_vfmt\fR('u .ti \w' 'u int \fBustr_add_vfmt\fR(struct Ustr **, const char *, va_list); .br .in \w' int \fBustr_add_fmt_lim\fR('u .ti \w' 'u int \fBustr_add_fmt_lim\fR(struct Ustr **, size_t, const char *, ...); .br .in \w' int \fBustr_add_fmt\fR('u .ti \w' 'u int \fBustr_add_fmt\fR(struct Ustr **, const char *, ...); .br .in \w' struct Ustr *\fBustr_dup_vfmt_lim\fR('u .ti \w' 'u struct Ustr *\fBustr_dup_vfmt_lim\fR(size_t, const char *, va_list); .br .in \w' struct Ustr *\fBustr_dup_vfmt\fR('u .ti \w' 'u struct Ustr *\fBustr_dup_vfmt\fR(size_t, const char *, va_list); .br .in \w' struct Ustr *\fBustr_dup_fmt_lim\fR('u .ti \w' 'u struct Ustr *\fBustr_dup_fmt_lim\fR(size_t, const char *, ...); .br .in \w' struct Ustr *\fBustr_dup_fmt\fR('u .ti \w' 'u struct Ustr *\fBustr_dup_fmt\fR(const char *, ...); .br .in \w' struct Ustr *\fBustr_dupx_fmt_lim\fR('u .ti \w' 'u struct Ustr *\fBustr_dupx_fmt_lim\fR(size_t, size_t, int, int, size_t, const char *, ...); .br .in \w' struct Ustr *\fBustr_dupx_fmt\fR('u .ti \w' 'u struct Ustr *\fBustr_dupx_fmt\fR(size_t, size_t, int, int, const char *, ...); .br .in \w' int \fBustr_set_vfmt_lim\fR('u .ti \w' 'u int \fBustr_set_vfmt_lim\fR(struct Ustr **, size_t, const char *, va_list); .br .in \w' int \fBustr_set_vfmt\fR('u .ti \w' 'u int \fBustr_set_vfmt\fR(struct Ustr **, const char *, va_list); .br .in \w' int \fBustr_set_fmt_lim\fR('u .ti \w' 'u int \fBustr_set_fmt_lim\fR(struct Ustr **, size_t, const char *, ...); .br .in \w' int \fBustr_set_fmt\fR('u .ti \w' 'u int \fBustr_set_fmt\fR(struct Ustr **, const char *, ...); .br .in \w' int \fBustr_ins_vfmt_lim\fR('u .ti \w' 'u int \fBustr_ins_vfmt_lim\fR(struct Ustr **, size_t, size_t, const char *, va_list); .br .in \w' int \fBustr_ins_vfmt\fR('u .ti \w' 'u int \fBustr_ins_vfmt\fR(struct Ustr **, size_t, const char *, va_list); .br .in \w' int \fBustr_ins_fmt_lim\fR('u .ti \w' 'u int \fBustr_ins_fmt_lim\fR(struct Ustr **, size_t, size_t, const char *, ...); .br .in \w' int \fBustr_ins_fmt\fR('u .ti \w' 'u int \fBustr_ins_fmt\fR(struct Ustr **, size_t, const char *, ...); .br .in \w' int \fBustr_sub_vfmt_lim\fR('u .ti \w' 'u int \fBustr_sub_vfmt_lim\fR(struct Ustr **, size_t, size_t, const char *, va_list); .br .in \w' int \fBustr_sub_vfmt\fR('u .ti \w' 'u int \fBustr_sub_vfmt\fR(struct Ustr **, size_t, const char *, va_list); .br .in \w' int \fBustr_sub_fmt_lim\fR('u .ti \w' 'u int \fBustr_sub_fmt_lim\fR(struct Ustr **, size_t, size_t, const char *, ...); .br .in \w' int \fBustr_sub_fmt\fR('u .ti \w' 'u int \fBustr_sub_fmt\fR(struct Ustr **, size_t, const char *, ...); .br .in \w' int \fBustr_sc_sub_vfmt_lim\fR('u .ti \w' 'u int \fBustr_sc_sub_vfmt_lim\fR(struct Ustr **, size_t, size_t, size_t, const char *, va_list); .br .in \w' int \fBustr_sc_sub_vfmt\fR('u .ti \w' 'u int \fBustr_sc_sub_vfmt\fR(struct Ustr **, size_t, size_t, const char *, va_list); .br .in \w' int \fBustr_sc_sub_fmt_lim\fR('u .ti \w' 'u int \fBustr_sc_sub_fmt_lim\fR(struct Ustr **, size_t, size_t, size_t, const char *, ...); .br .in \w' int \fBustr_sc_sub_fmt\fR('u .ti \w' 'u int \fBustr_sc_sub_fmt\fR(struct Ustr **, size_t, size_t, const char *, ...); .sp .br .in \w' size_t \fBustr_len\fR('u .ti \w' 'u size_t \fBustr_len\fR(const struct Ustr *); .br .in \w' const char *\fBustr_cstr\fR('u .ti \w' 'u const char *\fBustr_cstr\fR(const struct Ustr *); .br .in \w' char *\fBustr_wstr\fR('u .ti \w' 'u char *\fBustr_wstr\fR(struct Ustr *); .br .in \w' int \fBustr_alloc\fR('u .ti \w' 'u int \fBustr_alloc\fR(const struct Ustr *); .br .in \w' int \fBustr_exact\fR('u .ti \w' 'u int \fBustr_exact\fR(const struct Ustr *); .br .in \w' int \fBustr_sized\fR('u .ti \w' 'u int \fBustr_sized\fR(const struct Ustr *); .br .in \w' int \fBustr_ro\fR('u .ti \w' 'u int \fBustr_ro\fR(const struct Ustr *); .br .in \w' int \fBustr_fixed\fR('u .ti \w' 'u int \fBustr_fixed\fR(const struct Ustr *); .br .in \w' int \fBustr_enomem\fR('u .ti \w' 'u int \fBustr_enomem\fR(const struct Ustr *); .br .in \w' int \fBustr_shared\fR('u .ti \w' 'u int \fBustr_shared\fR(const struct Ustr *); .br .in \w' int \fBustr_limited\fR('u .ti \w' 'u int \fBustr_limited\fR(const struct Ustr *); .br .in \w' int \fBustr_owner\fR('u .ti \w' 'u int \fBustr_owner\fR(const struct Ustr *); .br .in \w' size_t \fBustr_size\fR('u .ti \w' 'u size_t \fBustr_size\fR(const struct Ustr *); .br .in \w' size_t \fBustr_size_alloc\fR('u .ti \w' 'u size_t \fBustr_size_alloc\fR(const struct Ustr *); .br .in \w' size_t \fBustr_size_overhead\fR('u .ti \w' 'u size_t \fBustr_size_overhead\fR(const struct Ustr *); .br .in \w' void \fBustr_conf\fR('u .ti \w' 'u void \fBustr_conf\fR(const struct Ustr *, size_t *, size_t *, int *, size_t *, size_t *); .sp .br .in \w' int \fBustr_setf_enomem_err\fR('u .ti \w' 'u int \fBustr_setf_enomem_err\fR(struct Ustr *); .br .in \w' int \fBustr_setf_enomem_clr\fR('u .ti \w' 'u int \fBustr_setf_enomem_clr\fR(struct Ustr *); .br .in \w' int \fBustr_setf_share\fR('u .ti \w' 'u int \fBustr_setf_share\fR(struct Ustr *); .br .in \w' int \fBustr_setf_owner\fR('u .ti \w' 'u int \fBustr_setf_owner\fR(struct Ustr *); .sp .br .in \w' int \fBustr_cmp_buf\fR('u .ti \w' 'u int \fBustr_cmp_buf\fR(const struct Ustr *, const void *, size_t); .br .in \w' int \fBustr_cmp\fR('u .ti \w' 'u int \fBustr_cmp\fR(const struct Ustr *, const struct Ustr *); .br .in \w' int \fBustr_cmp_subustr\fR('u .ti \w' 'u int \fBustr_cmp_subustr\fR(const struct Ustr *, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_cmp_cstr\fR('u .ti \w' 'u int \fBustr_cmp_cstr\fR(const struct Ustr *, const char *); .br .in \w' int \fBustr_cmp_fast_buf\fR('u .ti \w' 'u int \fBustr_cmp_fast_buf\fR(const struct Ustr *, const void *, size_t); .br .in \w' int \fBustr_cmp_fast\fR('u .ti \w' 'u int \fBustr_cmp_fast\fR(const struct Ustr *, const struct Ustr *); .br .in \w' int \fBustr_cmp_fast_subustr\fR('u .ti \w' 'u int \fBustr_cmp_fast_subustr\fR(const struct Ustr *, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_cmp_fast_cstr\fR('u .ti \w' 'u int \fBustr_cmp_fast_cstr\fR(const struct Ustr *, const char *); .br .in \w' int \fBustr_cmp_case_buf\fR('u .ti \w' 'u int \fBustr_cmp_case_buf\fR(const struct Ustr *, const void *, size_t); .br .in \w' int \fBustr_cmp_case\fR('u .ti \w' 'u int \fBustr_cmp_case\fR(const struct Ustr *, const struct Ustr *); .br .in \w' int \fBustr_cmp_case_subustr\fR('u .ti \w' 'u int \fBustr_cmp_case_subustr\fR(const struct Ustr *, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_cmp_case_cstr\fR('u .ti \w' 'u int \fBustr_cmp_case_cstr\fR(const struct Ustr *, const char *); .br .in \w' int \fBustr_cmp_eq\fR('u .ti \w' 'u int \fBustr_cmp_eq\fR(const struct Ustr *, const struct Ustr *); .br .in \w' int \fBustr_cmp_buf_eq\fR('u .ti \w' 'u int \fBustr_cmp_buf_eq\fR(const struct Ustr *, const void *, size_t); .br .in \w' int \fBustr_cmp_subustr_eq\fR('u .ti \w' 'u int \fBustr_cmp_subustr_eq\fR(const struct Ustr *, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_cmp_cstr_eq\fR('u .ti \w' 'u int \fBustr_cmp_cstr_eq\fR(const struct Ustr *, const char *); .br .in \w' int \fBustr_cmp_case_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_eq\fR(const struct Ustr *, const struct Ustr *); .br .in \w' int \fBustr_cmp_case_buf_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_buf_eq\fR(const struct Ustr *, const void *, size_t); .br .in \w' int \fBustr_cmp_case_subustr_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_subustr_eq\fR(const struct Ustr *, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_cmp_case_cstr_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_cstr_eq\fR(const struct Ustr *, const char *); .br .in \w' int \fBustr_cmp_prefix_eq\fR('u .ti \w' 'u int \fBustr_cmp_prefix_eq\fR(const struct Ustr *, const struct Ustr *); .br .in \w' int \fBustr_cmp_prefix_buf_eq\fR('u .ti \w' 'u int \fBustr_cmp_prefix_buf_eq\fR(const struct Ustr *, const void *, size_t); .br .in \w' int \fBustr_cmp_prefix_cstr_eq\fR('u .ti \w' 'u int \fBustr_cmp_prefix_cstr_eq\fR(const struct Ustr *, const char *); .br .in \w' int \fBustr_cmp_prefix_subustr_eq\fR('u .ti \w' 'u int \fBustr_cmp_prefix_subustr_eq\fR(const struct Ustr *, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_cmp_case_prefix_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_prefix_eq\fR(const struct Ustr *, const struct Ustr *); .br .in \w' int \fBustr_cmp_case_prefix_buf_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_prefix_buf_eq\fR(const struct Ustr *, const void *, size_t); .br .in \w' int \fBustr_cmp_case_prefix_cstr_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_prefix_cstr_eq\fR(const struct Ustr *, const char *); .br .in \w' int \fBustr_cmp_case_prefix_subustr_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_prefix_subustr_eq\fR(const struct Ustr *, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_cmp_suffix_eq\fR('u .ti \w' 'u int \fBustr_cmp_suffix_eq\fR(const struct Ustr *, const struct Ustr *); .br .in \w' int \fBustr_cmp_suffix_buf_eq\fR('u .ti \w' 'u int \fBustr_cmp_suffix_buf_eq\fR(const struct Ustr *, const void *, size_t); .br .in \w' int \fBustr_cmp_suffix_cstr_eq\fR('u .ti \w' 'u int \fBustr_cmp_suffix_cstr_eq\fR(const struct Ustr *, const char *); .br .in \w' int \fBustr_cmp_suffix_subustr_eq\fR('u .ti \w' 'u int \fBustr_cmp_suffix_subustr_eq\fR(const struct Ustr *, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_cmp_case_suffix_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_suffix_eq\fR(const struct Ustr *, const struct Ustr *); .br .in \w' int \fBustr_cmp_case_suffix_buf_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_suffix_buf_eq\fR(const struct Ustr *, const void *, size_t); .br .in \w' int \fBustr_cmp_case_suffix_cstr_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_suffix_cstr_eq\fR(const struct Ustr *, const char *); .br .in \w' int \fBustr_cmp_case_suffix_subustr_eq\fR('u .ti \w' 'u int \fBustr_cmp_case_suffix_subustr_eq\fR(const struct Ustr *, const struct Ustr *, size_t, size_t); .sp .br .in \w' size_t \fBustr_srch_chr_fwd\fR('u .ti \w' 'u size_t \fBustr_srch_chr_fwd\fR(const struct Ustr *, size_t, char); .br .in \w' size_t \fBustr_srch_chr_rev\fR('u .ti \w' 'u size_t \fBustr_srch_chr_rev\fR(const struct Ustr *, size_t, char); .br .in \w' size_t \fBustr_srch_buf_fwd\fR('u .ti \w' 'u size_t \fBustr_srch_buf_fwd\fR(const struct Ustr *, size_t, const void *, size_t); .br .in \w' size_t \fBustr_srch_buf_rev\fR('u .ti \w' 'u size_t \fBustr_srch_buf_rev\fR(const struct Ustr *, size_t, const void *, size_t); .br .in \w' size_t \fBustr_srch_fwd\fR('u .ti \w' 'u size_t \fBustr_srch_fwd\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_srch_rev\fR('u .ti \w' 'u size_t \fBustr_srch_rev\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_srch_cstr_fwd\fR('u .ti \w' 'u size_t \fBustr_srch_cstr_fwd\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_srch_cstr_rev\fR('u .ti \w' 'u size_t \fBustr_srch_cstr_rev\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_srch_subustr_fwd\fR('u .ti \w' 'u size_t \fBustr_srch_subustr_fwd\fR(const struct Ustr *, size_t, const struct Ustr *, size_t, size_t); .br .in \w' size_t \fBustr_srch_subustr_rev\fR('u .ti \w' 'u size_t \fBustr_srch_subustr_rev\fR(const struct Ustr *, size_t, const struct Ustr *, size_t, size_t); .br .in \w' size_t \fBustr_srch_case_chr_fwd\fR('u .ti \w' 'u size_t \fBustr_srch_case_chr_fwd\fR(const struct Ustr *, size_t, char); .br .in \w' size_t \fBustr_srch_case_chr_rev\fR('u .ti \w' 'u size_t \fBustr_srch_case_chr_rev\fR(const struct Ustr *, size_t, char); .br .in \w' size_t \fBustr_srch_case_buf_fwd\fR('u .ti \w' 'u size_t \fBustr_srch_case_buf_fwd\fR(const struct Ustr *, size_t, const void *, size_t); .br .in \w' size_t \fBustr_srch_case_buf_rev\fR('u .ti \w' 'u size_t \fBustr_srch_case_buf_rev\fR(const struct Ustr *, size_t, const void *, size_t); .br .in \w' size_t \fBustr_srch_case_fwd\fR('u .ti \w' 'u size_t \fBustr_srch_case_fwd\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_srch_case_rev\fR('u .ti \w' 'u size_t \fBustr_srch_case_rev\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_srch_case_cstr_fwd\fR('u .ti \w' 'u size_t \fBustr_srch_case_cstr_fwd\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_srch_case_cstr_rev\fR('u .ti \w' 'u size_t \fBustr_srch_case_cstr_rev\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_srch_case_subustr_fwd\fR('u .ti \w' 'u size_t \fBustr_srch_case_subustr_fwd\fR(const struct Ustr *, size_t, const struct Ustr *, size_t, size_t); .br .in \w' size_t \fBustr_srch_case_subustr_rev\fR('u .ti \w' 'u size_t \fBustr_srch_case_subustr_rev\fR(const struct Ustr *, size_t, const struct Ustr *, size_t, size_t); .sp .br .in \w' size_t \fBustr_spn_chr_fwd\fR('u .ti \w' 'u size_t \fBustr_spn_chr_fwd\fR(const struct Ustr *, size_t, char); .br .in \w' size_t \fBustr_spn_chr_rev\fR('u .ti \w' 'u size_t \fBustr_spn_chr_rev\fR(const struct Ustr *, size_t, char); .br .in \w' size_t \fBustr_spn_chrs_fwd\fR('u .ti \w' 'u size_t \fBustr_spn_chrs_fwd\fR(const struct Ustr *, size_t, const char *, size_t); .br .in \w' size_t \fBustr_spn_chrs_rev\fR('u .ti \w' 'u size_t \fBustr_spn_chrs_rev\fR(const struct Ustr *, size_t, const char *, size_t); .br .in \w' size_t \fBustr_spn_fwd\fR('u .ti \w' 'u size_t \fBustr_spn_fwd\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_spn_rev\fR('u .ti \w' 'u size_t \fBustr_spn_rev\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_spn_cstr_fwd\fR('u .ti \w' 'u size_t \fBustr_spn_cstr_fwd\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_spn_cstr_rev\fR('u .ti \w' 'u size_t \fBustr_spn_cstr_rev\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_cspn_chr_fwd\fR('u .ti \w' 'u size_t \fBustr_cspn_chr_fwd\fR(const struct Ustr *, size_t, char); .br .in \w' size_t \fBustr_cspn_chr_rev\fR('u .ti \w' 'u size_t \fBustr_cspn_chr_rev\fR(const struct Ustr *, size_t, char); .br .in \w' size_t \fBustr_cspn_chrs_fwd\fR('u .ti \w' 'u size_t \fBustr_cspn_chrs_fwd\fR(const struct Ustr *, size_t, const char *, size_t); .br .in \w' size_t \fBustr_cspn_chrs_rev\fR('u .ti \w' 'u size_t \fBustr_cspn_chrs_rev\fR(const struct Ustr *, size_t, const char *, size_t); .br .in \w' size_t \fBustr_cspn_fwd\fR('u .ti \w' 'u size_t \fBustr_cspn_fwd\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_cspn_rev\fR('u .ti \w' 'u size_t \fBustr_cspn_rev\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_cspn_cstr_fwd\fR('u .ti \w' 'u size_t \fBustr_cspn_cstr_fwd\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_cspn_cstr_rev\fR('u .ti \w' 'u size_t \fBustr_cspn_cstr_rev\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_utf8_spn_chrs_fwd\fR('u .ti \w' 'u size_t \fBustr_utf8_spn_chrs_fwd\fR(const struct Ustr *, size_t, const char *, size_t); .br .in \w' size_t \fBustr_utf8_spn_chrs_rev\fR('u .ti \w' 'u size_t \fBustr_utf8_spn_chrs_rev\fR(const struct Ustr *, size_t, const char *, size_t); .br .in \w' size_t \fBustr_utf8_spn_fwd\fR('u .ti \w' 'u size_t \fBustr_utf8_spn_fwd\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_utf8_spn_rev\fR('u .ti \w' 'u size_t \fBustr_utf8_spn_rev\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_utf8_spn_cstr_fwd\fR('u .ti \w' 'u size_t \fBustr_utf8_spn_cstr_fwd\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_utf8_spn_cstr_rev\fR('u .ti \w' 'u size_t \fBustr_utf8_spn_cstr_rev\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_utf8_cspn_chrs_fwd\fR('u .ti \w' 'u size_t \fBustr_utf8_cspn_chrs_fwd\fR(const struct Ustr *, size_t, const char *, size_t); .br .in \w' size_t \fBustr_utf8_cspn_chrs_rev\fR('u .ti \w' 'u size_t \fBustr_utf8_cspn_chrs_rev\fR(const struct Ustr *, size_t, const char *, size_t); .br .in \w' size_t \fBustr_utf8_cspn_fwd\fR('u .ti \w' 'u size_t \fBustr_utf8_cspn_fwd\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_utf8_cspn_rev\fR('u .ti \w' 'u size_t \fBustr_utf8_cspn_rev\fR(const struct Ustr *, size_t, const struct Ustr *); .br .in \w' size_t \fBustr_utf8_cspn_cstr_fwd\fR('u .ti \w' 'u size_t \fBustr_utf8_cspn_cstr_fwd\fR(const struct Ustr *, size_t, const char *); .br .in \w' size_t \fBustr_utf8_cspn_cstr_rev\fR('u .ti \w' 'u size_t \fBustr_utf8_cspn_cstr_rev\fR(const struct Ustr *, size_t, const char *); .sp .br .in \w' int \fBustr_io_get\fR('u .ti \w' 'u int \fBustr_io_get\fR(struct Ustr **, FILE *, size_t, size_t *); .br .in \w' int \fBustr_io_getfile\fR('u .ti \w' 'u int \fBustr_io_getfile\fR(struct Ustr **, FILE *); .br .in \w' int \fBustr_io_getfilename\fR('u .ti \w' 'u int \fBustr_io_getfilename\fR(struct Ustr **, const char *); .br .in \w' int \fBustr_io_getdelim\fR('u .ti \w' 'u int \fBustr_io_getdelim\fR(struct Ustr **, FILE *, char); .br .in \w' int \fBustr_io_getline\fR('u .ti \w' 'u int \fBustr_io_getline\fR(struct Ustr **, FILE *); .br .in \w' int \fBustr_io_put\fR('u .ti \w' 'u int \fBustr_io_put\fR(struct Ustr **, FILE *, size_t); .br .in \w' int \fBustr_io_putline\fR('u .ti \w' 'u int \fBustr_io_putline\fR(struct Ustr **, FILE *, size_t); .br .in \w' int \fBustr_io_putfile\fR('u .ti \w' 'u int \fBustr_io_putfile\fR(struct Ustr **, FILE *); .br .in \w' int \fBustr_io_putfileline\fR('u .ti \w' 'u int \fBustr_io_putfileline\fR(struct Ustr **, FILE *); .br .in \w' int \fBustr_io_putfilename\fR('u .ti \w' 'u int \fBustr_io_putfilename\fR(struct Ustr **, const char *, const char *); .sp .br .in \w' int \fBustr_sub_undef\fR('u .ti \w' 'u int \fBustr_sub_undef\fR(struct Ustr **, size_t, size_t); .br .in \w' int \fBustr_sub_buf\fR('u .ti \w' 'u int \fBustr_sub_buf\fR(struct Ustr **, size_t, const void *, size_t); .br .in \w' int \fBustr_sub_cstr\fR('u .ti \w' 'u int \fBustr_sub_cstr\fR(struct Ustr **, size_t, const char *); .br .in \w' int \fBUSTR_SUB_OSTR\fR('u .ti \w' 'u int \fBUSTR_SUB_OSTR\fR(struct Ustr **, size_t, const char []); .br .in \w' int \fBUSTR_SUB_OBJ\fR('u .ti \w' 'u int \fBUSTR_SUB_OBJ\fR(struct Ustr **, size_t, ...); .br .in \w' int \fBustr_sub\fR('u .ti \w' 'u int \fBustr_sub\fR(struct Ustr **, size_t, const struct Ustr *); .br .in \w' int \fBustr_sub_subustr\fR('u .ti \w' 'u int \fBustr_sub_subustr\fR(struct Ustr **, size_t, const struct Ustr *, size_t, size_t); .br .in \w' int \fBustr_sc_sub_undef\fR('u .ti \w' 'u int \fBustr_sc_sub_undef\fR(struct Ustr **, size_t, size_t, size_t); .br .in \w' int \fBustr_sc_sub_buf\fR('u .ti \w' 'u int \fBustr_sc_sub_buf\fR(struct Ustr **, size_t , size_t , const void *, size_t ); .br .in \w' int \fBustr_sc_sub_cstr\fR('u .ti \w' 'u int \fBustr_sc_sub_cstr\fR(struct Ustr **, size_t, size_t, const char *); .br .in \w' int \fBustr_sc_sub\fR('u .ti \w' 'u int \fBustr_sc_sub\fR(struct Ustr **, size_t, size_t, const struct Ustr *); .br .in \w' int \fBustr_sc_sub_subustr\fR('u .ti \w' 'u int \fBustr_sc_sub_subustr\fR(struct Ustr **, size_t, size_t, const struct Ustr *, size_t, size_t); .br .in \w' int \fBUSTR_SC_SUB_OSTR\fR('u .ti \w' 'u int \fBUSTR_SC_SUB_OSTR\fR(struct Ustr **, size_t, size_t, const char []); .br .in \w' int \fBUSTR_SC_SUB_OBJ\fR('u .ti \w' 'u int \fBUSTR_SC_SUB_OBJ\fR(struct Ustr **, size_t, size_t, ...); .br .in \w' size_t \fBustr_replace_buf\fR('u .ti \w' 'u size_t \fBustr_replace_buf\fR(struct Ustr **, const void *, size_t, const void *, size_t, size_t); .br .in \w' size_t \fBustr_replace_cstr\fR('u .ti \w' 'u size_t \fBustr_replace_cstr\fR(struct Ustr **, const char *, const char *, size_t); .br .in \w' int \fBustr_replace\fR('u .ti \w' 'u int \fBustr_replace\fR(struct Ustr **, const struct Ustr *, const struct Ustr *, size_t); .br .in \w' size_t \fBustr_replace_rep_chr\fR('u .ti \w' 'u size_t \fBustr_replace_rep_chr\fR(struct Ustr **ps1, char, size_t, char, size_t nlen, size_t lim); .sp .br .in \w' struct Ustr *\fBustr_split_buf\fR('u .ti \w' 'u struct Ustr *\fBustr_split_buf\fR(const struct Ustr *, size_t *, const void *, size_t, struct Ustr *, unsigned int); .br .in \w' struct Ustr *\fBustr_split\fR('u .ti \w' 'u struct Ustr *\fBustr_split\fR(const struct Ustr *, size_t *, const struct Ustr *, struct Ustr *, unsigned int); .br .in \w' struct Ustr *\fBustr_split_cstr\fR('u .ti \w' 'u struct Ustr *\fBustr_split_cstr\fR(const struct Ustr *, size_t *, const char *, struct Ustr *, unsigned int); .br .in \w' struct Ustr *\fBustr_split_spn_chrs\fR('u .ti \w' 'u struct Ustr *\fBustr_split_spn_chrs\fR(const struct Ustr *, size_t *, const char *, size_t, struct Ustr *, unsigned int); .br .in \w' struct Ustr *\fBustr_split_spn_cstr\fR('u .ti \w' 'u struct Ustr *\fBustr_split_spn_cstr\fR(const struct Ustr *, size_t *, const char *, struct Ustr *, unsigned int); .br .in \w' struct Ustr *\fBustr_split_spn\fR('u .ti \w' 'u struct Ustr *\fBustr_split_spn\fR(const struct Ustr *, size_t *, const struct Ustr *, struct Ustr *, unsigned int); .sp .br .in \w' int \fBustr_utf8_valid\fR('u .ti \w' 'u int \fBustr_utf8_valid\fR(const struct Ustr *); .br .in \w' size_t \fBustr_utf8_len\fR('u .ti \w' 'u size_t \fBustr_utf8_len\fR(const struct Ustr *); .br .in \w' ssize_t \fBustr_utf8_width\fR('u .ti \w' 'u ssize_t \fBustr_utf8_width\fR(const struct Ustr *); .br .in \w' size_t \fBustr_utf8_chars2bytes\fR('u .ti \w' 'u size_t \fBustr_utf8_chars2bytes\fR(const struct Ustr *, size_t, size_t, size_t *); .br .in \w' size_t \fBustr_utf8_bytes2chars\fR('u .ti \w' 'u size_t \fBustr_utf8_bytes2chars\fR(const struct Ustr *, size_t, size_t, size_t *); .br .in \w' int \fBustr_sc_utf8_reverse\fR('u .ti \w' 'u int \fBustr_sc_utf8_reverse\fR(struct Ustr **); .sp .br .in \w' uintmax_t \fBustr_parse_uintmaxx\fR('u .ti \w' 'u uintmax_t \fBustr_parse_uintmaxx\fR(const struct Ustr *, size_t, unsigned int, uintmax_t, uintmax_t, const char *, size_t *, unsigned int *); .br .in \w' uintmax_t \fBustr_parse_uintmax\fR('u .ti \w' 'u uintmax_t \fBustr_parse_uintmax\fR(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *); .br .in \w' intmax_t \fBustr_parse_intmax\fR('u .ti \w' 'u intmax_t \fBustr_parse_intmax\fR(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *); .br .in \w' unsigned long \fBustr_parse_ulongx\fR('u .ti \w' 'u unsigned long \fBustr_parse_ulongx\fR(const struct Ustr *, size_t, unsigned int, unsigned long, unsigned long, const char *, size_t *, unsigned int *); .br .in \w' unsigned long \fBustr_parse_ulong\fR('u .ti \w' 'u unsigned long \fBustr_parse_ulong\fR(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *); .br .in \w' long \fBustr_parse_long\fR('u .ti \w' 'u long \fBustr_parse_long\fR(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *); .br .in \w' unsigned int \fBustr_parse_uint\fR('u .ti \w' 'u unsigned int \fBustr_parse_uint\fR(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *); .br .in \w' int \fBustr_parse_int\fR('u .ti \w' 'u int \fBustr_parse_int\fR(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *); .br .in \w' unsigned short \fBustr_parse_ushort\fR('u .ti \w' 'u unsigned short \fBustr_parse_ushort\fR(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *); .br .in \w' short \fBustr_parse_short\fR('u .ti \w' 'u short \fBustr_parse_short\fR(const struct Ustr *, size_t, unsigned int, size_t *, unsigned int *); .sp .br .in \w' int \fBustr_sc_ensure_owner\fR('u .ti \w' 'u int \fBustr_sc_ensure_owner\fR(struct Ustr **); .br .in \w' char *\fBustr_sc_wstr\fR('u .ti \w' 'u char *\fBustr_sc_wstr\fR(struct Ustr **); .br .in \w' char *\fBustr_sc_export_subustr\fR('u .ti \w' 'u char *\fBustr_sc_export_subustr\fR(const struct Ustr *, size_t, size_t, void *(*)(size_t)); .br .in \w' char *\fBustr_sc_export\fR('u .ti \w' 'u char *\fBustr_sc_export\fR(const struct Ustr *, void *(*)(size_t)); .br .in \w' char *\fBustrp_sc_export_subustrp\fR('u .ti \w' 'u char *\fBustrp_sc_export_subustrp\fR(struct Ustr_pool *, const struct Ustr *, size_t, size_t, void *(*)(size_t)); .br .in \w' char *\fBustrp_sc_export\fR('u .ti \w' 'u char *\fBustrp_sc_export\fR(struct Ustr_pool *, const struct Ustr *, void *(*)(size_t)); .br .in \w' int \fBustr_sc_reverse\fR('u .ti \w' 'u int \fBustr_sc_reverse\fR(struct Ustr **); .br .in \w' int \fBustr_sc_tolower\fR('u .ti \w' 'u int \fBustr_sc_tolower\fR(struct Ustr **); .br .in \w' int \fBustr_sc_toupper\fR('u .ti \w' 'u int \fBustr_sc_toupper\fR(struct Ustr **); .br .in \w' int \fBustr_sc_ltrim_chrs\fR('u .ti \w' 'u int \fBustr_sc_ltrim_chrs\fR(struct Ustr **, const char *, size_t); .br .in \w' int \fBustr_sc_ltrim\fR('u .ti \w' 'u int \fBustr_sc_ltrim\fR(struct Ustr **, const struct Ustr *); .br .in \w' int \fBustr_sc_ltrim_cstr\fR('u .ti \w' 'u int \fBustr_sc_ltrim_cstr\fR(struct Ustr **, const char *); .br .in \w' int \fBustr_sc_rtrim_chrs\fR('u .ti \w' 'u int \fBustr_sc_rtrim_chrs\fR(struct Ustr **, const char *, size_t); .br .in \w' int \fBustr_sc_rtrim\fR('u .ti \w' 'u int \fBustr_sc_rtrim\fR(struct Ustr **, const struct Ustr *); .br .in \w' int \fBustr_sc_rtrim_cstr\fR('u .ti \w' 'u int \fBustr_sc_rtrim_cstr\fR(struct Ustr **, const char *); .br .in \w' int \fBustr_sc_trim_chrs\fR('u .ti \w' 'u int \fBustr_sc_trim_chrs\fR(struct Ustr **, const char *, size_t); .br .in \w' int \fBustr_sc_trim\fR('u .ti \w' 'u int \fBustr_sc_trim\fR(struct Ustr **, const struct Ustr *); .br .in \w' int \fBustr_sc_trim_cstr\fR('u .ti \w' 'u int \fBustr_sc_trim_cstr\fR(struct Ustr **, const char *); .sp .br .in \w' int \fBustr_add_b_uint16\fR('u .ti \w' 'u int \fBustr_add_b_uint16\fR(struct Ustr **, uint_least16_t); .br .in \w' int \fBustr_add_b_uint32\fR('u .ti \w' 'u int \fBustr_add_b_uint32\fR(struct Ustr **, uint_least32_t); .br .in \w' int \fBustr_add_b_uint64\fR('u .ti \w' 'u int \fBustr_add_b_uint64\fR(struct Ustr **, uint_least64_t); .sp .br .in \w' uint_least16_t \fBustr_parse_b_uint16\fR('u .ti \w' 'u uint_least16_t \fBustr_parse_b_uint16\fR(const struct Ustr *, size_t); .br .in \w' uint_least32_t \fBustr_parse_b_uint32\fR('u .ti \w' 'u uint_least32_t \fBustr_parse_b_uint32\fR(const struct Ustr *, size_t); .br .in \w' uint_least64_t \fBustr_parse_b_uint64\fR('u .ti \w' 'u uint_least64_t \fBustr_parse_b_uint64\fR(const struct Ustr *, size_t); .sp .br .in \w' int \fBustr_realloc\fR('u .ti \w' 'u int \fBustr_realloc\fR(struct Ustr **, size_t); .br .in \w' int \fBustr_cntl_opt\fR('u .ti \w' 'u int \fBustr_cntl_opt\fR(int, ...); .sp .br .in \w' struct Ustr_pool *\fBustr_pool_ll_make\fR('u .ti \w' 'u struct Ustr_pool *\fBustr_pool_ll_make\fR(void); .br .in \w' struct Ustr_pool *\fBustr_pool_make_subpool\fR('u .ti \w' 'u struct Ustr_pool *\fBustr_pool_make_subpool\fR(struct Ustr_pool *); .br .in \w' void \fBustr_pool_free\fR('u .ti \w' 'u void \fBustr_pool_free\fR(struct Ustr_pool *); .br .in \w' void \fBustr_pool_clear\fR('u .ti \w' 'u void \fBustr_pool_clear\fR(struct Ustr_pool *); .ti .SH "DESCRIPTION" A very simple overview is that you can use ustr_dup_cstr() to convert a C\-style to a Ustr, and ustr_cstr() to convert it back. You can also use USTR1() to create constant/read\-only strings, and USTR_SC_INIT_AUTO() to create strings that use stack space upto a certain amount. Use is somewhat unique in that, by default, it has an average overhead of only 55% overhead over strdup(), for strings in the range of 0 to 20 bytes. Or, to put it another way it only uses 8 bytes to store a 2 byte string where strdup() uses 3. .SH Creating read\-only Ustr functions .ti -2 .br \fBFunction: \fR USTR() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to Ustr data .br Type\fB[1]\fR: void * .br \fBExplanation:\fR .br This macro function is normally used with the empty string "". .sp \fBNote:\fR .br There is basically just a simple cast behind the macro. .ti -2 .br \fBFunction: \fR USTRP() .br Returns: Ustrp string .br Type: struct Ustrp * .br Parameter\fB[1]\fR: Pointer to Ustrp data .br Type\fB[1]\fR: void * .br \fBExplanation:\fR .br This macro function is normally used with the empty string "". .sp \fBNote:\fR .br There is basically just a simple cast behind the macro. .ti -2 .br \fBFunction: \fR USTR1() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Encoded number of the length of Ustr string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Data for Ustr string .br Type\fB[2]\fR: const char[] .br \fBExplanation:\fR .br This macro function simplifies the creation of read\-only Ustr string's. And is normally used like... .Vb 4 USTR1(\\x4, "abcd") .Ve ...it is worth pointing out that running with debugging turned on (USTR_CONF_USE_ASSERT) will complain if the length isn't encoded correctly, as in... .Vb 4 USTR1(\\x3, "abcd") .Ve ...here ustr_assert_valid() will fail, which is called before most functions do anything in debugging mode. Note also that extra debugging (USTR_CONF_USE_EOS_MARK) will still catch cases like... .Vb 4 USTR1(\\x3, "abc\\0d") .Ve ...at least using debugging is esp. important if you are putting UTF\-8 characters into the strings. .sp \fBNote:\fR .br Having ustr_ro() return true means that the Ustr cannot be written to without be reallocated into allocation space ... not that ustr_add() etc. will fail. .br There is now USTR1_CHK() which performs a compile time check so you can never have an invalid ustr. .ti -2 .br \fBFunction: \fR USTR2() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Encoded 2nd byte of number of the length of Ustr string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Encoded 1st byte of number of the length of Ustr string .br Type\fB[2]\fR: symbol .br Parameter\fB[3]\fR: Data for Ustr string .br Type\fB[3]\fR: const char[] .br \fBExplanation:\fR .br This function works in the same way as USTR1() but takes two length bytes, so the read\-only string can be upto 65,535 (2**16 \- 1) bytes in length. .ti -2 .br \fBFunction: \fR USTR4() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Encoded 4th byte of number of the length of Ustr string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Encoded 3rd byte of number of the length of Ustr string .br Type\fB[2]\fR: symbol .br Parameter\fB[3]\fR: Encoded 2nd byte of number of the length of Ustr string .br Type\fB[3]\fR: symbol .br Parameter\fB[4]\fR: Encoded 1st byte of number of the length of Ustr string .br Type\fB[4]\fR: symbol .br Parameter\fB[5]\fR: Data for Ustr string .br Type\fB[5]\fR: const char[] .br \fBExplanation:\fR .br This function works in the same way as USTR1() but takes four length bytes, so the read\-only string can be upto 2**32 \- 1 bytes in length. .ti -2 .br \fBFunction: \fR USTR1_CHK() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Encoded number of the length of Ustr string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Data for Ustr string .br Type\fB[2]\fR: const char[] .br \fBExplanation:\fR .br This function works in the same way as USTR1() but it does a check against the length of (Parameter[2]) using sizeof() \- 1. .sp \fBNote:\fR .br If the check fails the returned Ustr * will be "", so you can check ustr_len() to see if you screwed something up. .ti -2 .br \fBFunction: \fR USTR2_CHK() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Encoded 2nd byte of number of the length of Ustr string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Encoded 1st byte of number of the length of Ustr string .br Type\fB[2]\fR: symbol .br Parameter\fB[3]\fR: Data for Ustr string .br Type\fB[3]\fR: const char[] .br \fBExplanation:\fR .br This function works in the same way as USTR2() but it does a check against the length of (Parameter[2]) using sizeof() \- 1. .sp \fBNote:\fR .br If the check fails the returned Ustr * will be "". .ti -2 .br \fBFunction: \fR USTR4_CHK() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Encoded 4th byte of number of the length of Ustr string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Encoded 3rd byte of number of the length of Ustr string .br Type\fB[2]\fR: symbol .br Parameter\fB[3]\fR: Encoded 2nd byte of number of the length of Ustr string .br Type\fB[3]\fR: symbol .br Parameter\fB[4]\fR: Encoded 1st byte of number of the length of Ustr string .br Type\fB[4]\fR: symbol .br Parameter\fB[5]\fR: Data for Ustr string .br Type\fB[5]\fR: const char[] .br \fBExplanation:\fR .br This function works in the same way as USTR4() but it does a check against the length of (Parameter[2]) using sizeof() \- 1. .sp \fBNote:\fR .br If the check fails the returned Ustr * will be "". .ti -2 .br \fBFunction: \fR USTRP1() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Encoded number of the length of Ustr string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Data for Ustr string .br Type\fB[2]\fR: const char[] .br \fBExplanation:\fR .br This function works like USTR1(), but returns a Ustrp instead. .ti -2 .br \fBFunction: \fR USTRP2() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Encoded 2nd byte of number of the length of Ustr string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Encoded 1st byte of number of the length of Ustr string .br Type\fB[2]\fR: symbol .br Parameter\fB[3]\fR: Data for Ustr string .br Type\fB[3]\fR: const char[] .br \fBExplanation:\fR .br This function works like USTR4(), but returns a Ustrp instead. .ti -2 .br \fBFunction: \fR USTRP4() .br Returns: Ustrp string .br Type: struct Ustrp * .br Parameter\fB[1]\fR: Encoded 4th byte of number of the length of Ustrp string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Encoded 3rd byte of number of the length of Ustrp string .br Type\fB[2]\fR: symbol .br Parameter\fB[3]\fR: Encoded 2nd byte of number of the length of Ustrp string .br Type\fB[3]\fR: symbol .br Parameter\fB[4]\fR: Encoded 1st byte of number of the length of Ustrp string .br Type\fB[4]\fR: symbol .br Parameter\fB[5]\fR: Data for Ustr string .br Type\fB[5]\fR: const char[] .br \fBExplanation:\fR .br This function works like USTR2(), but returns a Ustrp instead. .ti -2 .br \fBFunction: \fR USTRP1_CHK() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Encoded number of the length of Ustr string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Data for Ustr string .br Type\fB[2]\fR: const char[] .br \fBExplanation:\fR .br This function works like USTR1_CHK(), but returns a Ustrp instead. .ti -2 .br \fBFunction: \fR USTRP2_CHK() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Encoded 2nd byte of number of the length of Ustr string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Encoded 1st byte of number of the length of Ustr string .br Type\fB[2]\fR: symbol .br Parameter\fB[3]\fR: Data for Ustr string .br Type\fB[3]\fR: const char[] .br \fBExplanation:\fR .br This function works like USTR4_CHK(), but returns a Ustrp instead. .ti -2 .br \fBFunction: \fR USTRP4_CHK() .br Returns: Ustrp string .br Type: struct Ustrp * .br Parameter\fB[1]\fR: Encoded 4th byte of number of the length of Ustrp string .br Type\fB[1]\fR: symbol .br Parameter\fB[2]\fR: Encoded 3rd byte of number of the length of Ustrp string .br Type\fB[2]\fR: symbol .br Parameter\fB[3]\fR: Encoded 2nd byte of number of the length of Ustrp string .br Type\fB[3]\fR: symbol .br Parameter\fB[4]\fR: Encoded 1st byte of number of the length of Ustrp string .br Type\fB[4]\fR: symbol .br Parameter\fB[5]\fR: Data for Ustr string .br Type\fB[5]\fR: const char[] .br \fBExplanation:\fR .br This function works like USTR2_CHK(), but returns a Ustrp instead. .SH Creating fixed Ustr functions .ti -2 .br \fBFunction: \fR USTR_SIZE_FIXED() .br Returns: Size of area of memory .br Type: size_t .br Parameter\fB[1]\fR: Size of area of memory .br Type\fB[1]\fR: size_t .br \fBExplanation:\fR .br This macro function is replaced by a static conversion from the max length desired (Parameter[1]) to the storage size needed. In other words it works out what ustr_size_overhead() will be, and adds that value. .sp \fBNote:\fR .br This is useful is you want a small fixed size allocation, as you can declare it like so: .br char buf[USTR_SIZE_FIXED(4)]; .Ve ...to give you exactly 4 bytes as a maximum, this is esp. useful if you want a limited (ustr_limited() == USTR_TRUE) Ustr string. .ti -2 .br \fBFunction: \fR ustr_init_fixed() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to area of memory to use as a Ustr string .br Type\fB[1]\fR: void * .br Parameter\fB[2]\fR: Size of area of memory .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Whether the fixed size Ustr should be limited .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: The initial length of the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This creates a new Ustr string, which is "fixed". This means the Ustr storage is managed outside of the ustr_* API, it is often used for stack allocated strings. .br As you add data to the Ustr past the size allowed via. the fixed storge the Ustr will automatically be converted into an allocated Ustr. So if this is possible you should always call ustr_free(), as this does nothing if given a fixed size Ustr. .sp \fBNote:\fR .br For simplicity you probably want to use USTR_SC_INIT_AUTO() or USTR_SC_INIT_AUTO() when possible. .ti -2 .br \fBFunction: \fR USTR_SC_INIT_AUTO() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Area of memory to use as a Ustr string .br Type\fB[1]\fR: char[] .br Parameter\fB[2]\fR: Whether the fixed size Ustr should be limited .br Type\fB[2]\fR: int .br Parameter\fB[3]\fR: The initial length of the Ustr .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This calls ustr_init_fixed() with sizeof() the area of memory (Parameter[1]) as the second argument. .sp \fBNote:\fR .br This does mean that the first argument must be the correct size, as far as sizeof() is concerned, as in... .Vb 4 char buf_sz[1024]; Ustr *s1 = USTR_SC_INIT_AUTO(buf_sz, USTR_FALSE, 0); .Ve ...so passing pointers to memory from malloc() will probably just return NULL. .ti -2 .br \fBFunction: \fR USTR_SC_INIT_AUTO_OSTR() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Area of memory to use as a Ustr string .br Type\fB[1]\fR: char[] .br Parameter\fB[2]\fR: Whether the fixed size Ustr should be limited .br Type\fB[2]\fR: int .br Parameter\fB[3]\fR: The initial string in the buffer, as a constant string .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This calls ustr_init_fixed() with sizeof() the area of memory (Parameter[1]) as the second argument, given as an "object string". .sp \fBNote:\fR .br This does mean that the first argument must be the correct size, as far as sizeof() is concerned, as in... .Vb 4 char buf_sz[1024] = USTR_BEG_FIXED2 "abcd"; Ustr *s1 = USTR_SC_INIT_AUTO_OSTR(buf_sz, USTR_FALSE, "abcd"); .Ve ...so passing pointers to memory from malloc() will probably just return NULL. .SH Debugging functions .ti -2 .br \fBFunction: \fR ustr_assert_valid() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a Ustr string .br Type\fB[1]\fR: Ustr * .br \fBExplanation:\fR .br This function asserts a few internal consistency checks, and can help point out when a Ustr is invalid. .sp \fBNote:\fR .br This calls ustr_assert_ret() so that when USTR_DEBUG if off the checks are still performed and the result is returned. .ti -2 .br \fBFunction: \fR ustr_assert_valid_subustr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a Ustr string .br Type\fB[1]\fR: Ustr * .br Parameter\fB[2]\fR: Position in the Ustr .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length to delete from the Ustr .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function calls ustr_assert_valid() and also checks that the position and length are within the Ustr. If they aren't valid it returns 0, if they are valid it returns ustr_len(). .ti -2 .br \fBFunction: \fR USTR_CNTL_MALLOC_CHECK_BEG() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Condition for begin malloc checking or not .br Type\fB[1]\fR: int .br \fBExplanation:\fR .br This function begins malloc checking, meaning all ustr allocations will go through the malloc check routines, but it fails if the condition check (Parameter[1]) fails. .sp \fBNote:\fR .br Turning malloc checking on after one or more allocations has happened will lead to false failures unless you really known what you are doing. .br You can automatically turn malloc checking on by giving the USTR_CNTL_MC environment variable the value of "1", "yes" or "on". .ti -2 .br \fBFunction: \fR USTR_CNTL_MALLOC_CHECK_LVL() .br Returns: Level of current malloc check .br Type: int .br Parameter\fB[1]\fR: Nothing .br Type\fB[1]\fR: void .br \fBExplanation:\fR .br This function returns the current "level" of the malloc check, with 0 indicating that malloc check isn't enabled. .br The level goes up by one whenever USTR_CNTL_MALLOC_CHECK_BEG() or USTR_CNTL_MALLOC_CHECK_ADD() returns success, and goes down by one whenever USTR_CNTL_MALLOC_CHECK_DEL() or USTR_CNTL_MALLOC_CHECK_END() returns success. .ti -2 .br \fBFunction: \fR USTR_CNTL_MALLOC_CHECK_MEM() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer returned from malloc check .br Type\fB[1]\fR: void * .br \fBExplanation:\fR .br This function asserts that the pointer (Parameter[1]) was allocated from malloc checking. .sp \fBNote:\fR .br Unless you are doing something special, or using a builtin Ustr_pool it is very likely you want to just call USTR_CNTL_MALLOC_CHECK_MEM_USTR(). .ti -2 .br \fBFunction: \fR USTR_CNTL_MALLOC_CHECK_MEM_SZ() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer returned from malloc check .br Type\fB[1]\fR: void * .br Parameter\fB[2]\fR: Length of allocated memory .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br This function asserts that the pointer (Parameter[1]) was allocated from malloc checking, and has the specified size (Parameter[2]). .sp \fBNote:\fR .br Unless you are doing something special, or using a builtin Ustr_pool it is very likely you want to just call USTR_CNTL_MALLOC_CHECK_MEM_USTR(). .ti -2 .br \fBFunction: \fR USTR_CNTL_MALLOC_CHECK_MEM_MINSZ() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer returned from malloc check .br Type\fB[1]\fR: void * .br Parameter\fB[2]\fR: Length of allocated memory .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br This function asserts that the pointer (Parameter[1]) was allocated from malloc checking, and has at least the specified size (Parameter[2]). .sp \fBNote:\fR .br Unless you are doing something special, or using a builtin Ustr_pool it is very likely you want to just call USTR_CNTL_MALLOC_CHECK_MEM_USTR(). .ti -2 .br \fBFunction: \fR USTR_CNTL_MALLOC_CHECK_MEM_USTR() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a Ustr string .br Type\fB[1]\fR: Ustr * .br \fBExplanation:\fR .br This function asserts that the pointer (Parameter[1]) is a Ustr allocated from malloc checking, if the Ustr is allocated (if not it returns TRUE). .sp \fBNote:\fR .br Because of the layering between the Ustr code and the pool code, if you allocate an implicity sized Ustrp from a pool and then delete some data from it (which fails) the Ustr layer will think it has an implicit less than the actual size so this function will fail. This is what USTR_CNTL_MALLOC_CHECK_MEM_USTRP() is for. .ti -2 .br \fBFunction: \fR USTR_CNTL_MALLOC_CHECK_MEM_USTRP() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a Ustrp string .br Type\fB[1]\fR: Ustrp * .br \fBExplanation:\fR .br This function asserts that the pointer (Parameter[1]) is a Ustr allocated from a builtin pool using malloc checking, if the Ustr is allocated (if not it returns TRUE). .ti -2 .br \fBFunction: \fR USTR_CNTL_MALLOC_CHECK_END() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Nothing .br Type\fB[1]\fR: void .br \fBExplanation:\fR .br This macro will cleanup any memory used by malloc check, and assert that no memory is left allocated. .sp \fBNote:\fR .br If any memory is left allocated, each one found is output to stderr with the file/line/function of the level it was allocated from. .ti -2 .br \fBFunction: \fR USTR_CNTL_MALLOC_CHECK_ADD() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Condition to begin malloc checking or not .br Type\fB[1]\fR: int .br \fBExplanation:\fR .br This function works like USTR_CNTL_MALLOC_CHECK_END() but it fails if the condition check (Parameter[1]) fails, or if USTR_CNTL_MALLOC_CHECK_LVL() is zero. .ti -2 .br \fBFunction: \fR USTR_CNTL_MALLOC_CHECK_DEL() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Condition to end malloc checking or not .br Type\fB[1]\fR: int .br \fBExplanation:\fR .br This function works like USTR_CNTL_MALLOC_CHECK_END() but it fails if the condition check (Parameter[1]) fails, or if USTR_CNTL_MALLOC_CHECK_LVL() is one. .sp \fBNote:\fR .br The condition (Parameter[1]) to this macro should almost certainly be the return value from USTR_CNTL_MALLOC_CHECK_ADD(). .SH Creating allocated Ustr functions .ti -2 .br \fBFunction: \fR ustr_init_size() .br Returns: Size that needs to be allocated .br Type: size_t .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: Length of data in the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function finds out the exact size of memory needed to store the specified Ustr of the given configuration. .ti -2 .br \fBFunction: \fR ustr_init_alloc() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to area of memory to use as a Ustr string .br Type\fB[1]\fR: void * .br Parameter\fB[2]\fR: Size of area of memory .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Whether Ustr should store the size .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Number of bytes to use for references .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: Whether the Ustr should use exact allocations .br Type\fB[5]\fR: int .br Parameter\fB[6]\fR: Whether the Ustr should have the "enomem" flag set .br Type\fB[6]\fR: int .br Parameter\fB[7]\fR: The initial length of the Ustr .br Type\fB[7]\fR: size_t .br \fBExplanation:\fR .br This creates a new Ustr string, you should have allocated the data via. USTR_CONF_MALLOC() or bad things will happen if the Ustr string is ever free'd or reallocated. .ti -2 .br \fBFunction: \fR ustr_dupx_empty() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocation flag .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br \fBExplanation:\fR .br This function creates an empty Ustr, owned by you, that is allocated from system memory, or it returns NULL. .br The size is the desired allocation size for the entire Ustr, including overhead for metadata. This value will be rounded up, if it's too small, so passing 1 as the size means you want a stored size but to allocate the smallest amount of memory possible. .br The exact memory allocation flag says if the Ustr should round allocations up to the nearest half power of two or should be no more than needed. .br The ENOMEM memory error flag sets the iniital state of the user visible flag for memory allocation errors. Eg. ustr_enomem(), ustr_setf_enomem_clr() and ustr_setf_enomem_err() .sp \fBNote:\fR .br The reference byte count can only be one of the following values: 0, 1, 2 or 4, or 8 (on environments with a 64bit size_t). .br It can be useful to ensure that the Ustr is in system memory, so that you can add things to it and check for errors with ustr_enomem(). .br If you chose to store the allocated size in the Ustr then the number of bytes allocated for the reference count will be a minimum of 2. .ti -2 .br \fBFunction: \fR ustr_dup_empty() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Nothing .br Type\fB[1]\fR: void .br \fBExplanation:\fR .br This function is the same as calling ustr_dupx_empty() with the current set of default options. .ti -2 .br \fBFunction: \fR ustr_dupx_undef() .br Returns: Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: Length of new undefined data .br Type\fB[5]\fR: size_t .br \fBExplanation:\fR .br This function works like you called ustr_dupx_empty() and then ustr_add_undef(). .ti -2 .br \fBFunction: \fR ustr_dup_undef() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Length of new undefined data .br Type\fB[1]\fR: size_t .br \fBExplanation:\fR .br This function is the same as calling ustr_dupx_undef() with the current set of default options. .ti -2 .br \fBFunction: \fR ustr_dup() .br Returns: A pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function tries to increase the reference count on the passed Ustr string, and if that succeeds returns that as an argument. If that fails it tries creates a new Ustr string that looks identical to the old Ustr string, apart from the reference count. .sp \fBNote:\fR .br Because the new Ustr string is configured identically to the old Ustr string this means the result can be very different to what you get if you call ustr_dup_buf() with ustr_cstr() and ustr_len() from the original string where the configuration would be whatever the default is. .br Esp. worth of note is that if you ustr_dup() a Ustr string with an explicit size of 900 but a length of 1, and the reference count is full the returned Ustr string will have a size of 900 bytes and so will have allocated a little over that. ustr_dup_buf(), even with a sized configuration would only allocate about 12 bytes and have a size a little less than that. .ti -2 .br \fBFunction: \fR ustr_dupx() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: Pointer to a constant Ustr string .br Type\fB[5]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function tries to add a reference if the value of the size, reference bytes, exact memory allocations and ENOMEM are the same as those in the passed Ustr string (Parameter[5]). If the comparison fails or the addition of a reference fails it works like ustr_dupx_buf() using ustr_cstr() and ustr_len(). .ti -2 .br \fBFunction: \fR ustr_sc_dup() .br Returns: A pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function works like calling ustr_dup(), but if the reference count is maxed out then and so a new Ustr string has been allocated then that is stored in the passed argument (Parameter[1]) and the "old" Ustr string is returned. .sp \fBNote:\fR .br The reason to use this is that if you have a "main" Ustr string pointer that a lot of things are getting references too then when the reference count maxes out you'll degrade into worst case behaviour which acts as though there are no reference counts. This function stops that problem. .br As an example, if you have a 1 byte reference count and have 255 * 2 references then using ustr_dup() will create 256 Ustr strings using this function will create 4 Ustr strings. .ti -2 .br \fBFunction: \fR ustr_sc_dupx() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: A pointer to a pointer to a Ustr string .br Type\fB[5]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function works like calling ustr_dupx(), but if the reference count is maxed out then and so a new Ustr string is allocated then that is stored in the passed argument (Parameter[1]) and the "old" Ustr string is returned. .br If the configurations of the new Ustr string and the old Ustr string are not the same, this function works identically to ustr_dupx(). .sp \fBNote:\fR .br The reason to use this is that if you have a "main" Ustr string pointer that a lot of things are getting references too then when the reference count maxes out you'll degrade into worst case behaviour which acts as though there are no reference counts. This function stops that problem. .br As an example, if you have a 1 byte reference count and have 255 * 2 references then using ustr_dupx() will create 256 Ustr strings using this function will create 4 Ustr strings. .ti -2 .br \fBFunction: \fR ustr_dup_buf() .br Returns: A pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to data .br Type\fB[1]\fR: const void * .br Parameter\fB[2]\fR: Length of data .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_dup_undef() and then copied the data into the new undefined space. .ti -2 .br \fBFunction: \fR ustr_dupx_buf() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: Pointer to data .br Type\fB[5]\fR: const void * .br Parameter\fB[6]\fR: Length of data .br Type\fB[6]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_dupx_undef() and then copied the data into the new undefined space. .ti -2 .br \fBFunction: \fR ustr_dup_cstr() .br Returns: A pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to constant C\-style string .br Type\fB[1]\fR: const char * .br \fBExplanation:\fR .br This function works as if you had called ustr_dup_buf() and passed strlen() as the length. .ti -2 .br \fBFunction: \fR ustr_dupx_cstr() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: Pointer to constant C\-style string .br Type\fB[5]\fR: const char * .br \fBExplanation:\fR .br This function works as if you had called ustr_dupx_buf() and passed strlen() as the length. .ti -2 .br \fBFunction: \fR USTR_DUP_OSTR() .br Returns: A pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: A constant C\-style string .br Type\fB[1]\fR: const char [] .br \fBExplanation:\fR .br This function works as if you had called ustr_dup_buf() and passed sizeof() \- 1 as the length. .ti -2 .br \fBFunction: \fR USTR_DUP_OBJ() .br Returns: A pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: A symbol .br Type\fB[1]\fR: ... .br \fBExplanation:\fR .br This function works as if you had called ustr_dup_buf() and passed sizeof() as the length. .sp \fBNote:\fR .br In most cases you'll want to use USTR_DUP_OSTR(). .ti -2 .br \fBFunction: \fR ustr_dup_subustr() .br Returns: A pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Position in the Ustr .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length to add from the Ustr .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function mostly works as if you had called ustr_dup_buf() with the ustr_cstr() + position \- 1 and length values of the Ustr string to be added. .sp \fBNote:\fR .br If the position is 1 and the length is the length of the Ustr string then it just calls ustr_dup(). .ti -2 .br \fBFunction: \fR ustr_dupx_subustr() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: A pointer to a constant Ustr string .br Type\fB[5]\fR: const struct Ustr * .br Parameter\fB[6]\fR: Position in the Ustr .br Type\fB[6]\fR: size_t .br Parameter\fB[7]\fR: Length to add from the Ustr .br Type\fB[7]\fR: size_t .br \fBExplanation:\fR .br This function mostly works as if you had called ustr_dupx_buf() with the ustr_cstr() + position \- 1 and length values of the Ustr string to be added. .sp \fBNote:\fR .br If the position is 1 and the length is the length of the Ustr string then it just calls ustr_dupx(). .ti -2 .br \fBFunction: \fR ustr_dup_rep_chr() .br Returns: A pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Byte value of data .br Type\fB[1]\fR: char .br Parameter\fB[2]\fR: Length of bytes as data .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_dup_undef() and then copied the byte value to each position. .ti -2 .br \fBFunction: \fR ustr_dupx_rep_chr() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: Byte value of data .br Type\fB[5]\fR: char .br Parameter\fB[6]\fR: Length of bytes as data .br Type\fB[6]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_dupx_undef() and then copied the byte value to each position. .ti -2 .br \fBFunction: \fR ustr_sc_vjoin() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Separator to go between Ustr strings .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to the first constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: A pointer to the second constant Ustr string .br Type\fB[3]\fR: const struct Ustr * .br Parameter\fB[4]\fR: Variable argument list variable, from va_start() .br Type\fB[4]\fR: va_list .br \fBExplanation:\fR .br This function works as if you called ustr_dup() on the first Ustr string (Parameter[2]), and then ustr_add() on the separator (Parameter[1]) followed by ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached. .sp \fBNote:\fR .br This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually. .ti -2 .br \fBFunction: \fR ustr_sc_join() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Separator to go between Ustr strings .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to the first constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: A pointer to the second constant Ustr string .br Type\fB[3]\fR: const struct Ustr * .br Parameter\fB[4]\fR: Zero or more pointers to constant Ustr strings and then USTR_NULL .br Type\fB[4]\fR: ... .br \fBExplanation:\fR .br This function calls va_start() to get a variable argument list and then calls ustr_sc_vjoin(). .sp \fBNote:\fR .br This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually. .ti -2 .br \fBFunction: \fR ustr_sc_vjoinx() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: Separator to go between Ustr strings .br Type\fB[5]\fR: const struct Ustr * .br Parameter\fB[6]\fR: A pointer to the first constant Ustr string .br Type\fB[6]\fR: const struct Ustr * .br Parameter\fB[7]\fR: A pointer to the second constant Ustr string .br Type\fB[7]\fR: const struct Ustr * .br Parameter\fB[8]\fR: Variable argument list variable, from va_start() .br Type\fB[8]\fR: va_list .br \fBExplanation:\fR .br This function works as if you called ustr_dupx() on the first Ustr string (Parameter[2]), and then ustr_add() on the separator (Parameter[1]) followed by ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached. .sp \fBNote:\fR .br This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually. .ti -2 .br \fBFunction: \fR ustr_sc_joinx() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: Separator to go between Ustr strings .br Type\fB[5]\fR: const struct Ustr * .br Parameter\fB[6]\fR: A pointer to the first constant Ustr string .br Type\fB[6]\fR: const struct Ustr * .br Parameter\fB[7]\fR: A pointer to the second constant Ustr string .br Type\fB[7]\fR: const struct Ustr * .br Parameter\fB[8]\fR: Zero or more pointers to constant Ustr strings and then USTR_NULL .br Type\fB[8]\fR: ... .br \fBExplanation:\fR .br This function calls va_start() to get a variable argument list and then calls ustr_sc_vjoinx(). .ti -2 .br \fBFunction: \fR ustr_sc_vconcat() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: A pointer to the first constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Variable argument list variable, from va_start() .br Type\fB[2]\fR: va_list .br \fBExplanation:\fR .br This function works as if you called ustr_dup() on the first Ustr string (Parameter[1]), and then ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached. .sp \fBNote:\fR .br This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually. .ti -2 .br \fBFunction: \fR ustr_sc_concat() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: A pointer to the first constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Zero or more pointers to constant Ustr strings and then USTR_NULL .br Type\fB[2]\fR: ... .br \fBExplanation:\fR .br This function calls va_start() to get a variable argument list and then calls ustr_sc_vconcat(). .ti -2 .br \fBFunction: \fR ustr_sc_vconcatx() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: A pointer to the first constant Ustr string .br Type\fB[5]\fR: const struct Ustr * .br Parameter\fB[6]\fR: Variable argument list variable, from va_start() .br Type\fB[6]\fR: va_list .br \fBExplanation:\fR .br This function works as if you called ustr_dupx() on the first Ustr string (Parameter[1]), and then ustr_add() on the second Ustr string (Parameter[3]). This process then repeats for all the Ustr strings in the variable argument list (Parameter[4]) until a USTR_NULL is reached. .sp \fBNote:\fR .br This function doesn't guarantee to just take a reference to one of the passed Ustr strings, even if that is what would happen if you called the above manually. .ti -2 .br \fBFunction: \fR ustr_sc_concatx() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: A pointer to the first constant Ustr string .br Type\fB[5]\fR: const struct Ustr * .br Parameter\fB[6]\fR: Zero or more pointers to constant Ustr strings and then USTR_NULL .br Type\fB[6]\fR: ... .br \fBExplanation:\fR .br This function calls va_start() to get a variable argument list and then calls ustr_sc_vconcatx(). .SH Deleting a Ustr, or data within a Ustr .ti -2 .br \fBFunction: \fR ustr_free() .br Returns: Nothing .br Type: void .br Parameter\fB[1]\fR: Pointer to a Ustr .br Type\fB[1]\fR: struct Ustr * .br \fBExplanation:\fR .br This function decrements the reference count on a Ustr, if there is one, and free's it if it is allocated and the reference count becomes zero. .sp \fBNote:\fR .br This function does nothing if passed USTR_NULL. .ti -2 .br \fBFunction: \fR ustrp_free() .br Returns: Nothing .br Type: void .br Parameter\fB[1]\fR: Pointer to a Ustr pool object .br Type\fB[1]\fR: struct Ustr_pool * .br Parameter\fB[2]\fR: Pointer to a Ustrp (pool allocated Ustr) .br Type\fB[2]\fR: struct Ustrp * .br \fBExplanation:\fR .br This function works like ustr_free() but calls the pool_free member function of the Ustr_pool (Parameter[1]) instead of the ustr system free. .ti -2 .br \fBFunction: \fR ustr_sc_free() .br Returns: Nothing .br Type: void .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function calls ustr_free() and then sets the pointer (Parameter[1]) to USTR_NULL, which is a noop when passed to ustr_free(). This can be used to help prevent "double free" errors. .sp \fBNote:\fR .br While the point to the pointer must be non\-NULL, this function also accepts a NULL ustr and does nothing. So you can pass the same pointer to this function multiple times and only the first one will do anything. .ti -2 .br \fBFunction: \fR ustr_sc_free2() .br Returns: Nothing .br Type: void .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Pointer to a Ustr string .br Type\fB[2]\fR: struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_sc_free() but instead of setting the pointer (Parameter[1]) to USTR_NULL it sets it to the Ustr string (Parameter[2]). .sp \fBNote:\fR .br While the point to the pointer must be non\-NULL, this function also accepts a NULL ustr to be free'd and does nothing. So you can pass the same pointer to ustr_sc_free() and then this function safely. .br The passed value (Parameter[2]) shouldn't be USTR_NULL, and in debugging mode the function will assert() that it isn't. .ti -2 .br \fBFunction: \fR ustr_sc_free_shared() .br Returns: Nothing .br Type: void .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function is a simple way to "free" a Ustr string that has been shared (ustr_shared() returns USTR_TRUE), normally ustr_free() is ignored on a shared Ustr string. It just calls ustr_setf_owner() and then ustr_sc_free(). .ti -2 .br \fBFunction: \fR ustr_del() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Length to delete from the Ustr .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br This function deletes data from the end of Ustr, possibly re\-sizing the Ustr at the same time. .sp \fBNote:\fR .br The Ustr is never re\-sized when the size is stored explicitly, so the pointer never changes. .ti -2 .br \fBFunction: \fR ustr_del_subustr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position in the Ustr .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length to delete from the Ustr .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_del() but can delete an arbitrary section of the Ustr. .ti -2 .br \fBFunction: \fR ustr_sc_del() .br Returns: Nothing .br Type: void .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function is like calling ustr_del() with ustr_len() as the length, however if that fails it does a ustr_free() and then sets the pointer to USTR(""). .sp \fBNote:\fR .br While the benifit is that you don't have to check for memory failure errors, if there is a memory failure and you have a non\-default configuration the configuration will revert back to the default. .SH Adding data to a Ustr .ti -2 .br \fBFunction: \fR ustr_add_undef() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Length of new undefined data .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br The Ustr string is expanded (possibly reallocated) so that it can contain length (Parameter[2]) extra data, if the length is not zero the Ustr will be writable. Or it'll return USTR_FALSE (zero) on failure. .ti -2 .br \fBFunction: \fR ustr_add_buf() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Pointer to data .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of data .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_add_undef() and then copied the data into the new undefined space. .ti -2 .br \fBFunction: \fR ustr_add_cstr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Pointer to constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works as if you had called ustr_add_buf() and passed strlen() as the length. .ti -2 .br \fBFunction: \fR USTR_ADD_OSTR() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A constant C\-style string .br Type\fB[2]\fR: const char [] .br \fBExplanation:\fR .br This function works as if you had called ustr_add_buf() and passed sizeof() \- 1 as the length. .ti -2 .br \fBFunction: \fR USTR_ADD_OBJ() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A symbol .br Type\fB[2]\fR: ... .br \fBExplanation:\fR .br This function works as if you had called ustr_add_buf() and passed sizeof() as the length. .sp \fBNote:\fR .br In most cases you'll want to use USTR_ADD_OSTR(). .ti -2 .br \fBFunction: \fR ustr_add() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function mostly works as if you had called ustr_add_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added. .sp \fBNote:\fR .br If the Ustr string is zero length and isn't writable this function may just add a reference, this is fine for Ustr strings that are "constant" because if the Ustr is read\-only then the memory will not be written to. .ti -2 .br \fBFunction: \fR ustr_add_subustr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to add from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function mostly works as if you had called ustr_add_buf() with the ustr_cstr() + position \- 1 and length values of the Ustr string to be added. The exception being if you add a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr, but this function just works. .sp \fBNote:\fR .br If the position is 1 and the length is the length of the Ustr string then it just calls ustr_add(). .ti -2 .br \fBFunction: \fR ustr_add_rep_chr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Byte value of data .br Type\fB[2]\fR: char .br Parameter\fB[3]\fR: Length of bytes as data .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_add_undef() and then copied the byte value to each position. .SH Setting a Ustr to some data .ti -2 .br \fBFunction: \fR ustr_set_undef() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: size_t .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_del() for the entire string and the ustr_add_undef(). .ti -2 .br \fBFunction: \fR ustr_set_empty() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function works as if you had called ustr_del() for the entire string, however the string will be allocated if this completes. .ti -2 .br \fBFunction: \fR ustr_set_buf() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Buffer containting data .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of Buffer .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_del() for the entire string and the ustr_add_buf(). .ti -2 .br \fBFunction: \fR ustr_set_cstr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works as if you had called ustr_del() for the entire string and then ustr_add_cstr(). .ti -2 .br \fBFunction: \fR USTR_SET_OSTR() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A constant C\-style string .br Type\fB[2]\fR: const char [] .br \fBExplanation:\fR .br This function works as if you had called ustr_del() for the entire string and then USTR_ADD_OSTR(). .ti -2 .br \fBFunction: \fR USTR_SET_OBJ() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A symbol .br Type\fB[2]\fR: ... .br \fBExplanation:\fR .br This function works as if you had called ustr_del() for the entire string and then USTR_ADD_OBJ(). .sp \fBNote:\fR .br In most cases you'll want to use USTR_SET_OSTR(). .ti -2 .br \fBFunction: \fR ustr_set() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works as if you had called ustr_del() for the entire string and the ustr_add(). .ti -2 .br \fBFunction: \fR ustr_set_subustr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to set from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_del() for the entire string and the ustr_add_subustr(). The exception being if you set a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works. .ti -2 .br \fBFunction: \fR ustr_set_rep_chr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Byte value of data .br Type\fB[2]\fR: char .br Parameter\fB[3]\fR: Length of bytes as data .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_del() for the entire string and the ustr_add_rep_chr(). .SH Inserting data into a Ustr .ti -2 .br \fBFunction: \fR ustr_ins_undef() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of new undefined data .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br The Ustr string is expanded (possibly reallocated) so that it can contain length (Parameter[2]) extra data, from after the required position. If the length is not zero the Ustr will be writable. Or it'll return USTR_FALSE (zero) on failure. The data in the Ustr is moved as needed to put the new data at position (Parameter[2]) + 1. .ti -2 .br \fBFunction: \fR ustr_ins_buf() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Pointer to data .br Type\fB[3]\fR: const void * .br Parameter\fB[4]\fR: Length of data .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_ins_undef() and then copied the data into the new undefined space. .ti -2 .br \fBFunction: \fR ustr_ins_cstr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Pointer to constant C\-style string .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works as if you had called ustr_ins_buf() and passed strlen() as the length. .ti -2 .br \fBFunction: \fR USTR_INS_OSTR() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A constant C\-style string .br Type\fB[3]\fR: const char [] .br \fBExplanation:\fR .br This function works as if you had called ustr_ins_buf() and passed sizeof() \- 1 as the length. .ti -2 .br \fBFunction: \fR USTR_INS_OBJ() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A symbol .br Type\fB[3]\fR: ... .br \fBExplanation:\fR .br This function works as if you had called ustr_ins_buf() and passed sizeof() as the length. .sp \fBNote:\fR .br In most cases you'll want to use USTR_INS_OSTR(). .ti -2 .br \fBFunction: \fR ustr_ins() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works as if you had called ustr_ins_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added. .ti -2 .br \fBFunction: \fR ustr_ins_subustr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to ins from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function mostly as if you had called ustr_ins_buf() with the ustr_cstr() + position \- 1 and length values of the Ustr string to be insed. The exception being if you insert a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works. .ti -2 .br \fBFunction: \fR ustr_ins_rep_chr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[2]\fR: Byte value of data .br Type\fB[2]\fR: char .br Parameter\fB[3]\fR: Length of bytes as data .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_ins_undef() and then copied the byte value to each position. .SH Adding, duplicating and setting formatted data to a Ustr .ti -2 .br \fBFunction: \fR ustr_add_vfmt_lim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Limit of data to add .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Variable argument list variable, from va_start() .br Type\fB[4]\fR: va_list .br \fBExplanation:\fR .br This function works like calling the system vsnprintf() with the limit (Parameter[2]) as the limit to vsnprintf() and then calling ustr_add_buf(). .ti -2 .br \fBFunction: \fR ustr_add_vfmt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: Variable argument list variable, from va_start() .br Type\fB[3]\fR: va_list .br \fBExplanation:\fR .br This function works like calling the system vsnprintf() and then calling ustr_add_buf(). .ti -2 .br \fBFunction: \fR ustr_add_fmt_lim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Limit of data to add .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Options depending on value of Parameter[3] .br Type\fB[4]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() with the limit (Parameter[2]) as the limit to snprintf() and then calling ustr_add_buf(). .ti -2 .br \fBFunction: \fR ustr_add_fmt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: Options depending on value of Parameter[2] .br Type\fB[3]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() and then calling ustr_add_buf(). .ti -2 .br \fBFunction: \fR ustr_dup_vfmt_lim() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Limit of data to dup .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Pointer to a constant Ustr string .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: Variable argument list variable, from va_start() .br Type\fB[3]\fR: va_list .br \fBExplanation:\fR .br This function works like calling the system vsnprintf() with the limit (Parameter[2]) as the limit to vsnprintf() and then calling ustr_dup_buf(). .ti -2 .br \fBFunction: \fR ustr_dup_vfmt() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Limit of data to dup .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Pointer to a constant Ustr string .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: Variable argument list variable, from va_start() .br Type\fB[3]\fR: va_list .br \fBExplanation:\fR .br This function works like calling the system vsnprintf() and then calling ustr_dup_buf(). .ti -2 .br \fBFunction: \fR ustr_dup_fmt_lim() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Limit of data to dup .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Pointer to a constant Ustr string .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: Options depending on value of Parameter[2] .br Type\fB[3]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() with the limit (Parameter[2]) as the limit to snprintf() and then calling ustr_dup_buf(). .ti -2 .br \fBFunction: \fR ustr_dup_fmt() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to a constant Ustr string .br Type\fB[1]\fR: const char * .br Parameter\fB[2]\fR: Options depending on value of Parameter[1] .br Type\fB[2]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() and then calling ustr_dup_buf(). .ti -2 .br \fBFunction: \fR ustr_dupx_fmt_lim() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: Limit of data to dup .br Type\fB[5]\fR: size_t .br Parameter\fB[6]\fR: Pointer to a constant Ustr string .br Type\fB[6]\fR: const char * .br Parameter\fB[7]\fR: Options depending on value of Parameter[6] .br Type\fB[7]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() with the limit (Parameter[2]) as the limit to snprintf() and then calling ustr_dupx_buf(). .ti -2 .br \fBFunction: \fR ustr_dupx_fmt() .br Returns: Pointer to a Ustr string .br Type: struct Ustr * .br Parameter\fB[1]\fR: Size of allocated storage .br Type\fB[1]\fR: size_t .br Parameter\fB[2]\fR: Number of bytes to use for reference count .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Exact memory allocations .br Type\fB[3]\fR: int .br Parameter\fB[4]\fR: ENOMEM, memory error flag .br Type\fB[4]\fR: int .br Parameter\fB[5]\fR: Pointer to a constant Ustr string .br Type\fB[5]\fR: const char * .br Parameter\fB[6]\fR: Options depending on value of Parameter[5] .br Type\fB[6]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() and then calling ustr_dup_bufx(). .ti -2 .br \fBFunction: \fR ustr_set_vfmt_lim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Limit of data to set .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Variable argument list variable, from va_start() .br Type\fB[4]\fR: va_list .br \fBExplanation:\fR .br This function works like calling ustr_del() for all the data and then ustr_add_vfmt_lim(). .ti -2 .br \fBFunction: \fR ustr_set_vfmt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: Variable argument list variable, from va_start() .br Type\fB[3]\fR: va_list .br \fBExplanation:\fR .br This function works like calling ustr_del() for all the data and then ustr_add_vfmt(). .ti -2 .br \fBFunction: \fR ustr_set_fmt_lim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Limit of data to set .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Options depending on value of Parameter[3] .br Type\fB[4]\fR: ... .br \fBExplanation:\fR .br This function works like calling ustr_del() for all the data and then ustr_add_fmt_lim(). .ti -2 .br \fBFunction: \fR ustr_set_fmt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: Options depending on value of Parameter[2] .br Type\fB[3]\fR: ... .br \fBExplanation:\fR .br This function works like calling ustr_del() for all the data and then ustr_add_fmt(). .ti -2 .br \fBFunction: \fR ustr_ins_vfmt_lim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Limit of data to insert .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: A pointer to a constant C\-style string .br Type\fB[4]\fR: const char * .br Parameter\fB[5]\fR: Variable argument list variable, from va_start() .br Type\fB[5]\fR: va_list .br \fBExplanation:\fR .br This function works like calling the system vsnprintf() with the limit (Parameter[3]) as the limit to vsnprintf() and then calling ustr_ins_buf(). .ti -2 .br \fBFunction: \fR ustr_ins_vfmt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Variable argument list variable, from va_start() .br Type\fB[4]\fR: va_list .br \fBExplanation:\fR .br This function works like calling the system vsnprintf() and then calling ustr_ins_buf(). .ti -2 .br \fBFunction: \fR ustr_ins_fmt_lim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Limit of data to insert .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: A pointer to a constant C\-style string .br Type\fB[4]\fR: const char * .br Parameter\fB[5]\fR: Options depending on value of Parameter[4] .br Type\fB[5]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() with the limit (Parameter[3]) as the limit to snprintf() and then calling ustr_ins_buf(). .ti -2 .br \fBFunction: \fR ustr_ins_fmt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position after which the data should be added .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Options depending on value of Parameter[3] .br Type\fB[4]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() and then calling ustr_ins_buf(). .ti -2 .br \fBFunction: \fR ustr_sub_vfmt_lim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Limit of data to substitute .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: A pointer to a constant C\-style string .br Type\fB[4]\fR: const char * .br Parameter\fB[5]\fR: Variable argument list variable, from va_start() .br Type\fB[5]\fR: va_list .br \fBExplanation:\fR .br This function works like calling the system vsnprintf() with the limit (Parameter[3]) as the limit to vsnprintf() and then calling ustr_sub_buf(). .ti -2 .br \fBFunction: \fR ustr_sub_vfmt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Variable argument list variable, from va_start() .br Type\fB[4]\fR: va_list .br \fBExplanation:\fR .br This function works like calling the system vsnprintf() and then calling ustr_sub_buf(). .ti -2 .br \fBFunction: \fR ustr_sub_fmt_lim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Limit of data to substitute .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: A pointer to a constant C\-style string .br Type\fB[4]\fR: const char * .br Parameter\fB[5]\fR: Options depending on value of Parameter[4] .br Type\fB[5]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() with the limit (Parameter[3]) as the limit to snprintf() and then calling ustr_sub_buf(). .ti -2 .br \fBFunction: \fR ustr_sub_fmt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Options depending on value of Parameter[3] .br Type\fB[4]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() and then calling ustr_sub_buf(). .ti -2 .br \fBFunction: \fR ustr_sc_sub_vfmt_lim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Limit of data to substitute .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: A pointer to a constant C\-style string .br Type\fB[5]\fR: const char * .br Parameter\fB[6]\fR: Variable argument list variable, from va_start() .br Type\fB[6]\fR: va_list .br \fBExplanation:\fR .br This function works like calling the system vsnprintf() with the limit (Parameter[4]) as the limit to vsnprintf() and then calling ustr_sc_sub_buf(). .ti -2 .br \fBFunction: \fR ustr_sc_sub_vfmt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: A pointer to a constant C\-style string .br Type\fB[4]\fR: const char * .br Parameter\fB[5]\fR: Variable argument list variable, from va_start() .br Type\fB[5]\fR: va_list .br \fBExplanation:\fR .br This function works like calling the system vsnprintf() and then calling ustr_sc_sub_buf(). .ti -2 .br \fBFunction: \fR ustr_sc_sub_fmt_lim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Limit of data to substitute .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: A pointer to a constant C\-style string .br Type\fB[5]\fR: const char * .br Parameter\fB[6]\fR: Options depending on value of Parameter[5] .br Type\fB[6]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() with the limit (Parameter[3]) as the limit to snprintf() and then calling ustr_sc_sub_buf(). .ti -2 .br \fBFunction: \fR ustr_sc_sub_fmt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: A pointer to a constant C\-style string .br Type\fB[4]\fR: const char * .br Parameter\fB[5]\fR: Options depending on value of Parameter[5] .br Type\fB[5]\fR: ... .br \fBExplanation:\fR .br This function works like calling the system snprintf() and then calling ustr_sc_sub_buf(). .SH Accessing the "variables" of a Ustr .ti -2 .br \fBFunction: \fR ustr_len() .br Returns: The length of the Ustr .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function returns the length of the data within the Ustr, much like strlen() but without getting the value wrong in the case of extra NIL bytes. .ti -2 .br \fBFunction: \fR ustr_cstr() .br Returns: Read\-only pointer to the start of data in the Ustr .br Type: const char * .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function returns a read\-only pointer to the start of the data of the Ustr string. Due to there always being a terminating NIL byte in a Ustr, this is also a valid C\-style string. .ti -2 .br \fBFunction: \fR ustr_wstr() .br Returns: Writable pointer to the start of data in the Ustr, or NULL .br Type: char * .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: struct Ustr * .br \fBExplanation:\fR .br This function returns a writable pointer to the start of the data of the Ustr string. Due to there always being a terminating NIL byte in a Ustr, this is also a valid C\-style string. .br If the ustr is read\-only (ustr_ro() == USTR_TRUE) then this function will return NULL. .sp \fBNote:\fR .br Unless the string is owned (ustr_owner() == USTR_TRUE) it can be a very bad idea to use this to change data, as then all references will be updated. See ustr_sc_wstr(). .ti -2 .br \fBFunction: \fR ustr_alloc() .br Returns: A boolean flag of either USTR_TRUE or USTR_FALSE .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function says if the Ustr is currently in allocated storage. .ti -2 .br \fBFunction: \fR ustr_exact() .br Returns: A boolean flag of either USTR_TRUE or USTR_FALSE .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function says if the Ustr is doing exact allocations, so as the Ustr grows it will only have storage allocated exactly as required and not in half powers of two. .sp \fBNote:\fR .br This will always be USTR_FALSE for read\-only Ustr strings (ustr_ro() == USTR_TRUE), even though the default may be to used exact sized allocations when adding data to them etc. .ti -2 .br \fBFunction: \fR ustr_sized() .br Returns: A boolean flag of either USTR_TRUE or USTR_FALSE .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function says if the Ustr stores an explicit allocation size, if not the size is implied as the next highest half power of two. .ti -2 .br \fBFunction: \fR ustr_ro() .br Returns: A boolean flag of either USTR_TRUE or USTR_FALSE .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function says if the Ustr is current in read\-only storage. .br Read\-only storage is not writable but can be referenced via. ustr_dup() an infinite amount of times. .ti -2 .br \fBFunction: \fR ustr_fixed() .br Returns: A boolean flag of either USTR_TRUE or USTR_FALSE .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function says if the Ustr is current in fixed size storage. .br Fixed size storage is writable but cannot be referenced. .sp \fBNote:\fR .br Fixed size storage always explicitly stores the size of the storage. .ti -2 .br \fBFunction: \fR ustr_enomem() .br Returns: A boolean flag of either USTR_TRUE or USTR_FALSE .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function just returns the value of the user settable flag in the Ustr. It can be set via. ustr_setf_enomem_err() and cleared by ustr_setf_enomem_clr(). .br This function is automatically set to on whever a memory allocation failure happens for a Ustr. .sp \fBNote:\fR .br If a Ustr is referenced multiple times, ustr_setf_enomem_err() will fail. .br This always fails for Ustr's in read\-only storage. .ti -2 .br \fBFunction: \fR ustr_shared() .br Returns: A boolean flag of either USTR_TRUE or USTR_FALSE .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function says if the Ustr is in the "shared" mode. It can be set via. ustr_setf_shared() and cleared by ustr_setf_owner() on allocated Ustr's. .br Shared mode means that a Ustr can be referenced and unreferenced an infinite number of times. .sp \fBNote:\fR .br This always succeeds for Ustr's in read\-only storage. .br This always fails for Ustr's in fixed size storage. .ti -2 .br \fBFunction: \fR ustr_limited() .br Returns: A boolean flag of either USTR_TRUE or USTR_FALSE .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function says if the Ustr is currently in fixed size storage and cannot move to allocated storage. .sp \fBNote:\fR .br This always fails for Ustr's in allocated storage. .br This always fails for Ustr's in read\-only storage. .ti -2 .br \fBFunction: \fR ustr_owner() .br Returns: A boolean flag of either USTR_TRUE or USTR_FALSE .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function says if there is only a single reference to the Ustr string. .sp \fBNote:\fR .br This always fails for Ustr's in read\-only storage. .br This always succeeds for Ustr's in fixed size storage. .ti -2 .br \fBFunction: \fR ustr_size() .br Returns: size_t .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function calculates the maximum amount of data that could be stored (Ie. the max ustr_len()) without having to re\-size the Ustr string. .ti -2 .br \fBFunction: \fR ustr_size_alloc() .br Returns: size_t .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function returns the size of the storage for the Ustr. .ti -2 .br \fBFunction: \fR ustr_size_overhead() .br Returns: size_t .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function returns the difference between the size of the storage and the maximum amount of data that could be stored without having to re\-size the Ustr string. .ti -2 .br \fBFunction: \fR ustr_conf() .br Returns: Nothing .br Type: void .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Return size allocated number .br Type\fB[2]\fR: size_t * .br Parameter\fB[3]\fR: Return number of bytes used in the reference count .br Type\fB[3]\fR: size_t * .br Parameter\fB[4]\fR: Return exact allocations flag .br Type\fB[4]\fR: int * .br Parameter\fB[5]\fR: Return number of bytes used in the length .br Type\fB[5]\fR: size_t * .br Parameter\fB[5]\fR: Return number of references to this Ustr .br Type\fB[5]\fR: size_t * .br \fBExplanation:\fR .br This function gives the configuration of the current Ustr needed to duplicate it via. the ustr_dupx_*() functions. It also gives the number of bytes used for the length and the number of references, which are mainly informational. .sp \fBNote:\fR .br This function differs from calling the ustr_exact() etc. functions in that it returns the global options if this Ustr isn't allocated, thus telling you what the configuration would be if the Ustr was turned into an allocated Ustr by adding data etc. .br Zero references for an allocated Ustr with a non\-zero number of bytes for a reference count means it's in "shared" mode). .SH Setting the "flags" of a Ustr .ti -2 .br \fBFunction: \fR ustr_setf_enomem_err() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr * .br \fBExplanation:\fR .br This function sets the enomem flag, which can be observed via. the ustr_enomem() function. .br The implication of setting this flag is that a memory error has occured in a previous function call on this Ustr. .sp \fBNote:\fR .br This function fails if ustr_owner() fails for the Ustr. .ti -2 .br \fBFunction: \fR ustr_setf_enomem_clr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr * .br \fBExplanation:\fR .br This function clears the enomem flag, which can be observed via. the ustr_enomem() function. .br The implication of this flag being set is that a memory error has occured in a previous function call on this Ustr, so on clearing the flag you should know you have brought the Ustr back to a known state. .sp \fBNote:\fR .br This function fails if ustr_owner() fails for the Ustr. .ti -2 .br \fBFunction: \fR ustr_setf_share() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr * .br \fBExplanation:\fR .br This function sets the shared mode, which can be observed via. the ustr_shared() function. .br This is used on a Ustr so that it can have more references than it is able to hold in it's reference count. After this call the Ustr can be referenced and unreferenced an infinite number of times. .sp \fBNote:\fR .br After this call the Ustr will never be deleted until ustr_setf_owner() is called. .br This function fails if ustr_alloc() fails for the Ustr. .ti -2 .br \fBFunction: \fR ustr_setf_owner() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr * .br \fBExplanation:\fR .br This function removes the shared mode, which can be observed via. the ustr_shared() function. .br This is used so that a Ustr in shared mode can be free'd. .sp \fBNote:\fR .br This function fails if ustr_alloc() fails for the Ustr. .SH Comparing data in a Ustr .ti -2 .br \fBFunction: \fR ustr_cmp_buf() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to constant bytes, to compare .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of comparison bytes .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like memcmp() on the Ustr and the passed data. .ti -2 .br \fBFunction: \fR ustr_cmp() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_cmp_buf() but with the data from ustr_cstr() and the length from ustr_len(). .ti -2 .br \fBFunction: \fR ustr_cmp_subustr() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to compare from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_cmp() but with a limit on the data and length. .ti -2 .br \fBFunction: \fR ustr_cmp_cstr() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_cmp_buf() but with a length from strlen(). .ti -2 .br \fBFunction: \fR ustr_cmp_fast_buf() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to constant bytes, to compare .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of comparison bytes .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_cmp_buf() but the order of comparison is optimized for speed, but is much less friendly to humans. .ti -2 .br \fBFunction: \fR ustr_cmp_fast() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_cmp_fast_buf() but with the data from ustr_cstr() and the length from ustr_len(). .ti -2 .br \fBFunction: \fR ustr_cmp_fast_subustr() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to compare from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_cmp_fast() but with a limit on the data and length. .ti -2 .br \fBFunction: \fR ustr_cmp_fast_cstr() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_cmp_fast_buf() but with a length from strlen(). .ti -2 .br \fBFunction: \fR ustr_cmp_case_buf() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to constant bytes, to compare .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of comparison bytes .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_cmp_buf() but the order of comparison ignores ASCII case. .ti -2 .br \fBFunction: \fR ustr_cmp_case() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_cmp_case_buf() but with the data from ustr_cstr() and the length from ustr_len(). .ti -2 .br \fBFunction: \fR ustr_cmp_case_subustr() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to compare from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_cmp_case() but with a limit on the data and length. .ti -2 .br \fBFunction: \fR ustr_cmp_case_cstr() .br Returns: Less then zero, zero or greater than zero depending on comparison .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_cmp_case_buf() but with a length from strlen(). .ti -2 .br \fBFunction: \fR ustr_cmp_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like comparing ustr_cmp() against 0. .ti -2 .br \fBFunction: \fR ustr_cmp_buf_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to constant bytes, to compare .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of comparison bytes .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_buf() against 0. .ti -2 .br \fBFunction: \fR ustr_cmp_subustr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to compare from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_subustr() against 0. .ti -2 .br \fBFunction: \fR ustr_cmp_cstr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_cstr() against 0. .ti -2 .br \fBFunction: \fR ustr_cmp_case_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_case() against 0. .ti -2 .br \fBFunction: \fR ustr_cmp_case_buf_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to constant bytes, to compare .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of comparison bytes .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_case_buf() against 0. .ti -2 .br \fBFunction: \fR ustr_cmp_case_subustr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to compare from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_case_subustr() against 0. .ti -2 .br \fBFunction: \fR ustr_cmp_case_cstr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_case_cstr() against 0. .ti -2 .br \fBFunction: \fR ustr_cmp_prefix_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like comparing ustr_cmp() against 0, but the comparison is limited to the length of the right hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_prefix_buf_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to constant bytes, to compare .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of comparison bytes .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_buf() against 0, but the comparison is limited to the length of the right hand side (Parameter[3]). .ti -2 .br \fBFunction: \fR ustr_cmp_prefix_cstr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_cstr() against 0, but the comparison is limited to the length of the right hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_prefix_subustr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to compare from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_subustr() against 0, but the comparison is limited to the given length (Parameter[4]). .ti -2 .br \fBFunction: \fR ustr_cmp_case_prefix_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_case() against 0, but the comparison is limited to the length of the right hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_case_prefix_buf_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to constant bytes, to compare .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of comparison bytes .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_case_buf() against 0, but the comparison is limited to the length of the right hand side (Parameter[3]). .ti -2 .br \fBFunction: \fR ustr_cmp_case_prefix_cstr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_case_cstr() against 0, but the comparison is limited to the length of the right hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_case_prefix_subustr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to compare from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_case_subustr() against 0, but the comparison is limited to the given length (Parameter[4]). .ti -2 .br \fBFunction: \fR ustr_cmp_suffix_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_cmp_prefix_eq() but compares the end of the left hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_suffix_buf_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to constant bytes, to compare .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of comparison bytes .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_cmp_prefix_buf_eq() but compares the end of the left hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_suffix_cstr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_cmp_prefix_cstr_eq() but compares the end of the left hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_suffix_subustr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to compare from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_subustr() against 0, but compares the end of the left hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_case_suffix_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_cmp_case_prefix_eq() but compares the end of the left hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_case_suffix_buf_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to constant bytes, to compare .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of comparison bytes .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_cmp_case_prefix_buf_eq() but compares the end of the left hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_case_suffix_cstr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant C\-style string .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_cmp_case_prefix_cstr_eq() but compares the end of the left hand side. .ti -2 .br \fBFunction: \fR ustr_cmp_case_suffix_subustr_eq() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to compare from the Ustr .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like comparing ustr_cmp_case_subustr() against 0, but compares the end of the left hand side. .SH Searching for data in a Ustr .ti -2 .br \fBFunction: \fR ustr_srch_chr_fwd() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Byte data to search for .br Type\fB[3]\fR: char .br \fBExplanation:\fR .br This function searches for the data (Parameter[3]) in the Ustr, skipping an offset (Parameter[2]) number of bytes. .ti -2 .br \fBFunction: \fR ustr_srch_chr_rev() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Byte data to search for .br Type\fB[3]\fR: char .br \fBExplanation:\fR .br This function works like ustr_srch_chr_fwd() but it searches from the end of the string to the beginning. .sp \fBNote:\fR .br The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length. .ti -2 .br \fBFunction: \fR ustr_srch_buf_fwd() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to data to search for .br Type\fB[3]\fR: const void * .br Parameter\fB[4]\fR: Length of the data to search for .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function searches for the data (Parameter[3]) of length (Parameter[4]) in the Ustr, skipping an offset (Parameter[2]) number of bytes. .ti -2 .br \fBFunction: \fR ustr_srch_buf_rev() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to data to search for .br Type\fB[3]\fR: const void * .br Parameter\fB[4]\fR: Length of the data to search for .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_srch_buf_fwd() but it searches from the end of the string to the beginning. .sp \fBNote:\fR .br The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length. .ti -2 .br \fBFunction: \fR ustr_srch_fwd() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string, to search for .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_srch_buf_fwd() but it gets the data pointer by calling ustr_cstr() and the length by calling ustr_len() on the passed Ustr (Parameter[3]). .ti -2 .br \fBFunction: \fR ustr_srch_rev() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string, to search for .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_srch_fwd() but it searches from the end of the string to the beginning. .sp \fBNote:\fR .br The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length. .ti -2 .br \fBFunction: \fR ustr_srch_cstr_fwd() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to C\-style string data, to search for .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_srch_buf_fwd() but it gets the length by calling strlen() on the passed data (Parameter[3]). .ti -2 .br \fBFunction: \fR ustr_srch_cstr_rev() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to C\-style string data, to search for .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_srch_cstr_fwd() but it searches from the end of the string to the beginning. .sp \fBNote:\fR .br The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length. .ti -2 .br \fBFunction: \fR ustr_srch_subustr_fwd() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string .br Type\fB[3]\fR: const struct Ustr * .br Parameter\fB[4]\fR: Position in the Ustr .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: Length of data to search, from the Ustr .br Type\fB[5]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_srch_fwd() but it moves the data to start at the correct position and limits the length to the value specified. .ti -2 .br \fBFunction: \fR ustr_srch_subustr_rev() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string .br Type\fB[3]\fR: const struct Ustr * .br Parameter\fB[4]\fR: Position in the Ustr .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: Length of data to search, from the Ustr .br Type\fB[5]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_srch_rev() but it moves the data to start at the correct position and limits the length to the value specified. .sp \fBNote:\fR .br The searching starts from the end of the string, and so the offset is the offset from the end. However the position of a byte is always relative to the begining, so to do a loop you need to take the position from the length. .ti -2 .br \fBFunction: \fR ustr_srch_case_chr_fwd() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Byte data to search for .br Type\fB[3]\fR: char .br \fBExplanation:\fR .br This function works like ustr_srch_chr_fwd(), but treats ASCII uppercase and lowercase as equivalent. .ti -2 .br \fBFunction: \fR ustr_srch_case_chr_rev() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Byte data to search for .br Type\fB[3]\fR: char .br \fBExplanation:\fR .br This function works like ustr_srch_chr_fwd(), but treats ASCII uppercase and lowercase as equivalent. .ti -2 .br \fBFunction: \fR ustr_srch_case_buf_fwd() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to data to search for .br Type\fB[3]\fR: const void * .br Parameter\fB[4]\fR: Length of the data to search for .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_srch_buf_fwd(), but treats ASCII uppercase and lowercase as equivalent. .ti -2 .br \fBFunction: \fR ustr_srch_case_buf_rev() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to data to search for .br Type\fB[3]\fR: const void * .br Parameter\fB[4]\fR: Length of the data to search for .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_srch_buf_rev(), but treats ASCII uppercase and lowercase as equivalent. .ti -2 .br \fBFunction: \fR ustr_srch_case_fwd() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string, to search for .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_srch_fwd(), but treats ASCII uppercase and lowercase as equivalent. .ti -2 .br \fBFunction: \fR ustr_srch_case_rev() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string, to search for .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_srch_rev(), but treats ASCII uppercase and lowercase as equivalent. .ti -2 .br \fBFunction: \fR ustr_srch_case_cstr_fwd() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to C\-style string data, to search for .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_srch_cstr_fwd(), but treats ASCII uppercase and lowercase as equivalent. .ti -2 .br \fBFunction: \fR ustr_srch_case_cstr_rev() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to C\-style string data, to search for .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_srch_cstr_rev(), but treats ASCII uppercase and lowercase as equivalent. .ti -2 .br \fBFunction: \fR ustr_srch_case_subustr_fwd() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string .br Type\fB[3]\fR: const struct Ustr * .br Parameter\fB[4]\fR: Position in the Ustr .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: Length of data to search, from the Ustr .br Type\fB[5]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_srch_subustr_fwd(), but treats ASCII uppercase and lowercase as equivalent. .ti -2 .br \fBFunction: \fR ustr_srch_case_subustr_rev() .br Returns: Position in the Ustr, or zero if not found .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start searching at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string .br Type\fB[3]\fR: const struct Ustr * .br Parameter\fB[4]\fR: Position in the Ustr .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: Length of data to search, from the Ustr .br Type\fB[5]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_srch_subustr_rev(), but treats ASCII uppercase and lowercase as equivalent. .SH Span lengths of data in a Ustr .ti -2 .br \fBFunction: \fR ustr_spn_chr_fwd() .br Returns: Number of bytes in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Byte data .br Type\fB[3]\fR: char .br \fBExplanation:\fR .br This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes. .ti -2 .br \fBFunction: \fR ustr_spn_chr_rev() .br Returns: Number of bytes in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Byte data .br Type\fB[3]\fR: char .br \fBExplanation:\fR .br This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes. .ti -2 .br \fBFunction: \fR ustr_spn_chrs_fwd() .br Returns: Number of bytes in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Array of byte data, for spanning .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Length of byte data, for spanning .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes. .ti -2 .br \fBFunction: \fR ustr_spn_chrs_rev() .br Returns: Number of bytes in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Array of byte data .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Length of byte data .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes. .ti -2 .br \fBFunction: \fR ustr_spn_fwd() .br Returns: Number of bytes in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string, containing spanning bytes .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_spn_buf_fwd() but passing ustr_cstr() and ustr_len() .ti -2 .br \fBFunction: \fR ustr_spn_rev() .br Returns: Number of bytes in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string, containing spanning bytes .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_spn_buf_rev() but passing ustr_cstr() and ustr_len() .ti -2 .br \fBFunction: \fR ustr_spn_cstr_fwd() .br Returns: Number of bytes in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string, containing spanning bytes .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_spn_buf_fwd() but passing strlen() for the length. .ti -2 .br \fBFunction: \fR ustr_spn_cstr_rev() .br Returns: Number of bytes in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string, containing spanning bytes .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_spn_buf_rev() but passing strlen() for the length. .ti -2 .br \fBFunction: \fR ustr_cspn_chr_fwd() .br Returns: Number of bytes not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Byte data .br Type\fB[3]\fR: char .br \fBExplanation:\fR .br This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are not equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes. .ti -2 .br \fBFunction: \fR ustr_cspn_chr_rev() .br Returns: Number of bytes not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Byte data .br Type\fB[3]\fR: char .br \fBExplanation:\fR .br This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are not equal to the data (Parameter[3]), skipping offset (Parameter[2]) bytes. .ti -2 .br \fBFunction: \fR ustr_cspn_chrs_fwd() .br Returns: Number of bytes not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Array of byte data .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Length of byte data .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function returns the length of the start of the Ustr (Parameter[1]) that only contains bytes that are not equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes. .ti -2 .br \fBFunction: \fR ustr_cspn_chrs_rev() .br Returns: Number of bytes not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Array of byte data .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Length of byte data .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function returns the length of the end of the Ustr (Parameter[1]) that only contains bytes that are not equal to any byte in the data (Parameter[3]), skipping offset (Parameter[2]) bytes. .ti -2 .br \fBFunction: \fR ustr_cspn_fwd() .br Returns: Number of bytes not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string, containing spanning bytes .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_cspn_buf_fwd() but passing ustr_cstr() and ustr_len() .ti -2 .br \fBFunction: \fR ustr_cspn_rev() .br Returns: Number of bytes not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string, containing spanning bytes .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_cspn_buf_rev() but passing ustr_cstr() and ustr_len() .ti -2 .br \fBFunction: \fR ustr_cspn_cstr_fwd() .br Returns: Number of bytes not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string, containing spanning bytes .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_cspn_buf_fwd() but passing strlen() for the length. .ti -2 .br \fBFunction: \fR ustr_cspn_cstr_rev() .br Returns: Number of bytes not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string, containing spanning bytes .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_cspn_buf_rev() but passing strlen() for the length. .ti -2 .br \fBFunction: \fR ustr_utf8_spn_chrs_fwd() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style UTF\-8 string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Length of the C\-style UTF\-8 string .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_spn_chrs_fwd() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_spn_chrs_fwd() but given "xy" as a multi\-byte UTF\-8 character it understands that the span over "xyxz" is 1 UTF\-8 character and not 3 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_spn_chrs_rev() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style UTF\-8 string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_spn_chrs_rev() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_spn_chrs_rev() but given "xy" as a multi\-byte UTF\-8 character it understands that the span over "xyxz" is 1 UTF\-8 character and not 3 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_spn_fwd() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_spn_fwd() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_spn_fwd() but given "xy" as a multi\-byte UTF\-8 character it understands that the span over "xyxz" is 1 UTF\-8 character and not 3 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_spn_rev() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_spn_rev() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_spn_rev() but given "xy" as a multi\-byte UTF\-8 character it understands that the span over "xyxz" is 1 UTF\-8 character and not 3 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_spn_cstr_fwd() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style UTF\-8 string .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_spn_cstr_fwd() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_spn_cstr_fwd() but given "xy" as a multi\-byte UTF\-8 character it understands that the span over "xyxz" is 1 UTF\-8 character and not 3 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_spn_cstr_rev() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style UTF\-8 string .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_spn_cstr_rev() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_spn_cstr_rev() but given "xy" as a multi\-byte UTF\-8 character it understands that the span over "xyxz" is 1 UTF\-8 character and not 3 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_cspn_chrs_fwd() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style UTF\-8 string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Length of the C\-style UTF\-8 string .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_cspn_chrs_fwd() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_cspn_chrs_fwd() but given "xy" as a multi\-byte UTF\-8 character it understands that the compliment span over "xzxy" is 1 UTF\-8 character and not 0 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_cspn_chrs_rev() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style UTF\-8 string .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Length of the C\-style UTF\-8 string .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_cspn_chrs_rev() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_cspn_chrs_rev() but given "xy" as a multi\-byte UTF\-8 character it understands that the compliment span over "xzxy" is 1 UTF\-8 character and not 0 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_cspn_fwd() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr UTF\-8 string, containing spanning data .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_cspn_fwd() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_cspn_fwd() but given "xy" as a multi\-byte UTF\-8 character it understands that the compliment span over "xzxy" is 1 UTF\-8 character and not 0 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_cspn_rev() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to constant Ustr UTF\-8 string data, containing spanning data .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works like ustr_cspn_rev() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_cspn_rev() but given "xy" as a multi\-byte UTF\-8 character it understands that the compliment span over "xzxy" is 1 UTF\-8 character and not 0 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_cspn_cstr_fwd() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to constant C\-style UTF\-8 string data, containing spanning data .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_cspn_cstr_fwd() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_cspn_cstr_fwd() but given "xy" as a multi\-byte UTF\-8 character it understands that the compliment span over "xzxy" is 1 UTF\-8 character and not 0 bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_cspn_cstr_rev() .br Returns: Number of UTF\-8 characters not in the span .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr UTF\-8 string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string, in UTF\-8 characters, to start compliment spanning from .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to C\-style UTF\-8 string data, containing spanning data .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_cspn_cstr_rev() but the return value, offset, and length all use UTF\-8 characters and not bytes. .sp \fBNote:\fR .br This is much slower than ustr_spn_cstr_rev() but given "xy" as a multi\-byte UTF\-8 character it understands that the compliment span over "xzxy" is 1 UTF\-8 character and not 0 bytes. .SH Doing IO from or to a Ustr .ti -2 .br \fBFunction: \fR ustr_io_get() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a C file object .br Type\fB[2]\fR: FILE * .br Parameter\fB[3]\fR: Number of bytes to read .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Returned number of bytes read .br Type\fB[4]\fR: size_t * .br \fBExplanation:\fR .br This function tries to read a minimum number of bytes from the file object, into the Ustr string. The exact number read is returned, unless (Parameter[4]) is NULL. .ti -2 .br \fBFunction: \fR ustr_io_getfile() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a C file object .br Type\fB[2]\fR: FILE * .br \fBExplanation:\fR .br This function calls ustr_io_get() rpeatedly until EOF is encountered. .sp \fBNote:\fR .br The errno value when this function ends could either be from fopen(), fread(), or if both of the those succeeded from fclose(). .ti -2 .br \fBFunction: \fR ustr_io_getfilename() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A C\-style string of a filename .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function opens a specified file, and then calls ustr_io_getfile(). Finally closing the FILE * object. .ti -2 .br \fBFunction: \fR ustr_io_getdelim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a C file object .br Type\fB[2]\fR: FILE * .br Parameter\fB[3]\fR: A delimiter byte to stop reading at .br Type\fB[3]\fR: char .br \fBExplanation:\fR .br This function reads bytes from the file until it hits the delimiter byte. .sp \fBNote:\fR .br The delimiter is included, use ustr_del() to remove 1 byte from the end if you don't want it. .br This function assumes a delimiter will happen every 80 bytes or so. .ti -2 .br \fBFunction: \fR ustr_io_getline() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a C file object .br Type\fB[2]\fR: FILE * .br \fBExplanation:\fR .br This function works like calling ustr_io_getdelim() with '\\n' as the delimiter. .ti -2 .br \fBFunction: \fR ustr_io_put() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a C file object .br Type\fB[2]\fR: FILE * .br Parameter\fB[3]\fR: Number of bytes to write .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function is the opposite of ustr_io_get(), taking bytes from the beginning of the Ustr and writting them to the file. .sp \fBNote:\fR .br Deleting bytes from the begining of a Ustr string is the most inefficient thing to do, so it is recommended to use ustr_io_putfile(). .ti -2 .br \fBFunction: \fR ustr_io_putline() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a C file object .br Type\fB[2]\fR: FILE * .br Parameter\fB[3]\fR: Number of bytes to write .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function works like calling ustr_io_put(), and then writting a '\\n' to the file. .sp \fBNote:\fR .br This doesn't write a line from the Ustr to the file, if you want that call ustr_io_put() directly, using the return from ustr_srch_chr_fwd() (with a '\\n') as the number of bytes argument. .ti -2 .br \fBFunction: \fR ustr_io_putfile() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a C file object .br Type\fB[2]\fR: FILE * .br \fBExplanation:\fR .br This function works like calling ustr_io_put() with ustr_len() as the number of bytes. .ti -2 .br \fBFunction: \fR ustr_io_putfileline() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a C file object .br Type\fB[2]\fR: FILE * .br \fBExplanation:\fR .br This function works like calling ustr_io_putline() with ustr_len() as the number of bytes. .ti -2 .br \fBFunction: \fR ustr_io_putfilename() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A C\-style string of a filename .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: A C\-style string of a filemode (the second argument to fopen) .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function opens a specified file, and then calls ustr_io_putfile(). Finally closing the FILE * object. .sp \fBNote:\fR .br The errno value when this function ends could either be from fopen(), fwrite(), or if both of the those succeeded from fclose(). .SH String substitution/replacement .ti -2 .br \fBFunction: \fR ustr_sub_undef() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of undefined data .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br The Ustr string is expanded as required (possibly reallocated) so that it can contain length (Parameter[2]) data, from the required position. If the length is not zero the Ustr will be writable. Or it'll return USTR_FALSE (zero) on failure. .sp \fBNote:\fR .br You can think of the operation as two seperate tasks, one which makes the current data in the Ustr undefined and the second which adds undefined data to the ustr to accomodate the desired length. .ti -2 .br \fBFunction: \fR ustr_sub_buf() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Buffer containing substitution string .br Type\fB[3]\fR: const void * .br Parameter\fB[4]\fR: Length of buffer .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had called ustr_sub_undef() and then copied the data into the new undefined space. .ti -2 .br \fBFunction: \fR ustr_sub_cstr() .br Returns: success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant C\-style string, which is the substitution .br Type\fB[3]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_sub_buf() but the length is worked out automatically by strlen(). .ti -2 .br \fBFunction: \fR USTR_SUB_OSTR() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A constant C\-style string .br Type\fB[3]\fR: const char [] .br \fBExplanation:\fR .br This function works as if you had called ustr_sub_buf() and passed sizeof() \- 1 as the length. .ti -2 .br \fBFunction: \fR USTR_SUB_OBJ() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A symbol .br Type\fB[3]\fR: ... .br \fBExplanation:\fR .br This function works as if you had called ustr_sub_buf() and passed sizeof() as the length. .sp \fBNote:\fR .br In most cases you'll want to use USTR_SUB_OSTR(). .ti -2 .br \fBFunction: \fR ustr_sub() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string .br Type\fB[3]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works as if you had called ustr_sub_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added. The exception being if you substitute a ustr into itself, while only having a single reference count, the simple method could access a free'd ustr data, but this function just works. .ti -2 .br \fBFunction: \fR ustr_sub_subustr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: A pointer to a constant Ustr string .br Type\fB[3]\fR: const struct Ustr * .br Parameter\fB[4]\fR: Position in the Ustr .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: Length to substitute from the Ustr .br Type\fB[5]\fR: size_t .br \fBExplanation:\fR .br This function mostly as if you had called ustr_sub_buf() with the ustr_cstr() + position \- 1 and length values of the Ustr string to be insed. The exception being if you insert a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works. .ti -2 .br \fBFunction: \fR ustr_sc_sub_undef() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length of undefined data .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works as if you had done ustr_del_subustr() followed by ustr_ins_undef(), however it is significantly more efficient. .ti -2 .br \fBFunction: \fR ustr_sc_sub_buf() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Buffer containting substitute data .br Type\fB[4]\fR: const void * .br Parameter\fB[5]\fR: Length of Buffer .br Type\fB[5]\fR: size_t .br \fBExplanation:\fR .br This function will substitute a specific number of characters in a Ustr with the data from a buffer, this function does the job of one or more of ustr_add_buf(), ustr_sub_buf() and ustr_del(). .ti -2 .br \fBFunction: \fR ustr_sc_sub_cstr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start replacement .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: A pointer to a constant C\-style string, containing spanning bytes .br Type\fB[4]\fR: const char * .br \fBExplanation:\fR .br This function works like ustr_sc_sub_buf() but the length is worked out automatically by strlen(). .ti -2 .br \fBFunction: \fR ustr_sc_sub() .br Returns: success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Pointer to a Ustr containing the substitute string .br Type\fB[4]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works as if you had called ustr_sc_sub_buf() with the ustr_cstr() and ustr_len() values of the Ustr string to be added. The exception being if you substitute a ustr into itself, while only having a single reference count, the simple method could access a free'd ustr data, but this function just works. .ti -2 .br \fBFunction: \fR ustr_sc_sub_subustr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: A pointer to a constant Ustr string .br Type\fB[4]\fR: const struct Ustr * .br Parameter\fB[5]\fR: Position in the Ustr .br Type\fB[5]\fR: size_t .br Parameter\fB[6]\fR: Length to substitute from the Ustr .br Type\fB[6]\fR: size_t .br \fBExplanation:\fR .br This function mostly as if you had called ustr_sc_sub_buf() with the ustr_cstr() + position \- 1 and length values of the Ustr string to be insed. The exception being if you insert a ustr to itself, while only having a single reference count, the simple method would access a free'd ustr data, but this function just works. .ti -2 .br \fBFunction: \fR USTR_SC_SUB_OSTR() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: A constant C\-style string .br Type\fB[4]\fR: const char [] .br \fBExplanation:\fR .br This function works as if you had called ustr_sc_sub_buf() and passed sizeof() \- 1 as the length. .ti -2 .br \fBFunction: \fR USTR_SC_SUB_OBJ() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Position where to start substitution .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of substitution .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: A symbol .br Type\fB[4]\fR: ... .br \fBExplanation:\fR .br This function works as if you had called ustr_sc_sub_buf() and passed sizeof() as the length. .sp \fBNote:\fR .br In most cases you'll want to use USTR_SUB_OSTR(). .ti -2 .br \fBFunction: \fR ustr_replace_buf() .br Returns: Number of tokens replaced .br Type: size_t .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr (haystack) .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Buffer containting search data .br Type\fB[2]\fR: const void * .br Parameter\fB[3]\fR: Length of search buffer .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Buffer containting replacement data .br Type\fB[4]\fR: const void * .br Parameter\fB[5]\fR: Length of replacement buffer .br Type\fB[5]\fR: size_t .br Parameter\fB[6]\fR: Maximum number of matches to replace (0 for unlimited) .br Type\fB[6]\fR: size_t .br \fBExplanation:\fR .br This function scans the "haystack" (Parameter[1]) for "needle" (Parameter[2]) and replaces max_replacements (Parameter[6]) matches with the "replacement" (Parameter[4]). .sp \fBNote:\fR .br If max_replacements (Parameter[6]) is 0, this function will replace ALL occurrences. .ti -2 .br \fBFunction: \fR ustr_replace_cstr() .br Returns: Number of tokens replaced .br Type: size_t .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr (haystack) .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant C\-style string, containing search bytes .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: A pointer to a constant C\-style string, containing replacement bytes .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Maximum number of matches to replace (0 for unlimited) .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_replace_buf() but gets the lengths for the buffer automatically from strlen(). .ti -2 .br \fBFunction: \fR ustr_replace() .br Returns: Number of tokens replaced .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr (haystack) .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Ustr to search for (needle) .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Ustr to replace needle with .br Type\fB[3]\fR: const struct Ustr * .br Parameter\fB[4]\fR: Maximum number of matches to replace (0 for unlimited) .br Type\fB[4]\fR: size_t .br \fBExplanation:\fR .br This function works like ustr_replace_buf() but gets the lengths from the ustr automatically. .ti -2 .br \fBFunction: \fR ustr_replace_rep_chr() .br Returns: number of replacements made .br Type: size_t .br Parameter\fB[1]\fR: pointer to a pointer to a Ustr to be modified .br Type\fB[1]\fR: struct Ustr **ps1 .br Parameter\fB[2]\fR: character to replace .br Type\fB[2]\fR: char .br Parameter\fB[3]\fR: number of characters to replace .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: character to replace with .br Type\fB[4]\fR: char .br Parameter\fB[5]\fR: number of characters to replace with .br Type\fB[5]\fR: size_t nlen .br Parameter\fB[6]\fR: maximum number of replacements to make (use 0 for unlimited) .br Type\fB[6]\fR: size_t lim .br \fBExplanation:\fR .br This function replaces a repeating sequence of characters with another repeating sequence of characters. For example... .Vb 4 Ustr *data = ustr_dup_cstr("xxxBxxCxDxxx"); ustr_replace_rep_chr(&data,'x',2,'y',1, 0) .Ve ...would change data to be "yxByCxDyx". .sp \fBNote:\fR .br Changing the same letter the same number of times is considered a No\-op since it is a vast performance improvement this way. So passing in (&data,'y',2,'y',2 ,0) will have a return value of 0 and the string will be unchanged. .SH Splitting a Ustr .ti -2 .br \fBFunction: \fR ustr_split_buf() .br Returns: pointer to a Ustr representing the next token .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to a constant Ustr to be split .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Pointer to an offset .br Type\fB[2]\fR: size_t * .br Parameter\fB[3]\fR: Buffer to use as split search pattern .br Type\fB[3]\fR: const void * .br Parameter\fB[4]\fR: Length of buffer .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: Pointer to a Ustr to be used as the return value .br Type\fB[5]\fR: struct Ustr * .br Parameter\fB[6]\fR: Flags with the prefix USTR_FLAG_SPLIT_ .br Type\fB[6]\fR: unsigned int .br \fBExplanation:\fR .br This function works in a manner similar to strtok(). Each time the function is called, the string inside of the buffer (Parameter[3]) is used as a search pattern at which to split. If the pattern is not found, the entire string will be returned. A USTR_NULL return value indicates there are no more tokens remaining. .br Parameter[5] is a a pointer to a Ustr where the return value will be placed. Passing a USTR_NULL to this parameter will cause the string to be allocated and \fBMUST\fR be freed \fBmanually\fR. If, however, you pass in a non\-null Ustr to this parameter, each call to ustr_split_buf() will free what is in this pointer and place the new token there (when USTR_NULL is returned, nothing needs to be free'd). For example, given... .Vb 4 Ustr *data = ...; Ustr *tok = USTR_NULL; const char *sep = ","; size_t off = 0; unsigned int flags = USTR_FLAGS_SPLIT_DEF; .Ve ...there are two options... .Vb 4 while ((tok = ustr_split_buf(data, &off, sep, strlen(sep), tok, flags))) { /* Do something with tok \-\- but next iteration of the loop will free * and overwrite tok, so you must ustr_dup() if you want to keep it */ } /* tok is now NULL again after the loop */ .Ve ...or... .Vb 4 while ((tok = ustr_split_buf(data, &off, sep, strlen(sep), USTR_NULL, flags))) { /* Do something with tok, and it will NOT be freed in the next iteration of * the loop */ ustr_free(tok); /* have to free to avoid mem leaks */ } .Ve ...the former of which being the safer option. .sp \fBNote:\fR .br There are several flags that will alter the behaviour of this function, all of which have a common with the default being USTR_FLAG_SPLIT_DEF. .br If you are calling this function directly, it is very likely that you'd want to use ustr_split_cstr() instead. .ti -2 .br \fBFunction: \fR ustr_split() .br Returns: Pointer to a Ustr representing the next token .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to a constant Ustr to be split .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Pointer to an offset variable .br Type\fB[2]\fR: size_t * .br Parameter\fB[3]\fR: Pointer to a constant Ustr to use as the split search pattern .br Type\fB[3]\fR: const struct Ustr * .br Parameter\fB[4]\fR: Pointer to a Ustr where the return value will be placed .br Type\fB[4]\fR: struct Ustr * .br Parameter\fB[5]\fR: Flags .br Type\fB[5]\fR: unsigned int .br \fBExplanation:\fR .br Works like ustr_split_buf() but takes a Ustr as the split search pattern .br instead. .ti -2 .br \fBFunction: \fR ustr_split_cstr() .br Returns: Pointer to a Ustr representing the next token .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to a constant Ustr to be split .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Pointer to an offset variable .br Type\fB[2]\fR: size_t * .br Parameter\fB[3]\fR: C string to use as split search pattern .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Pointer to a Ustr where the return value will be placed .br Type\fB[4]\fR: struct Ustr * .br Parameter\fB[5]\fR: Flags .br Type\fB[5]\fR: unsigned int .br \fBExplanation:\fR .br Works like ustr_split_buf() but takes a C string as the split search pattern, and so gets the length via. strlen(). .ti -2 .br \fBFunction: \fR ustr_split_spn_chrs() .br Returns: Pointer to a Ustr representing the next token .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to a Ustr to be split .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Pointer to an offset variable .br Type\fB[2]\fR: size_t * .br Parameter\fB[3]\fR: String representing a set of bytes to use as split chars .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Length of the string of set of bytes .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: Pointer to a Ustr where the return value will be placed .br Type\fB[5]\fR: struct Ustr * .br Parameter\fB[6]\fR: flags .br Type\fB[6]\fR: unsigned int .br \fBExplanation:\fR .br Works like ustr_split_buf() but uses the individual ASCII bytes in the separator string (Parameter[3]) as search patterns. It will split if \fBANY\fR of these individual characters are matched (much like strtok()). For example: if splitting "this, is,a test" with the separator string ", " the tokens returned would be {"this" "is" "a" "test"}; .sp \fBNote:\fR .br If you are calling this function directly, it is very likely that you'd want to use ustr_split_spn_cstr() instead. .ti -2 .br \fBFunction: \fR ustr_split_spn_cstr() .br Returns: Pointer to a Ustr representing the next token .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to a Ustr to be split .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Pointer to an offset variable .br Type\fB[2]\fR: size_t * .br Parameter\fB[3]\fR: String representing a set of bytes to use as split chars .br Type\fB[3]\fR: const char * .br Parameter\fB[4]\fR: Pointer to a Ustr where the return value will be placed .br Type\fB[4]\fR: struct Ustr * .br Parameter\fB[5]\fR: flags .br Type\fB[5]\fR: unsigned int .br \fBExplanation:\fR .br Works like ustr_split_spn_chrs() but gets the length automatically via. strlen(). .ti -2 .br \fBFunction: \fR ustr_split_spn() .br Returns: Pointer to a Ustr representing the next token .br Type: struct Ustr * .br Parameter\fB[1]\fR: Pointer to a constant Ustr to be split .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Pointer to an offset variable .br Type\fB[2]\fR: size_t * .br Parameter\fB[3]\fR: Pointer to a constant Ustr to use as the split search pattern .br Type\fB[3]\fR: const struct Ustr * .br Parameter\fB[4]\fR: Pointer to a Ustr where the return value will be placed .br Type\fB[4]\fR: struct Ustr * .br Parameter\fB[5]\fR: Flags .br Type\fB[5]\fR: unsigned int .br \fBExplanation:\fR .br Works like ustr_split_spn_chrs() but takes a Ustr as the split chars instead. .SH Dealing with UTF\-8 in a Ustr .ti -2 .br \fBFunction: \fR ustr_utf8_valid() .br Returns: A boolean flag of either USTR_TRUE or USTR_FALSE .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function tries it's best to find out if the string is a valid utf\-8 string. .ti -2 .br \fBFunction: \fR ustr_utf8_len() .br Returns: The number of the utf\-8 characters in the Ustr .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function counts the number of utf\-8 characters inn the Ustr. .sp \fBNote:\fR .br This function gives undefined answers on strings that aren't utf\-8 valid. .ti -2 .br \fBFunction: \fR ustr_utf8_width() .br Returns: ssize_t .br Type: ssize_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function returns the visible width of the string, assuming it is a valid utf\-8 string. This is like converting to wide characters and using wcwidth(). .ti -2 .br \fBFunction: \fR ustr_utf8_chars2bytes() .br Returns: Length of span in bytes .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Position of a span in utf\-8 characters .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of a span in utf\-8 characters .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Returns the position of the span in bytes .br Type\fB[4]\fR: size_t * .br \fBExplanation:\fR .br This function converts a span, in utf\-8 characters, to the same span in bytes. .ti -2 .br \fBFunction: \fR ustr_utf8_bytes2chars() .br Returns: Returns the position of a span in utf\-8 characters .br Type: size_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Position of a span in bytes .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length of a span in bytes .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Returns length of a span in utf\-8 characters .br Type\fB[4]\fR: size_t * .br \fBExplanation:\fR .br This function converts a span, in bytes, to the same span in utf\-8 characters. .sp \fBNote:\fR .br Because a byte span can start or end within a utf\-8 character, converting the return values back into bytes via. ustr_utf8_chars2bytes() may make the span be slightly bigger (position slightly earlier, and the length slightly longer). .ti -2 .br \fBFunction: \fR ustr_sc_utf8_reverse() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function reverses the utf\-8 characters in the Ustr string, assuming it is a valid utf\-8 string, so the last one becomes the first and the second to last becomes the second etc. .SH Parsing ASCII integer numbers from a Ustr .ti -2 .br \fBFunction: \fR ustr_parse_uintmaxx() .br Returns: Parsed number, or zero on error .br Type: uintmax_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Base (2\-36) and flags, starting with USTR_FLAG_PARSE_NUM_ .br Type\fB[3]\fR: unsigned int .br Parameter\fB[4]\fR: Absolute minimum value .br Type\fB[4]\fR: uintmax_t .br Parameter\fB[5]\fR: Absolute maximum value .br Type\fB[5]\fR: uintmax_t .br Parameter\fB[6]\fR: Thousands separator .br Type\fB[6]\fR: const char * .br Parameter\fB[7]\fR: Return length of parsed number .br Type\fB[7]\fR: size_t * .br Parameter\fB[8]\fR: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ .br Type\fB[8]\fR: unsigned int * .br \fBExplanation:\fR .br This function parses an ASCII representation of a number from a Ustr (Parameter[1]) starting at the offset (Parameter[2]). .sp \fBNote:\fR .br If stdint.h isn't available this function won't be available. .ti -2 .br \fBFunction: \fR ustr_parse_uintmax() .br Returns: Parsed number, or zero on error .br Type: uintmax_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Base (2\-36) and flags, starting with USTR_FLAG_PARSE_NUM_ .br Type\fB[3]\fR: unsigned int .br Parameter\fB[4]\fR: Return length of parsed number .br Type\fB[4]\fR: size_t * .br Parameter\fB[5]\fR: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ .br Type\fB[5]\fR: unsigned int * .br \fBExplanation:\fR .br This function works like ustr_parse_uintmaxx() with the minimum and maximum values taken as 0 and UINTMAX_MAX, and the thousands separator as "_". .sp \fBNote:\fR .br If stdint.h isn't available this function won't be available. .ti -2 .br \fBFunction: \fR ustr_parse_intmax() .br Returns: Parsed number, or zero on error .br Type: intmax_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Base (2\-36) and flags, starting with USTR_FLAG_PARSE_NUM_ .br Type\fB[3]\fR: unsigned int .br Parameter\fB[4]\fR: Return length of parsed number .br Type\fB[4]\fR: size_t * .br Parameter\fB[5]\fR: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ .br Type\fB[5]\fR: unsigned int * .br \fBExplanation:\fR .br This function works like ustr_parse_uintmaxx() with the minimum and maximum values taken as \-INTMAX_MIN and INTMAX_MAX, and the thousands separator as "_". .sp \fBNote:\fR .br If stdint.h isn't available this function won't be available. .ti -2 .br \fBFunction: \fR ustr_parse_ulongx() .br Returns: Parsed number, or zero on error .br Type: unsigned long .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Base (2\-36) and flags, starting with USTR_FLAG_PARSE_NUM_ .br Type\fB[3]\fR: unsigned int .br Parameter\fB[4]\fR: Absolute minimum value .br Type\fB[4]\fR: unsigned long .br Parameter\fB[5]\fR: Absolute maximum value .br Type\fB[5]\fR: unsigned long .br Parameter\fB[6]\fR: Thousands separator .br Type\fB[6]\fR: const char * .br Parameter\fB[7]\fR: Return length of parsed number .br Type\fB[7]\fR: size_t * .br Parameter\fB[8]\fR: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ .br Type\fB[8]\fR: unsigned int * .br \fBExplanation:\fR .br This function works like ustr_parse_uintmaxx() but returns an unsigned long, it is always available even when stdint.h isn't. .ti -2 .br \fBFunction: \fR ustr_parse_ulong() .br Returns: Parsed number, or zero on error .br Type: unsigned long .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Base (2\-36) and flags, starting with USTR_FLAG_PARSE_NUM_ .br Type\fB[3]\fR: unsigned int .br Parameter\fB[4]\fR: Return length of parsed number .br Type\fB[4]\fR: size_t * .br Parameter\fB[5]\fR: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ .br Type\fB[5]\fR: unsigned int * .br \fBExplanation:\fR .br This function works like ustr_parse_ulongx() with the minimum and maximum values taken as 0 and ULONG_MAX, and the thousands separator as "_". .ti -2 .br \fBFunction: \fR ustr_parse_long() .br Returns: Parsed number, or zero on error .br Type: long .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Base (2\-36) and flags, starting with USTR_FLAG_PARSE_NUM_ .br Type\fB[3]\fR: unsigned int .br Parameter\fB[4]\fR: Return length of parsed number .br Type\fB[4]\fR: size_t * .br Parameter\fB[5]\fR: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ .br Type\fB[5]\fR: unsigned int * .br \fBExplanation:\fR .br This function works like ustr_parse_ulongx() with the minimum and maximum values taken as \-LONG_MIN and LONG_MAX, and the thousands separator as "_". .ti -2 .br \fBFunction: \fR ustr_parse_uint() .br Returns: Parsed number, or zero on error .br Type: unsigned int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Base (2\-36) and flags, starting with USTR_FLAG_PARSE_NUM_ .br Type\fB[3]\fR: unsigned int .br Parameter\fB[4]\fR: Return length of parsed number .br Type\fB[4]\fR: size_t * .br Parameter\fB[5]\fR: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ .br Type\fB[5]\fR: unsigned int * .br \fBExplanation:\fR .br This function works like ustr_parse_ulongx() with the minimum and maximum values taken as 0 and UINT_MAX, and the thousands separator as "_". .ti -2 .br \fBFunction: \fR ustr_parse_int() .br Returns: Parsed number, or zero on error .br Type: int .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Base (2\-36) and flags, starting with USTR_FLAG_PARSE_NUM_ .br Type\fB[3]\fR: unsigned int .br Parameter\fB[4]\fR: Return length of parsed number .br Type\fB[4]\fR: size_t * .br Parameter\fB[5]\fR: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ .br Type\fB[5]\fR: unsigned int * .br \fBExplanation:\fR .br This function works like ustr_parse_ulongx() with the minimum and maximum values taken as \-INT_MIN and INT_MAX, and the thousands separator as "_". .ti -2 .br \fBFunction: \fR ustr_parse_ushort() .br Returns: Parsed number, or zero on error .br Type: unsigned short .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Base (2\-36) and flags, starting with USTR_FLAG_PARSE_NUM_ .br Type\fB[3]\fR: unsigned int .br Parameter\fB[4]\fR: Return length of parsed number .br Type\fB[4]\fR: size_t * .br Parameter\fB[5]\fR: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ .br Type\fB[5]\fR: unsigned int * .br \fBExplanation:\fR .br This function works like ustr_parse_ulongx() with the minimum and maximum values taken as 0 and USHRT_MAX, and the thousands separator as "_". .ti -2 .br \fBFunction: \fR ustr_parse_short() .br Returns: Parsed number, or zero on error .br Type: short .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Base (2\-36) and flags, starting with USTR_FLAG_PARSE_NUM_ .br Type\fB[3]\fR: unsigned int .br Parameter\fB[4]\fR: Return length of parsed number .br Type\fB[4]\fR: size_t * .br Parameter\fB[5]\fR: Return error code, starting with USTR_TYPE_PARSE_NUM_ERR_ .br Type\fB[5]\fR: unsigned int * .br \fBExplanation:\fR .br This function works like ustr_parse_ulongx() with the minimum and maximum values taken as \-SHRT_MIN and SHRT_MAX, and the thousands separator as "_". .SH Misc shortcut helper functions for Ustrs .ti -2 .br \fBFunction: \fR ustr_sc_ensure_owner() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function makes sure that the Ustr string is owned when it returns (Ie. ustr_owner() returns USTR_TRUE), or it fails to allocate. .ti -2 .br \fBFunction: \fR ustr_sc_wstr() .br Returns: Writable pointer to the start of data in the Ustr, or NULL .br Type: char * .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function works like calling ustr_sc_ensure_owner(), to make sure the Ustr string is writable, and if that succeeds it returns ustr_wstr(). On failure it returns NULL. .ti -2 .br \fBFunction: \fR ustr_sc_export_subustr() .br Returns: A pointer to newly allocated block of memory .br Type: char * .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Position in the Ustr .br Type\fB[2]\fR: size_t .br Parameter\fB[3]\fR: Length to export from the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Allocation function (like malloc) .br Type\fB[4]\fR: void *(*)(size_t) .br \fBExplanation:\fR .br This function allocates a block of memory of size Length (Parameter[3]) + 1 using the provided allocation function (Parameter[4]) and copies the data starting from Position (Parameter[2]) within the ustr. .ti -2 .br \fBFunction: \fR ustr_sc_export() .br Returns: A pointer to newly allocated block of memory .br Type: char * .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Allocation function (like malloc) .br Type\fB[2]\fR: void *(*)(size_t) .br \fBExplanation:\fR .br This function works like calling ustr_sc_export_subustr() with a position of 1 and a length of ustr_len(). .ti -2 .br \fBFunction: \fR ustrp_sc_export_subustrp() .br Returns: A pointer to newly allocated block of memory .br Type: char * .br Parameter\fB[1]\fR: Pointer to a Ustr pool object .br Type\fB[1]\fR: struct Ustr_pool * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Position in the Ustr .br Type\fB[3]\fR: size_t .br Parameter\fB[4]\fR: Length to export from the Ustr .br Type\fB[4]\fR: size_t .br Parameter\fB[5]\fR: Allocation function (like malloc), or NULL .br Type\fB[5]\fR: void *(*)(size_t) .br \fBExplanation:\fR .br This function allocates a block of memory of size Length (Parameter[4]) + 1 using either the provided allocation function (Parameter[5]), or from the pool object if the allocation function is NUL, and copies the data starting from Position (Parameter[3]) within the ustr. .ti -2 .br \fBFunction: \fR ustrp_sc_export() .br Returns: A pointer to newly allocated block of memory .br Type: char * .br Parameter\fB[1]\fR: Pointer to a Ustr pool object .br Type\fB[1]\fR: struct Ustr_pool * .br Parameter\fB[2]\fR: A pointer to a constant Ustr string .br Type\fB[2]\fR: const struct Ustr * .br Parameter\fB[3]\fR: Allocation function (like malloc) .br Type\fB[3]\fR: void *(*)(size_t) .br \fBExplanation:\fR .br This function works like calling ustrp_sc_export_subustrp() with a position of 1 and a length of ustrp_len(). .ti -2 .br \fBFunction: \fR ustr_sc_reverse() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function reverses all the bytes in the Ustr string, so the last one becomes the first and the second to last becomes the second etc. .ti -2 .br \fBFunction: \fR ustr_sc_tolower() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function changes any ASCII upper case bytes into ASCII lower case bytes. .ti -2 .br \fBFunction: \fR ustr_sc_toupper() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br \fBExplanation:\fR .br This function changes any ASCII lower case bytes into ASCII upper case bytes. .ti -2 .br \fBFunction: \fR ustr_sc_ltrim_chrs() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Array of bytes, containing trimming data .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: Length of byte data .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function deletes the bytes at the begining of the Ustr (Parameter[1]) that are in the span (Parameter[2]) of the specificed length (parameter[2]). .ti -2 .br \fBFunction: \fR ustr_sc_ltrim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant Ustr string, containing trimming bytes .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works as if you had called ustr_sc_ltrim_chrs() and passed ustr_cstr() and ustr_len() values of the Ustr string (Parameter[2]). .ti -2 .br \fBFunction: \fR ustr_sc_ltrim_cstr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant C\-style string, containing trimming bytes .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works as if you had called ustr_sc_ltrim_chrs() and passed strlen() as the length. .ti -2 .br \fBFunction: \fR ustr_sc_rtrim_chrs() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Array of bytes, containing trimming data .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: Length of byte data .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function deletes the bytes at the end of the Ustr (Parameter[1]) that are in the span (Parameter[2]) of the specificed length (parameter[2]). .ti -2 .br \fBFunction: \fR ustr_sc_rtrim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant Ustr string, containing trimming bytes .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works as if you had called ustr_sc_rtrim_chrs() and passed ustr_cstr() and ustr_len() values of the Ustr string (Parameter[2]). .ti -2 .br \fBFunction: \fR ustr_sc_rtrim_cstr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant C\-style string, containing trimming bytes .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works as if you had called ustr_sc_rtrim_chrs() and passed strlen() as the length. .ti -2 .br \fBFunction: \fR ustr_sc_trim_chrs() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Array of bytes, containing trimming data .br Type\fB[2]\fR: const char * .br Parameter\fB[3]\fR: Length of byte data .br Type\fB[3]\fR: size_t .br \fBExplanation:\fR .br This function deletes the bytes at the begining or end of the Ustr (Parameter[1]) that are in the span (Parameter[2]) of the specificed length (parameter[2]). .sp \fBNote:\fR .br Calling this function is much more efficient than calling ustr_sc_rtrim_chrs() and then ustr_sc_ltrim_chrs(), as both ends are trimmed in a single pass. .ti -2 .br \fBFunction: \fR ustr_sc_trim() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant Ustr string, containing trimming bytes .br Type\fB[2]\fR: const struct Ustr * .br \fBExplanation:\fR .br This function works as if you had called ustr_sc_trim_chrs() and passed ustr_cstr() and ustr_len() values of the Ustr string (Parameter[2]). .ti -2 .br \fBFunction: \fR ustr_sc_trim_cstr() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: A pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: A pointer to a constant C\-style string, containing trimming bytes .br Type\fB[2]\fR: const char * .br \fBExplanation:\fR .br This function works as if you had called ustr_sc_trim_chrs() and passed strlen() as the length. .SH Adding binary data to a Ustr .ti -2 .br \fBFunction: \fR ustr_add_b_uint16() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Binary value to add to the Ustr .br Type\fB[2]\fR: uint_least16_t .br \fBExplanation:\fR .br This function adds a binary representation of a value (Parameter[2]) to the Ustr (Parameter[1]). .ti -2 .br \fBFunction: \fR ustr_add_b_uint32() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Binary value to add to the Ustr .br Type\fB[2]\fR: uint_least32_t .br \fBExplanation:\fR .br This function adds a binary representation of a value (Parameter[2]) to the Ustr (Parameter[1]). .ti -2 .br \fBFunction: \fR ustr_add_b_uint64() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Binary value to add to the Ustr .br Type\fB[2]\fR: uint_least64_t .br \fBExplanation:\fR .br This function adds a binary representation of a value (Parameter[2]) to the Ustr (Parameter[1]). .SH Parsing binary data from a Ustr .ti -2 .br \fBFunction: \fR ustr_parse_b_uint16() .br Returns: uint_least16_t .br Type: uint_least16_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br This function parses a binary representation from a Ustr (Parameter[1]) starting at the offset (Parameter[2]). .ti -2 .br \fBFunction: \fR ustr_parse_b_uint32() .br Returns: uint_least32_t .br Type: uint_least32_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br This function parses a binary representation from a Ustr (Parameter[1]) starting at the offset (Parameter[2]). .ti -2 .br \fBFunction: \fR ustr_parse_b_uint64() .br Returns: uint_least64_t .br Type: uint_least64_t .br Parameter\fB[1]\fR: A pointer to a constant Ustr string .br Type\fB[1]\fR: const struct Ustr * .br Parameter\fB[2]\fR: Offset within string to start parsing at .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br This function parses a binary representation from a Ustr (Parameter[1]) starting at the offset (Parameter[2]). .SH Misc. functions .ti -2 .br \fBFunction: \fR ustr_realloc() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Pointer to a pointer to a Ustr string .br Type\fB[1]\fR: struct Ustr ** .br Parameter\fB[2]\fR: Size of allocation .br Type\fB[2]\fR: size_t .br \fBExplanation:\fR .br This function is re\-sizes the Ustr to the specified size (Parameter[2]). .br This is mostly used to shrink a sized Ustr that is now significantly smaller than it once was. Although this function can also grow a Ustr. .sp \fBNote:\fR .br To have a size that isn't implied from the length the Ustr must store a size value as well as a length (ustr_sized() must return USTR_TRUE). .ti -2 .br \fBFunction: \fR ustr_cntl_opt() .br Returns: Success or failure .br Type: int .br Parameter\fB[1]\fR: Optional value starting with USTR_CNTL_OPT_ .br Type\fB[1]\fR: int .br Parameter\fB[2]\fR: Arugments to option .br Type\fB[2]\fR: ... .br \fBExplanation:\fR .br This function views and/or changes global Ustr options, like whether ustr's have an implicit or explicit size (USTR_CNTL_OPT_GET_HAS_SIZE). .SH Simple Ustr pool API .ti -2 .br \fBFunction: \fR ustr_pool_ll_make() .br Returns: Pointer to a Ustr pool object .br Type: struct Ustr_pool * .br Parameter\fB[1]\fR: Nothing .br Type\fB[1]\fR: void .br \fBExplanation:\fR .br This allocates a new pool using the "linked list" strategy, each allocation in the pool is added to a linked list ... and any allocations not freed directly are freed by the pool when it is cleared or freed. .ti -2 .br \fBFunction: \fR ustr_pool_make_subpool() .br Returns: Pointer to a Ustr pool object .br Type: struct Ustr_pool * .br Parameter\fB[1]\fR: struct Ustr_pool * .br Type\fB[1]\fR: struct Ustr_pool * .br \fBExplanation:\fR .br This allocates a new pool as a child of the passed in pool (Parameter[1]), The pool can be freed and cleared independantly of the parent pool however free and clear operations on the parent pool are automatically applied to all child pools. .ti -2 .br \fBFunction: \fR ustr_pool_free() .br Returns: Nothing .br Type: void .br Parameter\fB[1]\fR: Pointer to a Ustr pool object .br Type\fB[1]\fR: struct Ustr_pool * .br \fBExplanation:\fR .br This deallocates a pool, and all sub\-pools. .sp \fBNote:\fR .br This also operates on all sub\-pools. .ti -2 .br \fBFunction: \fR ustr_pool_clear() .br Returns: Nothing .br Type: void .br Parameter\fB[1]\fR: Pointer to a Ustr pool object .br Type\fB[1]\fR: struct Ustr_pool * .br \fBExplanation:\fR .br This allows all the data in the pool to be reused, it may also free some/all of the data in the pool, from the pool API. .sp \fBNote:\fR .br This also operates on all sub\-pools. .SH "SEE ALSO" .BR ustr_const (3) ustr-1.0.4/Documentation/design.html0000644000076400007640000003017110763663475016474 0ustar jamesjames Design of ustr, the micro string API - for C body { width 85% }; A { background: #FFF; color: #44F; } A:hover { color: #20b2aa; } A.anchor { color: #000; } A.anchor:hover { color: #000; } P { text-indent: 2em; } ul li { list-style-type: lower-roman; }

      Design of ustr, the micro string API - for C

      Non-Magic version of a ustr

      /* As the saying goes:
       *   "you can tell a lot about the code from the data structure".
       *
       * So this is the non-magic version of 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.
       *
       */
      

      Magic/real version of ustr

      struct Ustr 
      {
       unsigned char data[1];
       /* 0b_wxzy_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 just used 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 aliasing rules screw us over if we do that. */
        struct Ustr s;
      };
      

      Unused bit patterns for a ustr

      /* 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
       *
       */
      

      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, <x>, <x>, <x>}
      

      Number of options for strings

      This design allows 83 different combinations of options for your string types:

      • Constant/read-only strings.: Ie.
        Ustr *s1 = USTR("");
        Ustr *s2 = USTR1(\x4, "abcd");
        
      • Fixed/auto sized strings.: These can seamlessly convert into allocated strings, if you add too much data. Ie.
          char buf_s3[USTR_SIZE_FIXED(128)] = "x112233abcd";
          /*                  x       = the info byte
                               11     = reference count storage - always two bytes
                                 22   = len storage  - always same size as the size
                                   33 = size storage - uses 2, 4 or 8 bytes depending on sizeof() */
          Ustr *s3 = USTR_SC_INIT_AUTO(buf_s3, USTR_FALSE, 4); /* s3 is now the string "abcd" */
        
      • Fixed/auto sized limited strings.: These will fail to go beyond their specified size (this failure can be checked with ustr_enomem(), just like allocated strings). Ie.
          char buf_s3[USTR_SIZE_FIXED(32)] = USTR_BEG_FIXED2 "abcd";
          Ustr *s3 = USTR_SC_INIT_AUTO(buf_s3, USTR_TRUE, 4); /* s3 is now the string "abcd" */
        
      • Allocated, no reference counts: This is the lowest overhead, meaning that ustr_dup() etc. will always have to create a new string and do a copy. For this loss of functionality you gain a single byte. Although if you never share the strings and have very small string lengths this could be significant (0% overhead for an 8 byte string, total overhead being 37.5% or 50% with allocation rounding).
      • Allocated, uint8_t reference counts: If you anticipate a low (1-255 users) amount of sharing, and a very low average string size. You can allocate just a single byte to the reference count (less than 10% overhead for an 8 byte string, total overhead being 50%).
      • Allocated, uint16_t reference counts: This is what I'd consider "normal" usage, it allows a string to be duplicated at no cost upto 65,535 times, and the reference count is only going to take up 2 bytes (less than 20% overhead for an 8 byte string, total overhead being 62.5% or 100% with allocation rounding). Note this is the default allocation policy
      • Allocated, uint32_t reference counts: This might be useful if you want to share the string in a lot of places, it allows a string to be duplicated at no cost upto 4,294,967,295 times, but the reference count is going to take up 4 bytes (less than 40% overhead for an 8 byte string, total overhead being 87.5% or 100% with allocation rounding).
      • Allocated, uint64_t reference counts: This is available, allowing a string to be duplicated at no cost upto 18,446,744,073,709,551,615 times, but the reference count is going to take up 8 bytes (less than 100% overhead for an 8 byte string, total overhead being 137.5% or 200% with allocation rounding). Note that this is only allowed on a 64bit machine.
      • Allocated, infinite reference count: If you have an allocates string which has any size of reference count you can call ustr_set_share() and the string will allow an infinite amount of duplication, but can never be free'd no matter how many times someone calls ustr_free(). The string can also not be altered anymore. Calling ustr_set_owner() returns the reference count to 1, and calling ustr_free_shared() will free the string.
      • Pool allocated: If you use the ustrp_*() calls instead of ustr_*() calls, you will get strings allocated from a "pool" of memory which can be free'd at once (note that ustrp_free() probably does nothing, in this case).
      • Allocated, with explicit size: For slightly extra overhead you can have explicitly sized allocated strings, these will have ustr_size() expand as needed ... but they will not implicitly reclaim that memory (you have to call ustr_realloc()). They are useful if you need to add significant amounts of data and then delete it before adding more.
      • Allocated, with exact size: For slightly less extra overhead you can have exactly sized allocated strings, these do not add any extra space when the strings need to be resized. Thus if you need to store a 4 byte string, using uint16_t reference counts and no stored size, you will allocate 9 bytes instead of 12 bytes. However to then add a single byte the system allocation functions will need to be called.

      James Antill
      Last modified: Tue Aug 28 01:06:50 EDT 2007 ustr-1.0.4/Documentation/strdup vs. ustr.gnumeric0000644000076400007640000010444210644060243021037 0ustar jamesjames‹£`Fí½qsÇ•åûÿ~ wgÞ±*ofUuz×ÚÆv[/h—£¥ö¼ -ÂÖ$ÁB–µŸþUåMv÷Í̆Ωr8F»°"$Ð'ówчØ?à¿þ·¿¾yýì/7÷ïoïÞþâ¹ûY÷üÙÍÛ¯î^ݾýúÏ_üúŸwÏÿÛÇÿá¿~ýöÍÏÿõîþϼ»ûó³9òöýÏç7ýâù7ï~þÑGß}÷ÝϾ~ûí››ûÛ¯~vwÿõGqÝÏ^=¼zžû×÷·æ±ßùô(é:÷ÑÿûÛŸõÍÍ›—ÿ|ûöýÃË·_ÝÌ©÷·?ŸÞøâî«—‰íêU»Ÿýõý«çÿ‡gÏæt˜g¿zw÷Õ7óHÏŸýöåÿº»ÿÅóaþÕíÛåWþù³_ûúõ2ïð3ÿü£Sö“‡‡ûÛ?~ûpó~ySùF}[~ëÃ÷ïn>ÿõ£Ó¯/ßùöå››?|¼þp{óÝÏþþ›»ï¾üæîþöß½}xùúË÷_Ýß½~ýÇ—÷zDJ\ñ——¯¿½ùø‹ÃñWúý½R}ÔÀú[£Î;ñpûÕôíÝÃÍò¦/^þñý¿?ÆWw_¾üöáî˯îÞ¼{}³¬ò¿?ÆÛ÷_¾»Ÿ?Œ_=ܼz”îן¼øÂ+Þôþôöù·oÞ¼¼ÿþb„ÏnÞÔ€/ß½{}«Ÿú׉þùý|þÛ¯?þÐ'²ï¸À;_óØ­ß>ÌŸ¢?|áÿ3¿ïý³OÞ>ܾ~\ª¿»˜]?ßÜÜ<ün>ê³·¯nþzwzÇÇéW.ÇOo½úHé,Þt¢JùýÍÝ››‡ûïŸýëí«‡¥W;‰ÏŸýææöëoæní.k4ñ¾¼üÙ/oß¿{ýòû_ßÝ¿ùöõË÷¿x>ÿaó›ÛW7ÿvswúÍþþöÕé7ÿr÷ú77/_ÝÜŸÞr¸ûîâ-ùÄéۇ׷ooÞ§¶Ï¿ùüû7¼{ýþÓ›×wß5Þ~Pîùí¸}ûÇÛ×·ßÿâùþw¿ýòóßüêW_|ù‡Ï>ÿìÓÏ^|öÅ×_¾øÕs³ Õ³ó»r]~ûò¯3þÇ2êûóo‹GÌãÌèOY~ù»»{óq¾!ýúò¿Ÿ×íá³·š?žéåÃ;OÇß=ÿ‘z~ë‡v¸{÷ì÷wstùxÉüQüýýÍŸŽooçÇWoôY4ÿãÝÃÃÝ,òaâf]‚ùO“›gKýâù»›û¯næ?¿žÿ°?ÿz٪Η>µ–÷ÞÜ?K³<íå¾ù¡|=ïÔõ÷Þüåæí—·úòîíëï¿|ÿðýëùSûêƒßܽ¿¬¸Ÿ?®?æÕýË?=\÷ÃíãWÜÝÏëýñ«/¾™¹réÛÊÇÝ.¶ôÌ¿»»¸yûðáÑç÷ØŒ~î<{qó§ù©[¾zõêõ ñŸ_¾y÷_þÇŸ|ú?Ÿ?ËŸÖ¯ïîÑßÏÏÛ3Íÿþ“ý¯Z(ÔµmÕÝHöra–7n¾^¾š›¿2¼˜?æª Ïõw‡å[úaùŠõUz—ô}úMzOèbÿ¼Zætæ³ß|òúöë·úéŸ)ÏŸýëýËw_Üüõ!UËçß̼þâî×·úûÃÝCþB4½sþ0¦_-%ùV1©úç›Wéй©æ7§·Îm·<òçó?ÏŸ}úò«?ÿâù¯çÿýüôó'Óˇù#ûvaùâ4?ô×éã4WÒÍÛ›û—¯Í$§gäíÃ3ý,tËáw¯µ9?›¿¾¼ý*ýò8ãÝ/µ§ØóP¾ùb^ßo¿þFßòÕýí»„ÿñç/ßæ/Ÿ–s×¥ݧÅ&^¼ÿ‹¹WÒcŠ¥¾xȧZ%?ð¨eÅ~è1iÉ~èA¿¼}ùõÝÛ—¯ð°›¿üó>6ÿéØþ \¼³,Ë-†öÛËå~»‹íöñ¼Ý˪?-÷ÓrÿÈ–Û–÷\Ñ×Ú{è{ÿ´áOþ£Ûp1Þ]®·;¯w·vµ¶ÚnÝjÇù?ÿ—ùË›þ¦{í~<{=·™ùiËè‹óEøàŸZü©ÅÏúQî·\ý"\.¾V×ø¿£Ýî~Öuÿð´ÙÅ2þŸ»ÙîÚf»¿çf¯ü%}m’¾J6û?þÓüËv?-w±ÿÇ.·‹W–ÛŧÚ~Úìófï®möî©¶Ÿ–ûô çr×–{xªí§Íþ1ovm³û§Ú~ZîÓƒ~œËí¯-·ªí§Íþ1oöµÿüçþ®ÿùï©¶ÍûŸ–ûo³Üݵåîžjûi³Ä›}í¿þý]ÿãßSi›÷?­ößdµÇ+«=>­öÓjŸô£\mûŠ©‹Ýöîé•$OÛ}~Ðs»ýµ×>½Nêi»/ôãÜnû:ÀáÊ+¥žöûi¿œûí®ï÷ßù«“¿ÇßOûýÛ~_ûoÒý(¶ûÜÞËŠ?mwù¨ÿ»·Û¾д÷å Ÿ¾:yÚïç~ï®ï÷îGÑßO_<í÷#û}í¿z»ñG±ÝO_?èǹßýõýþ;§‡§¯N.ßÿ´ß›ý¾ö÷–Ë;~ÛýôÕÉÓv?²Ýþz{?ýÍåÓ~_<èǹß×ÿæÒýÿæòé«“Ë÷?í÷ßf¿¯}Ÿ÷ãø{˧¯Nž¶û‘íî®·÷ßùo.Ÿ¾:¹|ÿÓ~ÿMöûú_\þÿÞòék“Ë÷?m÷ßd»¯}/“ÇßY>}eò´Û×w{¼ÚÜ?Ž¿³|jî§í¾¾Ý×¾QÏßùï+ŸšûòýO»ý7ÙíîÊnÿˆþ®2íöò«r·Ë÷>-ùÓ’§ß´l§oNÿïw«Ÿ¾9}õámÅתÜü ÷ô_ÿ]¯úÓr7—»—k~ùósž~>ÔÓvÿ·»¨îáJw?­÷Ózÿû\ï‹wœ~že™Wàý³_Þüéå·¯>¿ýß7¿_~˜jØ=/>/æ‡-?$óÙïîò“¼¬@~Ö/?Ç|ù±ªŸ¤}Ö_š~ý›—÷¯–ÓzþËÝ·ËÎÊåˆÕÁr:X~6þMO§“#ŠüØqý‡ãzƒ>vÞp:¯û™ü ÎWð}ø@úGOv§'¿ïÿ¶O¾“3ôöÀòbÀ|ZxôCÙÂã§> Áÿ-ögÑàòy»«§=z@üpÀÐ=6Þ£Ÿm~âÊgûGG<¿cÙ¢[ZÍÔÜüÇs]s.ÕLA2?²nº~´å{|²Ëó܇óœåŸžÝÿñ8F~øŽñÀ1ÿôìý¼(¯€ÓÂÕÓþóÿ÷íÝÃyûæÝü…å|òíÛ¯õMÀ©=*Ž<\=ü‹ùkÙ×ψgv¼zÔ'¹ùsÒî ¨M‰cQg¹ëŸÿ@žtýó ˜YcwýÓÁ vý“âÈ“®B”Câë®>³g^ÿ4ø‡u^ÿdÐÉ?ÿü™—?Þ> g]ÿtH3G]ÿdøpʳ@Ú÷úçÁi¼!`Lrý3áÃxðQ×? >œ÷a:gŽñó1ЧöÕtGüÁ¶.í7¥Ã)ýñ/ÞÝ}wsÿù§îú“ðÓôRÝý•#v?Mÿ G G¼ÿöÍO>ùOòóO„ùhIîå£ÿô RR»âº™¯ûèºxþ`ÿê¯ïî?û¥òz³»¾gÿLý£;i±W_â×&¬E ê/gÔ_b¨}*ó)üa6²û¯fö_aì—Ëu€£Mí‘tå¯gÊ_C”r¹GG”RĦ Êr~.ýÿD~Ê4ëE:\ôŒüãO?üÒAs·Ž»þ9àë‡÷·{äÊp:ãtë¶C¯vÅZ¯¿l=ˆÕ5¶ÈAÿr»Üõbøh  ÀÔz`k‹ »]îšPÀ±L­‡^.Ê~Š£MA”Ò”©õ J¹\‘#J)bSåÈk½ë%á‡ÓÃ7·Þ`Z˜.kmdjmIîÇù)‰Z.k º.6[þà3ôjר ¨Ö†ËZƒX]cMÜ£[è/îz1~´‡ `ª5 °µ&^îÉ„Ž`ª5 ðrQðSm ¢”® LµQÊåŠQJ›‚(?@Ž\­\­÷ÜÃÃéá›km$km¼¬5èë¼ñ"¹ßÍO鎨µñ²Ö ëbc°å‹üÏЫ]c3 Z/k bu5qý·`ç/îz±ûh  ÀTk`kM¼Ü“  ÀTkàå¢à§8ÚD)]A™j ¢”Ë9¢”"6Q~€Üqµ¶ãj |¸¯î.ÿjªp:dsÙíȲÛ]–]dÊnIîãüDG¢ìv—e]ƒ¥¿EE¯v}ÊnwYv«k,{ô.q׋øÑ(€©ì0ÀÖš< x¹' 8€©ì0ÀËE9ÀOq´)ˆRº‚2•D)—+rD)El ¢ü¹²‹\ÙEÓ^?ÜvèãCãñ£iÇU%wyÜ®8nÅž‹—è:¦—èÞuó8ä%»âÆTƒØ±1ûrÌgøí®±LPÆË&Äp]kµ[Eç/.{1µÇf c*C±µO2^nÌ„3ŽcêCñreÄs‹†*]šJC•Ëu9â¨"EC=½Â°ãªñòñ–—°ÏB+ðØ_£ö­Àc/#ÎËŽƒ^8^f÷Î-Ï'òºÈ]y§¶tgl (éï_ñû]k3 ž;kÑAÄ®µ&ý-lºîÅ<Ø›+”˜ÚufkuÇ4»3á˜c‰©u‡ašå9Oz,ƒ­t%­6ö’]³8GœV¤ b´'XGvžc; x6Z¨óÛyFÙpœ³‘¤ ·¼úÜQÚ†3lj—JAR7ðû]k3°Î3ºFìZk"˜±áRçɼð”³çŒªb¶VçqL³;Ž9–˜Úy¤–‘ âIe£•®¤ÕÎ#õŒdZà´"e£=Á ÙyÂvð€\ áüz<ÊÃ0P' Û‰F²p”e‘²{·¼ÎÜ1¢…3¦vgl}ˆÓ_Ýâ÷»Öæ`hŒ ŒØµÖH ¿ÀM×½˜Ûcs…S;‘3/pL³;Ž9–˜Ú‰œ€‘ÂâIe£•®¤ÕNäDŒ>â´"e£=Á’>Æåã±Nô¦â€ND¡…užg;ÏxŽ-Rvï–Wš;ƵpF¶Àaú{]ü~×Ú ¬óŒs»æš@»›®{1¶Çæ %¦vç^à˜fw&s,1µó8#…Ä“Ë F+]I«Ç©)|ÄiEÊ F{‚%ŒËÇ?ÚHÂ<Öyí<#Z8Ê´HÙ½[^gîÙÂÛ»3¶>„}ê<ø~×Ú ¬óŒs»æš<ög©ó—×½˜Ûcs…S;S/pL³;Ž9–˜Úyœ€‘ÂâIe£•®¤ÕÎãDŒ>â´"e£=Á’>Æåã±ÎCž „F뼞í<£Y8ʳHÙ½[^eîÕÂ×»3¶>„é%-øý®µXçã#vÍ5^Ø’®{1¶Çæ %¦v'^à˜fw&s,1µó8ý"…Ä“Ë F+]I«Çi)|ÄiEÊ F{‚%mŒËÇc‡<ÖyÛyÆÁp”„‘²{·¼Ý1†3"vgl}ÇÔyðý®µXç#vÍ5yìItþòºó`{l®PbjçqVŽivgÂ1ÇS;s3Rø@<é± b´Ò•´Úyœ£‘ÂGœV¤ b´'XRÕ¸|<ÖyhÀ³Ð \¾8¯_ù­û.Ï‹Åyk¾ŸÑ;åw¤ìÞ-¯nwŒâáŒãÝ[+¡¯„ïw­½ÂÓ˜±k-™Ç^ “dy°=6W(1µ19áÇ4»3á˜c‰©Éi)| žôX1ZéJZmLNÿHá#N+R1Ú,i\>kL4àÙ@hû¢¯o{½êp\v¥y¤ìÞ-/rwŒéáŒêÝ[Oª¾¾ßµ6ë<#|`Ä®µ&{%Lr>æÁöØ\¡ÄÔÎã¼Óì΄cŽ%¦vg¤ðxÒcÄh¥+iµó8 $…8­HÄhO°¤ rùx¬óЀg¡€:/²g¬¡¬Ž”ÝËò va´g¼ìÎØzRÓ÷^Áïw­ÍÀ:Ϩ±k­‰‡¾KºîÅ<Ø›+”˜úš9»Ç4»3á˜c‰©ß“™â´"e£=Á’j‡y<ÔyhÀ³Ð`7°gÔ¡ÔŽ”ÝËòºuaÔ1jvgl Ò •ñû]k3°Î3jFìZk *§ë^Ìƒí±¹B‰©Ç©8¦Ù ÇKLíâ´"e£=Á’†ÇòøM¹2ï7æCc^¬ YÄÄS:HÊîýòZwÏè Þè Ø±1`H:~¿k­VFÁˆ´‘‘‚L:È<Ø›+”˜Zœ‚cšÝ™p̱ÄÔ‚ät>Oz,ƒ­t%­$§ƒ¤ð§)ƒí –ÔA–Ço*È•y¿1óbɺ#Þ¸#žrGRvï—Æ{ÆñÆÁîŒCrGðû]k°‚4îF줌drGæÁöØ\¡ÄÔ‚äÜÓì΄cŽ%¦$玤ðxÒcÄh¥+iµ 9w$…8­HÄhO°¤;²<~SA®ÌûùИ7\þ|áaÝ÷4çíŠóV|ÏAo4Oi*)»÷Ëkð=£©x£©`wÆÖüé勸ý®µ„X½M#vÒFFê5i*ó`{l®Pbj½rš ŽivgÂ1ÇSë•ÓTRø@<é± b´Ò•´Z¯œ¦’ÂGœV¤ b´'XRSY¿©^WæýÆ|hÌocmÈ·±öÆiñ”Ó’²{¿¼`ß3N‹7N vgl ا×:â÷»ÖaiœŒØI)Èä´Ìƒí±¹B‰©É9-8¦Ù ÇKL-HÎiIáñ¤Ç2ˆÑJWÒjArNK qZ‘2ˆÑž`I§eyü¦‚\™÷ó¡1/V=[F€ñ”“²{¿¼ºß3Œ7 vgl اFâ÷»ÖaiŒØI)È$ÀÌƒí±¹B‰©É 08¦Ù ÇKL-HN€Iáñ¤Ç2ˆÑJWÒjArL qZ‘2ˆÑž`Ifyü¦‚\™÷ó¡1/V[Æ–ñ”-“²{¿¨ž±e¼±e°;ccÀ>½l¿ßµÖ+HcË`ÄNÚÈHA&[flÍJL-HΖÁ1ÍîL8æXbjAr¶L ˆ'=–AŒVº’V ’³eRøˆÓŠ”AŒöKÚ2Ëã7äʼߘy±‚Ù‚4j§Ôš”ÝûÅðŒZãZƒÝöú*Jø~×Z#¬ Zƒ;i##™Ôšy°=6W(1µ 9µÇ4»3á˜c‰©É©5)| žôX1ZéJZ-HN­Iá#N+R1Ú,©Öø•â‹lÌûùИ+È[F¼ñ”x“²{¿Xžo¼o°;ccÀ^_E ßïZk„¤o0b'md¤ “x3¶Çæ %¦$'Þà˜fw&s,1µ 9ñ&…Ä“Ë F+]I«ɉ7)|ÄiEÊ F{‚%ſ҃‘y¿1óbÙ‚4N <œ”݇E2Œ‡ã‡ƒÝöéU”øý®µFXA#vÒFF 2y8ó`{l®Pb¦‚1[«ó8¦Ù ÇKÌT ¦Yžñ¤Ç2ˆÑJWÒ¦‚ÄhÅ,Χ)ƒíØ@z8a£‡³6ï7æCc^¨ M)È`<œ@y8)»‹dçt§$åá\اWQâ÷»ÖAy"Ö‚ä<œ(ÈtÝ‹y°=6W(1µ 9Ç4»3á˜c‰©Éy8)| žôX1ZéJZ-HÎÃIá#N+R1Ú,éá„Îڼߘy±‚tlA'PNÊîÃ"ÆÃ ÆÃÁîŒûôíºñû]k°‚4F줌dòpæÁöØ\¡ÄÔ‚ä<Óì΄cŽ%¦$çá¤ðxÒcÄh¥+iµ 9'…8­HÄhO°¤‡6z8kó~c>4æÅ RØ‚4N <œ”݇E2Œ‡Œ‡ƒÝöé{{ã÷»Öai<ŒØI)ÈäáÌƒí±¹B‰©Éy88¦Ù ÇKL-HÎÃIáñ¤Ç2ˆÑJWÒjArN qZ‘2ˆÑž`I'lôpÖæýÆ|hÌ‹¤g Ò˜42iRvM 0&M0& vgl Ø'“¿ßµÖ+HcÒ`ÄNÚÈHA&“flÍJL-HΤÁ1ÍîL8æXbjAr&M ˆ'=–AŒVº’V ’3iRøˆÓŠ”AŒöKš4a£I³6ï¯çdÞИ+HÖ¤ Ƥ ”I“²û°h1i‚1i°;ccÀ!™4øý®µFXA“#vÒFF 2™4ó`{l®PbjAr& ŽivgÂ1ÇS ’3iRø@<é± b´Ò•´ZœI“ÂGœV¤ b´'XÒ¤ MšF*8¿1óbÉš4Á˜42iRvM 0&M0& vgl 8$“¿ßµÖ+HcÒ`ÄNÚÈHA&“flÍJL-HΤÁ1ÍîL8æXbjAr&M ˆ'=–AŒVº’V ’3iRøˆÓŠ”AŒöKš4¡6Y ‚’y¿1óbÉš4Á˜42iRvM 0&M0& vgl 8$“¿ßµÖ+HcÒ`ÄNÚÈHA&“flÍJL-HΤÁ1ÍîL8æXbjAr&M ˆ'=–AŒVº’V ’3iRøˆÓŠ”AŒöKš4¡6Y¸‚\™÷ó¡1/V¬IŒI(“&e÷aÑ ¯ËwåZ”Is9àLü~×Z#¬ Iƒ;i##™Lšy°=6W(1µ 9“Ç4»3á˜c‰©É™4)| žôX1ZéJZ-HΤIá#N+R1Ú,iÒ„Údá reÞȯƼXA²&M0&M Lš”݇EŒIŒIƒÝɤÁïw­5 Ҙ4±“62Rɤ™Ûcs…S ’3ipL³;Ž9–˜ZœI“ÂâIe£•®¤Õ‚äLš>â´"e£=Á’&M¨M® WæýÆ|hÌ‹$kÒcÒô”I“²û~ÑzƤ ƤÁdÒà÷»ÖaiLŒØI)ÈdÒÌƒí±¹B‰™ Äl­Îã˜fw&s,1SA‚˜fyÄ“Ë F+]I› £³8GœV¤ b´`{Ò¤ék“…*ȵy¿1óBiHAöƤé)“&e÷ý¢ ôŒIsºS ’2i.’IƒßïZkä‰X ’3i d  Óu/æÁöØ\¡ÄÔ‚äLÓì΄cŽ%¦$gÒ¤ðxÒcÄh¥+iµ 9“&…8­HÄhO°¤IÓ×& W+ó~c>4æÅ ’5izcÒô”I“²û~ÑzƤéIƒÝɤÁïw­5 Ҙ4±“62Rɤ™Ûcs…S ’3ipL³;Ž9–˜ZœI“ÂâIe£•®¤Õ‚äLš>â´"e£=Á’&M_›,\A®ÌûùИ+HÖ¤éIÓS&MÊîûE蓦7& vgl 8$“¿ßµÖ+HcÒ`ÄNÚÈHA&“flÍJL-HΤÁ1ÍîL8æXbjAr&M ˆ'=–AŒVº’V ’3iRøˆÓŠ”AŒöKš4}m²p¹2ï7æCc^¬ Y“¦7&MO™4)»ïM gLšÞ˜4ر1àLü~×Z#¬ Iƒ;i##™Lšy°=6W(1µ 9“Ç4»3á˜c‰©É™4)| žôX1ZéJZ-HΤIá#N+R1Ú,iÒô+MÙ˜÷ó¡1/V¬IÓ“¦§Lš”Ý÷‹&Ð3&MoLìÎØpL& ~¿k­VƤÁˆ´‘‘‚L&Í<Ø›+”˜ZœIƒcšÝ™p̱ÄÔ‚äLš>Oz,ƒ­t%­$gÒ¤ð§)ƒí –4iú•&‹lÌûùИ+HÖ¤éIÓS&MÊîûE蓦7& vgl 8&“¿ßµÖ+HcÒ`ÄNÚÈHA&“flÍJL-HΤÁ1ÍîL8æXbjAr&M ˆ'=–AŒVº’V ’3iRøˆÓŠ”AŒöKš4ýF“fmÞȯƼXA²&MoLšž2iRvß/š@Ϙ4½1i°;ccÀ1™4øý®µFXA“#vÒFF 2™4ó`{l®PbjAr& ŽivgÂ1ÇS ’3iRø@<é± b´Ò•´ZœI“ÂGœV¤ b´'XÒ¤é7š4kó~c>4æÅ ’5izcÒô”I“²û~ÑzƤéIƒÝŽÉ¤Áïw­5 Ҙ4±“62Rɤ™Ûcs…S ’3ipL³;Ž9–˜ZœI“ÂâIe£•®¤Õ‚äLš>â´"e£=Á’&M¿Ñ¤Y›÷ó¡1/V¬IÓ“¦§Lš”Ý÷‹&Ð3&MoLìÎØpL& ~¿k­VƤÁˆ´‘‘‚L&Í<Ø›+”˜ZœIƒcšÝ™p̱ÄÔ‚äLš>Oz,ƒ­t%­$gÒ¤ð§)ƒí –4iú&Íڼߘy±‚dMšÞ˜4eÒ¤ì~X41izcÒ`wÆÆ€c2iðû]k°‚4& F줌d2iæÁöØ\¡ÄL b¶VçqL³;Ž9–˜© AL³<âIe£•®¤M‰ÑŠYœ#N+R1Ú°iÒ Mšµy=‘ÿæóBiHAƤ(“&e÷â ŒIsºS ’2i.“IƒßïZkä‰X ’3i d  Óu/æÁöØ\¡ÄÔ‚äLÓì΄cŽ%¦$gÒ¤ðxÒcÄh¥+iµ 9“&…8­HÄhO°¤I3l4iy¨àüÆ|hÌ‹$kÒ Æ¤(“&e÷â ŒI3“»36“IƒßïZk„¤1i0b'md¤ “I3¶Çæ %¦$gÒà˜fw&s,1µ 9“&…Ä“Ë F+]I«É™4)|ÄiEÊ F{‚%Mš¡6Y ‚’y¿1óbÉš4ƒ1iʤIÙý°hcÒ Æ¤ÁîŒÇdÒà÷»ÖaiLŒØI)ÈdÒÌƒí±¹B‰©É™48¦Ù ÇKL-HΤIáñ¤Ç2ˆÑJWÒjAr&M qZ‘2ˆÑž`I“f¨M® WæýÆ|hÌ‹$kÒ Æ¤(“&e÷â @_—ïÊ;µ )“ærÀ1™4øý®µFXA“#vÒFF 2™4ó`{l®PbjAr& ŽivgÂ1ÇS ’3iRø@<é± b´Ò•´ZœI“ÂGœV¤ b´'XÒ¤j“…+È•y¿1óbÉš4ƒ1iʤIÙý°hcÒ Æ¤ÁîŒwɤÁïw­5 Ҙ4±“62Rɤ™Ûcs…S ’3ipL³;Ž9–˜ZœI“ÂâIe£•®¤Õ‚äLš>â´"e£=Á’&ÍP›,\A®ÌûùИw·üW‰wwßÝÜÿDþiüÇŸþ$ü4ýƒ4æÝ=&õ­Àc2Åp\$åá¤ì~X$ƒñpãá`wÆÖ€éU”øý®µFXA#vÒFF 2y8ó`{l®PbjArŽivgÂ1ÇS ’ópRø@<é± b´Ò•´Zœ‡“ÂGœV¤ b´'XÒÃj†+È•y¿1ób9²i<œòpRv?,’ÁÀx8ƒñp°;ck@}%|¿k­VÆÃÁˆ´‘‘‚LÎ<Ø›+”˜Zœ‡ƒcšÝ™p̱ÄÔ‚ä<œ>Oz,ƒ­t%­$çá¤ð§)ƒí –ôp†Úƒá reÞȯƼXAîØ‚4Î@y8)»É``<œÁx8ر5 ¾Š¾ßµÖ+Hãá`ÄNÚÈHA&glÍJL-HÎÃÁ1ÍîL8æXbjArN ˆ'=–AŒVº’V ’ópRøˆÓŠ”AŒöKz8CíÁp¹2ï7æCc^¬ #[ÆÃ)'e÷ã"ŒŒ‡3»3¶L¯¢Äïw­5 Òx8±“62RÉÙÛcs…3$ˆÙ\ìU”ÉÃÁ1Ç3$ˆi–ç@<é± b´Ò•´© 1Z1‹sÄiEÊ Fûv$=œq¥#ó~c>4æ… Ò‚‡3RNÊîÇE2çt§$åá˜Ó«(ñû]k ‚<kArN dºîÅ<Ø›+”˜Zœ‡ƒcšÝ™p̱ÄÔ‚ä<œ>Oz,ƒ­t%­$çá¤ð§)ƒí –ôpÆ•ŒlÌûùИ+HǤñpFÊÃIÙý¸H#ãáŒÆÃÁÓ«(ñû]k°‚4F줌dòpæÁöØ\¡ÄÔ‚ä<Óì΄cŽ%¦$çá¤ðxÒcÄh¥+iµ 9'…8­HÄhO°¤‡3nôpÖæýÆ|hÌ‹¤°i<œ‘òpRv?.’ÁÈx8£ñp°;ccÀ˜^E‰ßïZk„¤ñp0b'md¤ “‡3¶Çæ %¦$çáà˜fw&s,1µ 9'…Ä“Ë F+]I«Éy8)|ÄiEÊ F{‚%=œq£‡³6ï7æCc^¬ =[ÆÃ)'e÷ã"ŒŒ‡3»36Œéû‘ã÷»Öai<ŒØI)ÈäáÌƒí±¹B‰©Éy88¦Ù ÇKL-HÎÃIáñ¤Ç2ˆÑJWÒjArN qZ‘2ˆÑž`IgÜèá¬ÍûùИ+ÈÀ¤ñpFÊÃIÙý¸H#ãáŒÆÃÁîŒcú~äøý®µFXA#vÒFF 2y8ó`{l®PbjArŽivgÂ1ÇS ’ópRø@<é± b´Ò•´Zœ‡“ÂGœV¤ b´'XÒÃ7z8kó~c>4æÅ ²g Ò˜4#eÒ¤ì~\4‘1iFcÒ`wÆÆ€1™4øý®µFXA“#vÒFF 2™4ó`{l®PbjAr& ŽivgÂ1ÇS ’3iRø@<é± b´Ò•´ZœI“ÂGœV¤ b´'XÒ¤7š4kó~c>4æÅ ’5iFcÒŒ”I“²ûqÑFƤIƒÝÆdÒà÷»ÖaiLŒØI)ÈdÒÌƒí±¹B‰©É™48¦Ù ÇKL-HΤIáñ¤Ç2ˆÑJWÒjAr&M qZ‘2ˆÑž`I“fÜhÒ¬ÍûùИ+HÖ¤I3R&MÊîÇE“f4& vgl “IƒßïZk„¤1i0b'md¤ “I3¶Çæ %¦$gÒà˜fw&s,1µ 9“&…Ä“Ë F+]I«É™4)|ÄiEÊ F{‚%Mšq£I³6ï7æCc^¬ Y“f4&ÍH™4)»M`dLšÑ˜4ر1`L& ~¿k­VƤÁˆ´‘‘‚L&Í<Ø›+”˜ZœIƒcšÝ™p̱ÄÔ‚äLš>Oz,ƒ­t%­$gÒ¤ð§)ƒí –4iÆ&Íڼߘy±‚dMšÑ˜4;ʤIÙýnÑvŒI3“»36ŒÉ¤Áïw­5 Ҙ4±“62Rɤ™Ûcs…3$ˆÙZÇ1ÍîL8æXb¦‚1Íòˆ'=–AŒVº’6$F+fqŽ8­HÄh?ÀîH“f·Ñ¤Y›÷ó¡1/T&€äΘ4;ʤIÙýnÑvŒIsºS ’2i.ŒÉ¤Áïw­5‚ òD¬É™42Péºó`{l®PbjAr& ŽivgÂ1ÇS ’3iRø@<é± b´Ò•´ZœI“ÂGœV¤ b´'XÒ¤Ùm4iÖæýÆ|hÌ‹$kÒìŒI³£Lš”ÝïM`ǘ4;cÒ`wÆÆ€1™4øý®µFXA“#vÒFF 2™4ó`{l®PbjAr& ŽivgÂ1ÇS ’3iRø@<é± b´Ò•´ZœI“ÂGœV¤ b´'XÒ¤Ùm4iÖæýÆ|hÌ‹$kÒìŒI³£Lš”ÝïM`ǘ4;cÒ`wÆÆ€®K* àZ{„5¤Qi0d'W˜‘ŠL.Í<Ù,”œZ‘œKCpšõ™pαäÔŽädš>O{,ƒ­t%­v$'Ó¤ð§)ƒí –”ivešµy¿1óbÉÊ4;#Óì(™&e÷»ÅØ12ÍÎÈ4ر1 ë’Mƒ¸Öail ÙÉf¤#“N3O¶Ç %§v$§Óœf}&œs,9µ#9Ÿ&…ÄÓË F+]I«Éù4)|ÄiEÊ F{‚%}šÝFŸfmÞȯƼXG²>ÍÎø4;ʧIÙýn‘vŒO³3> vgl èº$ÔவGXG¡Cvr…éÈdÔÌ“í±ÁBÉ©É5§YŸ çKNíHN©Iáñ´Ç2ˆÑJWÒjGrJM qZ‘2ˆÑž`I¥f·Q©Y›÷ó¡1/Ö‘¬R³3JÍŽRjRv¿[|£ÔìŒRƒÝº.958€kíÖ‘Æ©Á\aF:2I5ód{l°PrjGrR ÁiÖgÂ9Ç’S;’³jRø@<í± b´Ò•´Ú‘œU“ÂGœV¤ b´'XÒªÙm´jÖæýÆ|hÌ‹u$kÕìŒU³£¬š”Ýïe`ÇX5;cÕ`wÆÆ€®KZ àZ{„u¤Ñj0d'W˜‘ŽL^Í<Ù,”œÚ‘œWCpšõ™pαäÔŽäÄš>O{,ƒ­t%­v$'Ö¤ð§)ƒí –kvÅšµy¿1óbÉŠ5;#Öì(±&e÷»ÅØ1bÍΈ5ر1 ë’Yƒ¸ÖaiÌ ÙÉf¤#“Z3O¶Ç %§v$§Öœf}&œs,9µ#9·&…ÄÓË F+]I«ɹ5)|ÄiEÊ F{‚%ÝšÝF·fmÞȯƼXG²nÍθ5;Ê­IÙýnvŒ[³3n vgl èº$×வGXG¹Cvr…éÈd×Ì“í±ÁBÉ©ÉÙ5§YŸ çKNíHN¯Iáñ´Ç2ˆÑJWÒjGrzM qZ‘2ˆÑž`I½f·Q¯Y›÷ó¡1/Ö‘¬^³3zM¤ôš”ÝÇňŒ^³3z vgl èºä×வGXG¿Cvr…éÈ$ØÌ“í±ÁBÉ™:äl-Ïpšõ™pαäL ršý9O{,ƒ­t%mêHŒVÌêqZ‘2ˆÑ~€¤a76kó~c>4æ…:ÒŽŒÆ°‰”a“²û¸è‘1lNwjGR†Í倮KŠ àZ{uä Y;’SlJf #Ó}/æÉöØ`¡äÔŽä‚ӬτsŽ%§v$'Ù¤ðxÚcÄh¥+iµ#9É&…8­HÄhO°¤d7J6kó~c>4æÅ:’•l¢‘l"%Ù¤ì>.Ad$›h$ìÎØÐuɲÁ\k°Ž4– †ìä 3Ò‘I³™'Ûcƒ…’S;’ÓlN³>Î9–œÚ‘œg“Ââie£•®¤ÕŽä<›>â´"e£=Á’žMÜèÙ¬Íûëy'È€ ±’dE›hD›H‰6)»‹BÑ&Ñ»36t.‰68€k-V’F´Á\aFJ2‰6ód{l°PrjIr¢ ÁiÖgÂ9Ç’SK’mRø@<í± b´Ò•´Z’œh“ÂGœV¤ b´'XR´‰E›F+9¿õ€Ð˜kIVµ‰Fµ‰”j“²û¸H‘Qm¢Qm°;cc@ç’jƒ¸Ö&a-iT ÙÉf¤%“j3O¶Ç %§¶$§Úœf}&œs,9µ%9Õ&…ÄÓË F+]I«-É©6)|ÄiEÊ F{‚%U›X«.XIÉÖüÖBcd¬&YÛ&Û&R¶MÊîãâDƶ‰Æ¶ÁîŒK¶ àZ«„Õ¤±m0d'W˜‘šL¶Í<Ù,”œZ“œmCpšõ™pαäÔšäl›>O{,ƒ­t%­Ö$gÛ¤ð§)ƒí –´mbm»5¹ö¿õ€Ð«IV¸‰F¸‰”p“²û¸¨ÐWé»òN­IJ¸¹й$ÜவJXMáCvr…©É$ÜÌ“í±ÁBÉ©5É 7§YŸ çKN­IN¸Iáñ´Ç2ˆÑJWÒjMrÂM qZ‘2ˆÑž`Iá&Ö Y“kð[‘±šd›hœ›H97)»‹Mç&ç»36t.978€k­V“ƹÁ\aFj297ód{l°PrjMrÎ ÁiÖgÂ9Ç’Sk’snRø@<í± b´Ò•´Z“œs“ÂGœV¤ b´'XÒ¹‰µóBÖäÚüÖBcd¬&Yí&í&RÚMÊîã"DF»‰F»ÁîŒKÚ àZ«„Õ¤Ñn0d'W˜‘šLÚÍ<Ù,”œZ“œvCpšõ™pαäÔšä´›>O{,ƒ­t%­Ö$§Ý¤ð§)ƒí –Ônb­½5¹ö¿õ€Ð«IÖ¼‰Æ¼‰”y“²û¸8‘1o¢1o°;cc@ç’yƒ¸Ö*a5iÌ ÙÉf¤&“y3O¶Ç %§Ö$gÞœf}&œs,9µ&9ó&…ÄÓË F+]I«5É™7)|ÄiEÊ F{‚%Í›X›/dM®=Ào= 4FÆj’•o¢‘o\GÙ7)¼ŸCó ÌÿÏ4¥ñoÀkccHç’€Ã0¸ÖBaeiÚÉl¤-“ƒ³ ·g %jêKµµF?€jibPÇ5U&Šj6é@=ÿ±Š‚ÈÒ•È©7Ad1ktdEª(ˆüxùFÊT{¦À¦ú\‚ß|Bh 5¨M ªßÿû¢C);GÓó³éÒ60‚ÎùâÜ¢”¢cun§5ŠS¸æjA=zÏEʉ:9Фzå‹eÀ=8_¨hs—rºCkWjbhÇŠ6×)'íhü@-B¬³ µtunTNÞÑø‘¡©³ õštxR`c§®=Áo>!´Æ;•uyôû…_t*eóhz~6%­#ôœ/ÎJ)=fPç¢v*Náš«vª³Ê‰=9Ô©N;U–ÏJî9ÓæNåô†Ö®ÔÄÐŽmîTNòÑøZ„XgAjé*êÜ©œì£ñ#C-RgAê34éü¤ÀÆN]{‚ß|Bh v*«þè÷¿èTJþÑôülú´Œÿs¾8w*e™AtÚ©8…k®Ø©b;•ó€*r¨SE;Õ/Ÿ9” t¦ÍÊÙ@ ­]©‰¡+ÚÜ©œ¤ñµ±Î‚ÔÒUÔ¹S97HãG†Z¤Î‚ÔghRJºÕZBh v*+ é÷#¿èTJÒôül†´Œ-t¾8w*å ™A8íTœÂ5W ìTo;•³†*r¨S½vjX>s(sèL›;•s‡Z»RC;V´¹S9ƒHãjb©¥«¨s§r&‘Æ µH©ÏФP”;u«R´þ„ÐìTÖ*Òï_~Ñ©”W¤éùÙìÓ:0jÑùâÜ©”\du"Ú©8…k®Ø©Áv*§UäP§íÔ~ùÌ¡4£3mîTN4bhíJM íXÑæNåt#¨Eˆu¤–®¢ÎÊiG?2Ô"u¤>C“öQ lìÔ­þÑúBkl°SYI¿ßùE§R’¦çgsHëÀxHç‹s§R&’Ô‰×NÅ)\sµÀNím§r>REuj¯:,Ÿ9”“t¦ÍÊYI ­]©‰¡+ÚÜ©œ›¤ñµ±Î‚ÔÒUÔ¹S9GIãG†Z¤Î‚ÔghRUJºUVZBh v*ë+é÷G¿èTÊXÒôülŽiié|qîTJ[2ƒ: Ú©8…k®Ø©ƒíTN^ªÈ¡N´SÇå3‡˜Î´¹S9…‰¡µ+51´cE›;•™4~ !ÖYZºŠ:w*'4iüÈP‹ÔYú MzM)°±S·šMëO­±ÁNeå&ý~êJéMšžŸÍ]ZÆp:_œ;•rœÌ NzíTœÂ5W ìÔÑv*g:UäP§ŽÚ©»å3‡²Î´¹S9߉¡µ+51´cE›;•³ž4~ !ÖYZºŠ:w*g?iüÈP‹ÔYú MJP)°±S·jPëO­±ÁNeM(ýþëJ¹PšžŸÍ˜ÖÑ¡ÎçN¥„(3¨“A;§pÍÕ;ug;•Ó¢*r¨SwÚ©qù̡Ԩ3mîTNŽbhíJM íXÑæNå)¨Eˆu¤–®¢ÎÊ©R?2Ô"u¤>C“ÆT lìÔ­ÎÔúBkl°SYmJ¿_û¹SåMiz?§–upŒ8u¾X;»8¶u¢êAáš«vª•§0p'×È¡NU}Ê-¶ 6_¨hµSAÚæBý­]©‰¡+ZíTÖîÔZ„XgAjé*jíTŒZìBj‘: RŸ ëQ¹ÍÕêüæBkl¬SMêTg=*ÇyTN=*—GyT§‹s§rÕå óGU;§pÍÕÂ:õž;•ô¨Jr¤SzTn±e°ùBE›;•ô¨Z»RC;V´¹SIÊ© Å,B¬³ µtuîTÒ£rêBÔ"u¤>C³•ÛìQ­>Áo>!´Æ;•ö¨œõ¨çQ9õ¨\R@åQ9ëQaÇÖ NÔ£"(\sµÀNµîä9Ô©êQ¹Å–Áæ mîTÒ£"híJM íXÑæN%=*§.³±Î‚ÔÒUÔ¹SIÊ© EP‹ÔYú ÍzTn³Gµú¿ù„ÐìTÚ£rÖ£rœGåÔ£rIq”Gå¬G…][ƒ:¯Aáš«vªõ¨0p'×È¡NUÊ-¶ 6_¨hs§’AkWjbhÇŠ6w*éQ9u¡˜Eˆu¤–®¢ÎJzTN](‚Z¤Î‚ÔghÖ£r›=ªÕ'øÍ'„ÖØ`§Ò•³•ã<*§•K ˆ£<*g=*ìâØÔyõ¨ ×\-°S­G…;¹FuªzTn±e°ùBE›;•ô¨Z»RC;V´¹SIÊ© Å,B¬³ µtuîTÒ£rêBÔ"u¤>C³•ÛìQ­>Áo>!´Æ;•ö¨œõ¨çQ9õ¨\R@åQ9ëQaÇ֠ΫGEP¸æjj=* ÜÉ5r¨SÕ£r‹-ƒÍ*ÚÜ©¤GEÐÚ•šÚ±¢ÍJzTN](fb©¥«¨s§’•SŠ ©³ õšõ¨Üfjõ ~ó ¡56Ø©´Gå¬Gå8Ê©Gå’â(ÊY »8¶u^=*‚Â5W ìTëQaàN®‘Cª•[ll¾PÑæN%=*‚Ö®ÔÄÐŽmîTÒ£rêB1‹ë,H-]E;•ô¨œºPµH©ÏЬGå6{T«Oð›O­±ÁN¥=*g=*ÇyTN=*—GyTÎzTØÅ±5¨óêQ®¹Z`§Z wrêTõ¨ÜbË`ó…Š6w*éQ´v¥&†v¬hs§’•SŠY„XgAjé*êÜ©¤GåÔ…"¨Eê,H}†f=*·Ù£Z}‚ß|Bh v*íQ9ëQ9ΣrêQ¹¤€8Ê£rÖ£Â.Ž­AWŠ pÍÕ;ÕzT¸“käP§ªGå[›/T´¹SIŠ µ+51´cE›;•ô¨œºPÌ"Ä: RKWQçN%=*§.A-RgAê34ëQ¹ÍÕêüæBkl°SiÊYÊq•SÊ%ÄQ•³vql ê¼zT…k®ة֣ÂÀ\#‡:U=*·Ø2Ø|¡¢ÍJzT­]©‰¡+ÚÜ©¤GåÔ…b!ÖYZºŠ:w*éQ9u¡j‘: RŸ¡YÊmö¨VŸà7ŸZcƒJ{TÎzTÂyTN=*I ˆP•³vql ê¼zT…k®ة֣ÂÀ\#‡:U=*Yll¾PÑj§‚´Í…úZ»RC;V´Ú© ­Ý©µ±Î‚ÔÒUÔÚ©µØ…:2Ô"u¤>A ëQÉfjõ ~ó ¡56Ö©&uªXJ8JÔ£’¤€åQ.ÎÊyT—ƒ:¯Aáš«…uê C³•lö¨VŸà;!"_ž‡ÖØ`§Ò•XJ8JÔ£’¤€åQ‰õ¨°‹ckPÔ£"(\sµÀNµîä9Ô©êQÉbË`ó…Š6w*éQ´v¥&†v¬hs§’•¨ Å,B¬³ µtuîTÒ£u¡j‘: RŸ¡YJ6{T­ Fô›O­±ÁN¥=*±•p•¨G%IÊ£ëQaÇÖ .¨GEP¸æjj=* ÜÉ5r¨SÕ£’Å–Áæ mîTÒ£"híJM íXÑæN%=*QŠY„XgAjé*êÜ©¤G%êBÔ"u¤>C³•4&¨Ïdó ~ó ¡56Ø©´G%Ö£Σõ¨$) ByTb=*ìâØÔõ¨ ×\-°S­G…;¹FuªzT²Ø2Ø|¡¢ÍJzT­]©‰¡+ÚÜ©¤G%êB1‹ë,H-]E;•ô¨D](‚Z¤Î‚ÔghÖ£’†ÃDvêÚüæBkl°SiJ¬G%œG%êQIR@ ØUçNå<ªËA]PŠ pÍÕ;ÕzT¸“käP§ªG%‹-ƒÍ*ÚÜ©¤GEÐÚ•šÚ±¢ÍJzT¢.³±Î‚ÔÒUÔ¹SIJÔ…"¨Eê,H}†f=*i8Ld§®=Áo>!´Æ;•ö¨ÄzTÂyT¢•$D(J¬G…][ƒº Aáš«vªõ¨0p'×È¡NUJ[›/T´¹SIŠ µ+51´cE›;•ô¨D](fb©¥«¨s§’•¨ EP‹ÔYú ÍzTÒp˜ÈN]{‚ß|BhíÂò'Ò»»ïnî"ÿ´ûÇŸþ$ü4ýƒ<}ûÄ]qâî§éäÄáâÄËNöœ‡%êaù¤xÊÃëaaÇöB_ßJP¸æj‚l=, ÜÉ5r¨“ÕÃò‹mƒÍ*ZídöʯoU‹ +ZídÖîÔZ„XgAjé*jídŒZìBj‘: RŸ =ëaù†ÅuòêüæBk쥓/tmä1of¸ˆ˜VåL,¯&–O‰§L¬ÓŹU9ËLÚë+\ ×\.¬UOà¹UI«$GZÕ«‰åß›/T´¹UI‹ µ+51´cE›[•4±¼ÚTÌ"Ä: RKWQçV%M,¯6A-RgAê34kbù†E¶êÚüæBkl´UߪÖÅòœ‹åÕÅòI#ñ”‹å­‹…]›“öúW‚Â5— lUëbaàN®‘C­ª.–_Œl¾PÑæV%],‚Ö®ÔÄÐŽmnUÒÅòêS1‹ë,H-]E[•t±¼úTµH©ÏЬ‹åÙªkOð›O­±ÑV¾U­å9Ë«å“Hâ)Ë[ »86'íõU®…k.ØªÖÆÂÀ\#‡ZUm,¿87Ø|¡¢Í­JÚX­]©‰¡+Úܪ¤åÕ¨b!ÖYZºŠ:·*icy5ªj‘: RŸ¡YË7L(²Uמà7ŸZc£­êùVµ>–ç|,¯>–O*‰§|,o},ìâØœ´××¹®¹\`«Z wrjUõ±übÝ`ó…Š6·*éc´v¥&†v¬hs«’>–W§ŠY„XgAjé*êܪ¤åÕ©"¨Eê,H}†f},¿Ö…’Í'øÍ'„ÖØh«¾U­‘å9#Ë«‘å“Lâ)#Ë[# »86'íõ•®…k.تÖÈÂÀ\#‡ZU,¿x7Ø|¡¢Í­JY­]©‰¡+Úܪ¤‘åÕªb!ÖYZºŠ:·*idyµªj‘: RŸ¡Y#˯µ¡dó ~ó ¡56Úª=ߪÖÉòœ“åÕÉòI'ñ”“å­“…]›“öúZW‚Â5— lUëdaàN®‘C­ªN–_Ìl¾PÑæV%,‚Ö®ÔÄÐŽmnUÒÉòêU1‹ë,H-]E[•t²¼zUµH©ÏЬ“å7;Y«Oð›O­±ÑVøVµV–ç¬,¯V–OB‰§¬,o­,ìâØœ´×W»®¹\`«Z+ wrjUµ²üâÞ`ó…Š6·*ie´v¥&†v¬hs«’V–W³ŠY„XgAjé*êܪ¤•åÕ¬"¨Eê,H}†f­,¿ÙÊZ}‚ß|Bh¶êÈ·ªõ²<çeyõ²|RJ<åeyëeaÇæ¤½þÜ‚Â5— lUëeaàN®‘C­ª^–_ìl¾PÑæV%½,‚Ö®ÔÄÐŽmnUÒËòêV1‹ë,H-]E[•ô²¼ºUµH©ÏЬ—å7{Y«Oð›O­±ÑVÝñ­jÍ,Ï™Y^Í,Ÿ¤O™YÞšYØÅ±9i¯?9€ pÍå[ÕšY¸“käP«ª™åÿ›/T´¹UI3‹ µ+51´cE›[•4³¼ÚUÌ"Ä: RKWQçV%Í,¯vA-RgAê34kfùÍfÖêüæBkl´U#ߪ֭ œ[åÕ­ I ”[å­[…]›“öêV®¹\`«Z· wrjUu«ÂbÐ`ó…ŠV[¤moÔã´v¥&†v¬hµUAZ»Sjb©¥«¨µU1j± ud¨Eê,H}‚¬[6»U«Oð›O­±ÁVµ¨Uƒu«çVu«BÒBåV.έʹUfÒAÝ*‚Â5— kÕxnUÒ­*É‘V êV…Å Áæ mnUÒ­"híJM íXÑæV%ݪ ~³±Î‚ÔÒUÔ¹UI·*¨EP‹ÔYú ͺUa³[µú¿ù„ÐmUÞ­ Ö­ œ[Ô­ I ”[¬[…]›“êV®¹\`«Z· wrjUu«ÂbÐ`ó…Š6·*éV´v¥&†v¬hs«’nUP?ŠY„XgAjé*êܪ¤[Ô"¨Eê,H}†fݪ°Ù­Z}‚ß|Bh¶*ïVëVέ êV…¤…Ê­ Ö­Â.ŽÍIu« ×\.°U­[…;¹FµªºUa1h°ùBE›[•t«Z»RC;V´¹UI·*¨Å,B¬³ µtunUÒ­ êGÔ"u¤>C³nUØìV­>Áo>!´ÆF[•w«‚u«çVu«BÒBåVëVaÇæ¤ƒºU…k.ت֭ÂÀ\#‡ZUݪ°4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[Ôb!ÖYZºŠ:·*éVõ£j‘: RŸ¡Y·*lv«VŸà7ŸZc£­Ê»UÁºUs«‚ºU!i!r«‚u«°‹csÒAÝ*‚Â5— lUëVaàN®‘C­ªnUX l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­ êG1‹ë,H-]E[•t«‚úQµH©ÏЬ[6»U«Oð›O­±ÑVåݪ`ݪÀ¹UAݪ´@¹UÁºUØÅ±9é nAášË¶ªu«0p'×È¡VU·*, 6_¨hs«’nAkWjbhÇŠ6·*éVõ£˜Eˆu¤–®¢Î­JºUAý(‚Z¤Î‚ÔghÖ­ ›ÝªÕ'øÍ'„ÖØh«ònU°nUàܪ nUHZH Üª`Ý*ìâØœtP·Š pÍå[ÕºU¸“käP«ª[ƒ›/T´¹UI·Š µ+51´cE›[•t«‚úQÌ"Ä: RKWQçV%ݪ ~A-RgAê34ëV…ÍnÕêüæBkl´Uy·*X·*pnUP·*$-$PnU°nvqlN:¨[EP¸ær­jÝ* ÜÉ5r¨UÕ­ ‹AƒÍ*Úܪ¤[EÐÚ•šÚ±¢Í­JºUAý(fb©¥«¨s«’nUP?Š ©³ õšu«Âf·jõ ~ó ¡56Úª¼[¬[8·*¨[’(·*X· »86'Ô­"(\s¹ÀVµnîä9ÔªêV…Å Áæ mnUÒ­"híJM íXÑæV%ݪ ~³±Î‚ÔÒUÔ¹UI·*¨EP‹ÔYú ͺUa³[µú¿ù„ÐmUÞ­ Ö­ê9·*¨[Õ'-¤§Üª`Ý*ìâØœtP·Š pÍå[ÕºU¸“käP«ª[Õ/ 6_¨hµUAÚöF=NkWjbhÇŠV[¤µ;u !ÖYZºŠZ[£»PG†Z¤Î‚Ô'èžu«úÍnÕêüæBkl°UmjÕÞºU=çVõêVõI é)·êtqnUέ2“ŽêV®¹\X«žÀs«’nUIŽ´j¯nU¿4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[Õ«Å,B¬³ µtunUÒ­êÕ"¨Eê,H}†fݪ~³[µú¿ù„ÐmUÞ­ê­[ÕsnU¯nUŸ´žr«zëVaÇæ¤£ºU…k.ت֭ÂÀ\#‡ZUݪ~1h°ùBE›[•t«Z»RC;V´¹UI·ªW?ŠY„XgAjé*êܪ¤[Õ«EP‹ÔYú ͺUýf·jõ ~ó ¡56Úª¼[Õ[·ªçܪ^ݪ>i!=åVõÖ­Â.ŽÍIGu« ×\.°U­[…;¹FµªºUýbÐ`ó…Š6·*éV´v¥&†v¬hs«’nU¯~³±Î‚ÔÒUÔ¹UI·ªW?Š ©³ õšu«úÍnÕêüæBkl´Uy·ª·nUϹU½ºU}ÒBzÊ­ê­[…]›“ŽêV®¹\`«Z· wrjUu«úÅ Áæ mnUÒ­"híJM íXÑæV%ݪ^ý(fb©¥«¨s«’nU¯~A-RgAê34ëVõ›ÝªÕ'øÍ'„ÖØh«ònUoݪžs«zu«ú¤…ô”[Õ[· »86'Õ­"(\s¹ÀVµnîä9ÔªêVõ‹AƒÍ*Úܪ¤[EÐÚ•šÚ±¢Í­JºU½úQÌ"Ä: RKWQçV%ݪ^ý(‚Z¤Î‚ÔghÖ­ê7»U«Oð›O­±ÑVåݪ޺U=çVõêVõI é)·ª·nvqlN:ª[EP¸ær­jÝ* ÜÉ5r¨Uխꃛ/T´¹UI·Š µ+51´cE›[•t«zõ£˜Eˆu¤–®¢Î­JºU½úQµH©ÏЬ[Õov«VŸà7ŸZc£­Ê»U½u«zέêÕ­ê“ÒSnUoÝ*ìâØœtT·Š pÍå[ÕºU¸“käP«ª[Õ/ 6_¨hs«’nAkWjbhÇŠ6·*éVõêG1‹ë,H-]E[•t«zõ£j‘: RŸ¡Y·ªßìV­>Áo>!´ÆF[•w«zëVõœ[Õ«[Õ'-¤§ÜªÞºUØÅ±9é¨nAášË¶ªu«0p'×È¡VU·ª_ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­êÕb!ÖYZºŠ:·*éVõêGÔ"u¤>C³nU¿Ù­Z}‚ß|Bh¶*ïVõÖ­ê9·ªW·ªOZHO¹U½u«°‹csÒQÝ*‚Â5— lUëVaàN®‘C­ªnU¿4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[Õ«Å,B¬³ µtunUÒ­êÕ"¨Eê,H}†fݪ~³[µú¿ù„ÐmUÞ­ê­[5pnU¯nÕ´r«zëVaÇæ¤£ºU…k.ت֭ÂÀ\#‡ZUݪa1h°ùBE«­ Ò¶7êqZ»RC;V´Úª ­Ý©µ±Î‚ÔÒUÔÚªµØ…:2Ô"u¤>A¬[5lv«VŸà7ŸZcƒ­j#P«Ö­8·jP·jHZÈ@¹U§‹s«rn•™t§nAášË…µê <·*éV•äH«êV ‹AƒÍ*Úܪ¤[EÐÚ•šÚ±¢Í­JºUƒúQÌ"Ä: RKWQçV%ݪAý(‚Z¤Î‚ÔghÖ­6»U«Oð›O­±ÑVåݪÁºUçV êV I (·j°nvqlNºS·Š pÍå[ÕºU¸“käP«ª[5, 6_¨hs«’nAkWjbhÇŠ6·*éV êG1‹ë,H-]E[•t«õ£j‘: RŸ¡Y·jØìV­>Áo>!´ÆF[•w«ëV œ[5¨[5$-d ÜªÁºUØÅ±9éNÝ*‚Â5— lUëVaàN®‘C­ªnÕ°4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[5¨Å,B¬³ µtunUÒ­Ô"¨Eê,H}†fݪa³[µú¿ù„ÐmUÞ­¬[5pnÕ nÕ´r«ëVaÇæ¤;u« ×\.°U­[…;¹FµªºUÃbÐ`ó…Š6·*éV´v¥&†v¬hs«’nÕ ~³±Î‚ÔÒUÔ¹UI·jP?Š ©³ õšu«†ÍnÕêüæBkl´Uy·j°nÕÀ¹UƒºUCÒBÊ­¬[…]›“îÔ­"(\s¹ÀVµnîä9ÔªêV ‹AƒÍ*Úܪ¤[EÐÚ•šÚ±¢Í­JºUƒúQÌ"Ä: RKWQçV%ݪAý(‚Z¤Î‚ÔghÖ­6»U«Oð›O­±ÑVåݪÁºUçV êV I (·j°nvqlNºS·Š pÍå[ÕºU¸“käP«ª[5, 6_¨hs«’nAkWjbhÇŠ6·*éV êG1‹ë,H-]E[•t«õ£j‘: RŸ¡Y·jØìV­>Áo>!´ÆF[•w«ëV œ[5¨[5$-d ÜªÁºUØÅ±9éNÝ*‚Â5— lUëVaàN®‘C­ªnÕ°4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[5¨Å,B¬³ µtunUÒ­Ô"¨Eê,H}†fݪa³[µú¿ù„ÐmUÞ­¬[5pnÕ nÕ´r«ëVaÇæ¤;u« ×\.°U­[…;¹FµªºUÃbÐ`ó…Š6·*éV´v¥&†v¬hs«’nÕ ~³±Î‚ÔÒUÔ¹UI·jP?Š ©³ õšu«†ÍnÕêüæBkl´Uy·j°nÕÀ¹UƒºUCÒBÊ­¬[…]›“îÔ­"(\s¹ÀVµnîä9ÔªêV ‹AƒÍ*Úܪ¤[EÐÚ•šÚ±¢Í­JºUƒúQÌ"Ä: RKWQçV%ݪAý(‚Z¤Î‚ÔghÖ­6»U«Oð›O­±ÑVåݪÁºU#çV êVI )·j°nvqlNºS·Š pÍå[ÕºU¸“käP«ª[5. 6_¨hµUAÚöF=NkWjbhÇŠV[¤µ;u !ÖYZºŠZ[£»PG†Z¤Î‚Ô'è‘u«ÆÍnÕêüæBkl°UmjÕѺU#çVêVI )·êtqnUέ2“Fu« ×\.¬UOà¹UI·ª$GZuT·j\ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­Õb!ÖYZºŠ:·*éVêGÔ"u¤>C³nÕ¸Ù­Z}‚ß|Bh¶*ïVÖ­9·jT·jLZÈH¹U£u«°‹csÒ¨nAášË¶ªu«0p'×È¡VU·j\ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­Õb!ÖYZºŠ:·*éVêGÔ"u¤>C³nÕ¸Ù­Z}‚ß|Bh¶*ïVÖ­9·jT·jLZÈH¹U£u«°‹csÒ¨nAášË¶ªu«0p'×È¡VU·j\ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­Õb!ÖYZºŠ:·*éVêGÔ"u¤>C³nÕ¸Ù­Z}‚ß|Bh¶*ïVÖ­9·jT·jLZÈH¹U£u«°‹csÒ¨nAášË¶ªu«0p'×È¡VU·j\ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­Õb!ÖYZºŠ:·*éVêGÔ"u¤>C³nÕ¸Ù­Z}‚ß|Bh¶*ïVÖ­9·jT·jLZÈH¹U£u«°‹csÒ¨nAášË¶ªu«0p'×È¡VU·j\ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­Õb!ÖYZºŠ:·*éVêGÔ"u¤>C³nÕ¸Ù­Z}‚ß|Bh¶*ïVÖ­9·jT·jLZÈH¹U£u«°‹csÒ¨nAášË¶ªu«0p'×È¡VU·j\ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­Õb!ÖYZºŠ:·*éVêGÔ"u¤>C³nÕ¸Ù­Z}‚ß|Bh¶*ïVÖ­9·jT·jLZÈH¹U£u«°‹csÒ¨nAášË¶ªu«0p'×È¡VU·j\ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­Õb!ÖYZºŠ:·*éVêGÔ"u¤>C³nÕ¸Ù­Z}‚ß|Bh¶*ïVÖ­9·jT·jLZÈH¹U£u«°‹csÒ¨nAášË¶ªu«0p'×È¡VU·j\ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­Õb!ÖYZºŠ:·*éVêGÔ"u¤>C³nÕ¸Ù­Z}‚ß|Bh¶*ïVÖ­9·jT·jLZÈH¹U£u«°‹csÒ¨nAášË¶ªu«0p'×È¡VU·j\ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­Õb!ÖYZºŠ:·*éVêGÔ"u¤>C³nÕ¸Ù­Z}‚ß|Bh¶*ïVÖ­ÚqnÕ¨nÕ.i!;Ê­­[…]›“Fu« ×\.°U­[…;¹FµªºU»Å Áæ ­¶*HÛÞ¨ÇiíJM íXÑj«‚´v§Ô"Ä: RKWQk«bÔbêÈP‹ÔYú½cݪÝf·jõ ~ó ¡56ت6µêκU;έک[µKZÈŽr«NçVåܪËI¥S·Š pÍåÂZõž[•t«Jr¤UwêV탛/T´¹UI·Š µ+51´cE›[•t«vêG1‹ë,H-]E[•t«vêGÔ"u¤>C³nÕn³[µú¿ù„ÐmUÞ­ÚY·jǹU;u«vI ÙQnÕκUØÅ±5©têV®¹\`«Z· wrjUu«v‹AƒÍ*Úܪ¤[EÐÚ•šÚ±¢Í­JºU;õ£˜Eˆu¤–®¢Î­JºU;õ£j‘: RŸ¡Y·j·Ù­Z}‚ß|Bh¶*ïVí¬[µãܪºU»¤…ì(·jgÝ*ìâØšT:u« ×\.°U­[…;¹FµªºU»Å Áæ mnUÒ­"híJM íXÑæV%ݪúQÌ"Ä: RKWQçV%ݪúQµH©ÏЬ[µÛìV­>Áo>!´ÆF[•w«vÖ­ÚqnÕNݪ]ÒBv”[µ³nvqlM*ºU…k.ت֭ÂÀ\#‡ZUݪÝbÐ`ó…Š6·*éV´v¥&†v¬hs«’nÕNý(fb©¥«¨s«’nÕNý(‚Z¤Î‚ÔghÖ­Úmv«VŸà7ŸZc£­Ê»U;ëVí8·j§nÕ.i!;Ê­ÚY· »8¶&•NÝ*‚Â5— lUëVaàN®‘C­ªnÕn1h°ùBE›[•t«Z»RC;V´¹UI·j§~³±Î‚ÔÒUÔ¹UI·j§~A-RgAê34ëVí6»U«Oð›O­±ÑVåݪu«vœ[µS·j—´åVí¬[…][“J§nAášË¶ªu«0p'×È¡VU·j·4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[µS?ŠY„XgAjé*êܪ¤[µS?Š ©³ õšu«v›ÝªÕ'øÍ'„ÖØh«ònÕκU;έک[µKZÈŽr«vÖ­Â.Ž­I¥S·Š pÍå[ÕºU¸“käP«ª[µ[ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­Ú©Å,B¬³ µtunUÒ­Ú©EP‹ÔYú ͺU»ÍnÕêüæBkl´Uy·jgݪçVíÔ­Ú%-dG¹U;ëVaÇÖ¤Ò©[EP¸ær­jÝ* ÜÉ5r¨UÕ­Ú- 6_¨hs«’nAkWjbhÇŠ6·*éVíÔb!ÖYZºŠ:·*éVíÔ"¨Eê,H}†fݪÝf·jõ þ‘¤G¾D­±ÑVåݪu«vœ[µS·j—´åVí¬[…][“J§nAášË¶ªu«0p'×È¡VU·j·4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[µS?ŠY„XgAjé*êܪ¤[µS?Š ©³ õšu«v›ÝªÆ X'úÍ'„ÖØh«ònÕκU‘s«vêVŤ…DÊ­ÚY· »8¶&•NÝ*‚Â5— lUëVaàN®‘C­ªnU\ l¾PÑj«‚´ÍúZ»RC;V´Úª ­Ý©µ±Î‚ÔÒUÔÚªµØ…:2Ô"u¤>AG֭еׄ5šl>Áo>!´Æ[ÕF VÖ­Šœ[Õ­ŠI ‰”[uº8·*çV]N*NÝ*‚Â5— kÕxnUÒ­*É‘VêVÅÅ Áæ mnUÒ­"híJM íXÑæV%ݪ¨~³±Î‚ÔÒUÔ¹UI·*ªEP‹ÔYú ͺU±öšØV]{‚ß|Bh¶*ïVEëVEέŠêVŤ…@ÿ:°«.έʹU—“ŠS·Š pÍå[ÕºU¸“käP«ª[ƒ›/T´¹UI·Š µ+51´cE›[•t«¢úQÌ"Ä: RKWQçV%ݪ¨~A-RgAê34ëVÅÚkb[uí ~ó ¡56Úª¼[­[9·*ª[“)·*Z· »8¶&§nAášË¶ªu«0p'×È¡VU·*. 6_¨hs«’nAkWjbhÇŠ6·*éVEõ£˜Eˆu¤–®¢Î­JºUQý(‚Z¤Î‚Ôgh֭е×ĶêÚüæBkl´Uy·*Z·*rnUT·*&-$RnU´nvqlM*NÝ*‚Â5— lUëVaàN®‘C­ªnU\ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­ŠêG1‹ë,H-]E[•t«¢úQµH©ÏЬ[k¯‰mÕµ'øÍ'„ÖØh«ònU´nUäܪ¨nULZH¤ÜªhÝ*ìâØšTœºU…k.ت֭ÂÀ\#‡ZUݪ¸4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[Õb!ÖYZºŠ:·*éVEõ£j‘: RŸ¡Y·*Ö^ÛªkOð›O­±ÑVåݪhݪȹUQݪ˜´H¹UѺUØÅ±5©8u« ×\.°U­[…;¹FµªºUq1h°ùBE›[•t«Z»RC;V´¹UI·*ªÅ,B¬³ µtunUÒ­ŠêGÔ"u¤>C³nU¬½&¶Uמà7ŸZc£­Ê»UѺU‘s«¢ºU1i!‘r«¢u«°‹ckRqêV®¹\`«Z· wrjUu«âbÐ`ó…Š6·*éV´v¥&†v¬hs«’nUT?ŠY„XgAjé*êܪ¤[Õ"¨Eê,H}†fݪX{Ml«®=Áo>!´ÆF[•w«¢u«"çVEu«bÒB"åVEëVaÇÖ¤âÔ­"(\s¹ÀVµnîä9ÔªêVÅÅ Áæ mnUÒ­"híJM íXÑæV%ݪ¨~³±Î‚ÔÒUÔ¹UI·*ªEP‹ÔYú ͺUq­×$›Oð›O­±ÑVåݪhݪȹUQݪ˜´H¹UѺUØÅ±5©8u« ×\.°U­[…;¹FµªºUq1h°ùBE›[•t«Z»RC;V´¹UI·*ªÅ,B¬³ µtunUÒ­ŠêGÔ"u¤>C³nU\ë5ÉæüæBkl´Uy·*·J:έJéýœšbþªU[^[“ŠKnCášË¶ªq«@p'×È¡VMnÕ2àœ/T´©UQÚæFý­]©‰¡+ÚÔª(­Ý©µ±Î‚ÔÒUÔ©UAj± ud¨Eê,Hýzùq9T«¦À¦V]‚ß|BhµjAZUæÓE«Rn•¦ççÓ¥…`ܪóŹU)·ÊL*Òi«â®¹\P«žÁs«rnUE´ª^ùbpÎ*Úܪœ[ÅÐÚ•šÚ±¢Í­Ê¹U?P‹ë,H-]E[•s«4~d¨Eê,H}†&ݪØØª[ݪõ'„ÖØh«Òn•þ̧‹V¥Ü*MÏϧ¤…`ܪóŹU)·ÊL*â´Uq ×\.°UmUέªÈ¡VuÚª²|îPnÕ™6·*çV1´v¥&†v¬hs«rn•ÆÔ"Ä: RKWQçVåÜ*j‘: RŸ¡I·*6¶êV·jý ¡56Úª´[¥?óé¢U)·JÓóóéÓB0nÕùâܪ”[e&mUœÂ5— lU±­Ê¹U9Ôª¢­ê—ÏÊ­:ÓæVåÜ*†Ö®ÔÄÐŽmnUÎ­ÒøZ„XgAjé*êܪœ[¥ñ#C-RgAê34éV¥ÀÆVÝêV­?!´ÆF[•v«ôg>]´*åViz~>CZÆ­:_œ[•r«Ì¤"^[§pÍå[ÕÛVåܪŠjU¯­–ÏÊ­:ÓæVåÜ*†Ö®ÔÄÐŽmnUÎ­ÒøZ„XgAjé*êܪœ[¥ñ#C-RgAê34éV¥ÀÆVÝêV­?!´ÆF[•v«ôg>]´*åViz~>û´Œ[u¾8·*åV™IE‚¶*NášË¶j°­Ê¹U9ÔªA[µ_>w(·êL›[•s«Z»RC;V´¹U9·Jãjb©¥«¨s«rn•Æ µH©ÏФ[•«[µþ„ÐmUÚ­ÒŸùtѪ”[¥éùùÒB0nÕùâܪ”[e&éµUq ×\.°U{Ûªœ[U‘C­Úk«ËçåVis«rnCkWjbhÇŠ6·*çViü@-B¬³ µtunUÎ­Òø‘¡©³ õšt«R`c«nu«ÖŸZc£­J»Uú3Ÿ.Z•r«4=?ŸcZÆ­:_œ[•r«Ì¤"ƒ¶*NášË¶ê`[•s«*r¨UmÕqùܡܪ3mnUέbhíJM íXÑæVåÜ*¨Eˆu¤–®¢Î­Ê¹U?2Ô"u¤>C“nU llÕ­nÕúBkl´Ui·JæÓE«Rn•¦ççs—‚q«ÎçV¥Ü*3©È¨­ŠS¸ær­:ÚVåܪŠjÕQ[u·|îPnÕ™6·*çV1´v¥&†v¬hs«rn•ÆÔ"Ä: RKWQçVåÜ*j‘: RŸ¡I·*6¶êV·jý ¡56Úª´[¥?óé¢U)·JÓóóÓB0nÕùâܪ”[e&Ùi«â®¹\`«îl«rnUEµêN[5.Ÿ;”[u¦Í­Ê¹U ­]©‰¡+Úܪœ[¥ñµ±Î‚ÔÒUÔ¹U9·JãG†Z¤Î‚ÔghÒ­J­ºÕ­ZBh¶*íVéÏ|:·ª£Ü*MïçÔ²Žq«Îk«bÇÖ¤"êV®¹\`«Z· wrjUu«ÜbÐ`ó…ŠV[¤mnÔÐÚ•šÚ±¢ÕViíN¨Eˆu¤–®¢ÖVŨÅ.Ô‘¡©³ õ Ú±n•ÛìV­>Áo>!´Æ[ÕF VuÖ­rœ[åÔ­rI q”[uº8·*çV]N*^Ý*‚Â5— kÕxnUÒ­*É‘VuêV¹Å Áæ mnUÒ­"híJM íXÑæV%Ý*§~³±Î‚ÔÒUÔ¹UI·Ê©EP‹ÔYú ͺUn³[µú¿ù„ÐmUÞ­rÖ­rœ[åÔ­rI q”[å¬[…][“ŠW·Š pÍå[ÕºU¸“käP«ª[僛/T´¹UI·Š µ+51´cE›[•t«œúQÌ"Ä: RKWQçV%Ý*§~A-RgAê34ëV¹ÍnÕêüæBkl´Uy·ÊY·Êqn•S·Ê%-ÄQn•³nvqlM*^Ý*‚Â5— lUëVaàN®‘C­ªn•[ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­rêG1‹ë,H-]E[•t«œúQµH©ÏЬ[å6»U«Oð›O­±ÑVåÝ*gÝ*ǹUNÝ*—´G¹UκUØÅ±5©xu« ×\.°U­[…;¹FµªºUn1h°ùBE›[•t«Z»RC;V´¹UI·Ê©Å,B¬³ µtunUÒ­rêGÔ"u¤>C³n•ÛìV­>Áo>!´ÆF[•w«œu«çV9u«\ÒBåV9ëVaÇÖ¤âÕ­"(\s¹ÀVµnîä9ÔªêV¹Å Áæ mnUÒ­"híJM íXÑæV%Ý*§~³±Î‚ÔÒUÔ¹UI·Ê©EP‹ÔYú ͺUn³[µú¿ù„ÐmUÞ­rÖ­rœ[åÔ­rI q”[å¬[…][“ŠW·Š pÍå[ÕºU¸“käP«ª[僛/T´¹UI·Š µ+51´cE›[•t«œúQÌ"Ä: RKWQçV%Ý*§~A-RgAê34ëV¹ÍnÕêüæBkl´Uy·ÊY·Êqn•S·Ê%-ÄQn•³nvqlM*^Ý*‚Â5— lUëVaàN®‘C­ªn•[ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­rêG1‹ë,H-]E[•t«œúQµH©ÏЬ[å6»U«Oð›O­±ÑVåÝ*gÝ*ǹUNÝ*—´G¹UκUØÅ±5©xu« ×\.°U­[…;¹FµªºUn1h°ùBE›[•t«Z»RC;V´¹UI·Ê©Å,B¬³ µtunUÒ­rêGÔ"u¤>C³n•ÛìV­>Áo>!´ÆF[•w«œu«çV9u«\ÒBåV9ëVaÇÖ¤âÕ­"(\s¹ÀVµnîä9ÔªêV¹Å Áæ mnUÒ­"híJM íXÑæV%Ý*§~³±Î‚ÔÒUÔ¹UI·Ê©EP‹ÔYú ͺUn³[µú¿ù„ÐmUÞ­rÖ­έrêVIÒB„r«œu«°‹ckRñêV®¹\`«Z· wrjUu«d1h°ùBE«­ Ò67êhíJM íXÑj«‚´v§Ô"Ä: RKWQk«bÔbêÈP‹ÔYú-¬[%›ÝªÕ'øÍ'„ÖØ`«ÚÔªbÝ*áÜ*Q·J’"”[uº8·*çV]N*AÝ*‚Â5— kÕxnUÒ­*É‘Vu«d1h°ùBE›[•t«Z»RC;V´¹UI·JÔb!ÖYZºŠ:·*éV‰úQµH©ÏЬ[%›ÝªÕ'øÍ'„ÖØh«òn•X·J8·JÔ­’¤…åV‰u«°‹ckR êV®¹\`«Z· wrjUu«d1h°ùBE›[•t«Z»RC;V´¹UI·JÔb!ÖYZºŠ:·*éV‰úQµH©ÏЬ[%›ÝªÕ'øÍ'„ÖØh«òn•X·J8·JÔ­’¤…åV‰u«°‹ckR êV®¹\`«Z· wrjUu«d1h°ùBE›[•t«Z»RC;V´¹UI·JÔb!ÖYZºŠ:·*éV‰úQµH©ÏЬ[%›ÝªÕ'øÍ'„ÖØh«òn•X·J8·JÔ­’¤…åV‰u«°‹ckR êV®¹\`«Z· wrjUu«d1h°ùBE›[•t«Z»RC;V´¹UI·JÔb!ÖYZºŠ:·*éV‰úQµH©ÏЬ[%›ÝªÕ'øÍ'„ÖØh«òn•X·J8·JÔ­’¤…åV‰u«°‹ckR êV®¹\`«Z· wrjUu«d1h°ùBE›[•t«Z»RC;V´¹UI·JÔb!ÖYZºŠ:·*éV‰úQµH©ÏЬ[%›ÝªÕ'øÍ'„ÖØh«òn•X·J8·JÔ­’¤…åV‰u«°‹ckR êV®¹\`«Z· wrjUu«d1h°ùBE›[•t«Z»RC;V´¹UI·JÔb!ÖYZºŠ:·*éV‰úQµH©ÏЬ[%›ÝªÕ'øÍ'„ÖØh«òn•X·J8·JÔ­’¤…åV‰u«°‹ckR êV®¹\`«Z· wrjUu«d1h°ùBE›[•t«Z»RC;V´¹UI·JÔb!ÖYZºŠ:·*éV‰úQµH©ÏЬ[%›ÝªÕ'øÍ'„ÖØh«òn•X·J8·JÔ­’¤…åV‰u«°‹ckR êV®¹\`«Z· wrjUu«d1h°ùBE›[•t«Z»RC;V´¹UI·JÔb!ÖYZºŠ:·*éV‰úQµH©ÏЬ[%›ÝªÕ'øÍ'„ÖØh«òn•X·J8·JÔ­’¤…åV‰u«°‹ckR êV®¹\`«Z· wrjUu«d1h°ùBE›[•t«Z»RC;V´¹UI·JÔb!ÖYZºŠ:·*éV‰úQµH©ÏЬ[%›ÝªÕ'øÍ'„ÖØh«òn•X·Êsn•¨[å“â)·J¬[…][“JP·Š pÍå[ÕºU¸“käP«ª[僛/T´Úª ms£~€Ö®ÔÄÐŽ­¶*Hkwê@-B¬³ µtµ¶*F-v¡Ž µH©OОu«üf·jõ ~ó ¡56ت6µª·n•çÜ*¯n•OZˆ§ÜªÓŹU9·êrRéÕ­"(\s¹°V=çV%ݪ’iU¯n•_ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­òêG1‹ë,H-]E[•t«¼úQµH©ÏЬ[å7»U«Oð›O­±ÑVåÝ*oÝ*ϹU^Ý*Ÿ´O¹UÞºUØÅ±5©ôêV®¹\`«Z· wrjUu«übÐ`ó…Š6·*éV´v¥&†v¬hs«’n•W?ŠY„XgAjé*êܪ¤[åÕ"¨Eê,H}†fÝ*¿Ù­Z}‚ß|Bh¶*ïVyëVyέòêVù¤…xÊ­òÖ­Â.Ž­I¥W·Š pÍå[ÕºU¸“käP«ª[僛/T´¹UI·Š µ+51´cE›[•t«¼úQÌ"Ä: RKWQçV%Ý*¯~A-RgAê34ëVùÍnÕêüæBkl´Uy·Ê[·Êsn•W·Ê'-ÄSn•·nvqlM*½ºU…k.ت֭ÂÀ\#‡ZUÝ*¿4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[åÕb!ÖYZºŠ:·*éVyõ£j‘: RŸ¡Y·Êov«VŸà7ŸZc£­Ê»UÞºUžs«¼ºU>i!žr«¼u«°‹ckRéÕ­"(\s¹ÀVµnîä9ÔªêVùÅ Áæ mnUÒ­"híJM íXÑæV%Ý*¯~³±Î‚ÔÒUÔ¹UI·Ê«EP‹ÔYú ͺU~³[µú¿ù„ÐmUÞ­òÖ­òœ[åÕ­òI ñ”[å­[…][“J¯nAášË¶ªu«0p'×È¡VU·Ê/ 6_¨hs«’nAkWjbhÇŠ6·*éVyõ£˜Eˆu¤–®¢Î­JºU^ý(‚Z¤Î‚ÔghÖ­ò›ÝªÕ'øÍ'„ÖØh«òn•·n•çÜ*¯n•OZˆ§Ü*oÝ*ìâØštþ¸j«â®¹\`«Z· wrjUu«übÐ`ó…Š6·*éV´v¥&†v¬hs«’n•W?ŠY„XgAjé*êܪ¤[åÕ"¨Eê,H}†fÝ*¿Ù­Z}‚ß|Bh¶*ïVyëVyέòêVù¤…xÊ­òÖ­Â.Ž­I¥W·Š pÍå[ÕºU¸“käP«ª[僛/T´¹UI·Š µ+51´cE›[•t«¼úQÌ"Ä: RKWQçV%Ý*¯~A-RgAê34ëVùÍnÕêüæBkl´Uy·Ê[·Êsn•W·Ê'-ÄSn•·nvqlM*½ºU…k.ت֭ÂÀ\#‡ZUÝ*¿4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[åÕb!ÖYZºŠ:·*éVyõ£j‘: RŸ¡Y·Êov«VŸà7ŸZc£­Ê»UÞºUs«¼ºU!i!r«¼u«°‹ckRéÕ­"(\s¹ÀVµnîä9ÔªêV…Å Áæ ­¶*HÛܨ µ+51´cE«­ ÒÚ:P‹ë,H-]E­­ŠQ‹]¨#C-RgAêt`ݪ°Ù­Z}‚ß|Bh ¶ª@­¬[8·*¨[’(·êtqnUέºœTu« ×\.¬UOà¹UI·ª$GZ5¨[ƒ›/T´¹UI·Š µ+51´cE›[•t«‚úQÌ"Ä: RKWQçV%ݪ ~A-RgAê34ëV…ÍnÕêüæBkl´Uy·*X·*pnUP·*$-$PnU°nvqlM*ƒºU…k.ت֭ÂÀ\#‡ZUݪ°4Ø|¡¢Í­JºU­]©‰¡+Úܪ¤[Ôb!ÖYZºŠ:·*éVõ£j‘: RŸ¡Y·*lv«VŸà7ŸZc£­Ê»UÁºUs«‚ºU!i!r«‚u«°‹ckRÔ­"(\s¹ÀVµnîä9ÔªêV…Å Áæ mnUÒ­"híJM íXÑæV%ݪ ~³±Î‚ÔÒUÔ¹UI·*¨EP‹ÔYú ͺUa³[µú¿ù„ÐmUÞ­ Ö­ œ[Ô­ I ”[¬[…][“Ê nAášË¶ªu«0p'×È¡VU·*, 6_¨hs«’nAkWjbhÇŠ6·*éVõ£˜Eˆu¤–®¢Î­JºUAý(‚Z¤Î‚ÔghÖ­ ›ÝªÕ'øÍ'„ÖØh«ònU°nUàܪ nUHZH Üª`Ý*ìâØšTu« ×\.°U­[…;¹FµªºUa1h°ùBE›[•t«Z»RC;V´¹UI·*¨Å,B¬³ µtunUÒ­ êGÔ"u¤>C³nUØìV­>Áo>!´ÆF[•w«‚u«çVu«BÒBåVëVaÇÖ¤2¨[EP¸ær­jÝ* ÜÉ5r¨UÕ­ ‹AƒÍ*Úܪ¤[EÐÚ•šÚ±¢Í­JºUAý(fb©¥«¨s«’nUP?Š ©³ õšu«Âf·jõ ~ó ¡56Úª¼[¬[8·*¨[’(·*X· »8¶&•AÝ*‚Â5— lUëVaàN®‘C­ªnUX l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­ êG1‹ë,H-]E[•t«‚úQµH©ÏЬ[6»U«Oð›O­±ÑVåݪ`ݪÀ¹UAݪ´@¹UÁºUØÅ±5© êV®¹\`«Z· wrjUu«ÂbÐ`ó…Š6·*éV´v¥&†v¬hs«’nUP?ŠY„XgAjé*êܪ¤[Ô"¨Eê,H}†fݪ°Ù­Z}‚ß|Bh¶*ïVëVέ êV…¤…Ê­ Ö­Â.Ž­IeP·Š pÍå[ÕºU¸“käP«ª[ƒ›/T´¹UI·Š µ+51´cE›[•t«‚úQÌ"Ä: RKWQçV%ݪ ~A-RgAê34ëV…ÍnÕêüæBkl´Uy·*X·ªçܪ nUŸ´žr«‚u«°‹ckRÔ­"(\s¹ÀVµnîä9ÔªêVõ‹AƒÍ*ZmU¶¹Q?@kWjbhÇŠV[¤µ;u !ÖYZºŠZ[£»PG†Z¤Î‚Ô'èžu«úÍnÕêüæBkl°UmjÕÞºU=çVõêVõI é)·êtqnUέºœTFu« ×\.¬UOà¹UI·ª$GZµW·ª_ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­êÕb!ÖYZºŠ:·*éVõêGÔ"u¤>C³nU¿Ù­Z}‚ß|Bh¶*ïVõÖ­ê9·ªW·ªOZHO¹U½u«°‹ckRÕ­"(\s¹ÀVµnîä9ÔªêVõ‹AƒÍ*Úܪ¤[EÐÚ•šÚ±¢Í­JºU½úQÌ"Ä: RKWQçV%ݪ^ý(‚Z¤Î‚ÔghÖ­ê7»U«OðœàwÈËtCkl´Uy·ª·nUϹU½ºU}ÒBzÊ­ê­[…][“ʨnAášË¶ªu«0p'×È¡VU·ª_ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­êÕb!ÖYZºŠ:·*éVõêGÔ"u¤>C³nU¿Ù­jœ€u¢ß|Bh¶*ïVõÖ­ê9·ªW·ªOZHO¹U½u«°‹ckRÕ­"(\s¹ÀVµnîä9ÔªêVõ‹AƒÍ*Úܪ¤[EÐÚ•šÚ±¢Í­JºU½úQÌ"Ä: RKWQçV%ݪ^ý(‚Z¤Î‚ÔghÖ­êk¯ k4Ù|‚ß|Bh¶*ïVõÖ­ê9·ªW·ªOZHO¹U½u«°‹ckRÕ­"(\s¹ÀVµnîä9ÔªêVõ‹AƒÍ*Úܪ¤[EÐÚ•šÚ±¢Í­JºU½úQÌ"Ä: RKWQçV%ݪ^ý(‚Z¤Î‚ÔghÖ­êk¯‰mÕµ'øÍ'„ÖØh«ònUoݪžs«zu«ú¤…@ÿ:°«.έʹU—“ʨnAášË¶ªu«0p'×È¡VU·ª_ l¾PÑæV%Ý*‚Ö®ÔÄÐŽmnUÒ­êÕb!ÖYZºŠ:·*éVõêGÔ"u¤>C³nU_{Ml«®=Áo>!´ÆF[•w«zëVõœ[Õ«[Õ'-¤§ÜªÞºUØÅ±5©ŒêV®¹\`«Z· wrjUu«úÅ Áæ mnUÒ­"híJM íXÑæV%ݪ^ý(fb©¥«¨s«’nU¯~A-RgAê34ëVõµ×ĶêÚüæBkl‡âÝÝw7÷?‘ŠÿøÓŸ„Ÿ¦ç¯oŸ¸+NÜý4ýƒœ8\œh:™3³z5³ú$•ô”™Õ[3 »8¶?ùÕ®8…k®&ØÉÖÌÂÀ\#‡:Yͬ~ño°ùBE›;™4³Z»RC;V´¹“I3«W»ŠY„XgAjé*êÜɤ™Õ«]EP‹ÔYú ÍšY}mE±¼ö¿ù„Ð{édä+Ý-]ä+]kfõœ™Õ«™Õ'©¤§Ì¬ÞšYØÅ±9é.¿Ú§pÍå[ÕšY¸“käP«ª™Õ/þ 6_¨hs«’fAkWjbhÇŠ6·*ifõjW1‹ë,H-]E[•4³zµ«j‘: RŸ¡Y3«¯­(¶Uמà7ŸZc£­ùVµfÖÀ™Y½šYC’JÊÌê­™…]›“îôÕ®…k.تÖÌÂÀ\#‡ZUͬaño°ùBE«­ Ò¶7êqZ»RC;V´Úª ­Ý©µ±Î‚ÔÒUÔÚªµØ…:2Ô"u¤>A¬™5ÔVÙª«Oð›O­±ÁVµ¨Ukf œ™5¨™5$©d Ì¬ÓŹU93ËLºÓW»®¹\X«žÀs«’fVIŽ´ê fÖ°ø7Ø|¡¢Í­JšY­]©‰¡+Úܪ¤™5¨]Å,B¬³ µtunUÒÌÔ®"¨Eêl›úü–÷§7-oùü›››‡/¿¿ûöáÙwï^ÜüéáÏuñ§¦>êîõ_nîŸýþþî¯oÞh“ÍØŸ½}÷íÃû_<þì·/ÿúÅí››TÖó¯?{¸¹O¿þÝÝÛßÝ|üËÛ÷_é?ùöáîó¯^¾Ö‡þÍÝw§Çòöýw7÷}ÇÍÛ÷··¹}ø^ßðâöÍíÃ{ýõïoîÿtwÿ&ÿæþîëû—ú› ®ó¦éòN¿_HÞ½~ùý¯çü·¯_¾OGüæöÕÍ¿ÝÜß~³¿¿}uúÍüÁþÍÍËWryËüQ¿xK>qúöáõíÛ›÷iÞü›Ï¿óÇ»×ï?½y½ûü³O?{ñÙÿ]ùâWÏÍ3ó»—on>Nceq$½áòóÓ1ãüÏy)òo‹GÌã\>bùíå#þíîîÍÇùÝé×—ïüýýíÛ‡ÏÞ.Oǡۻ·Å¶þöåý×·oߟߚßþp÷îÙïïæèòá’ô,Þüéøövþh|õæ²_òãÿx÷ðp÷‹|¤¸Yw`Ù¼gi‡ßÝÜuóöáå×7ÏŸ½ü±PÿÛø_–÷ΟYþ0¿Ø´Ó¾ù¡|=¯Ôõ÷Þüåæí—·úòîíëï¿|ÿðýë›÷×üæîíÝWßÜß½¹¹þ˜W÷/ÿôpýÝ·^qw?o÷ǯ¾|øfæº×¨¾­|ÜíòaKÏü»»û‡û—·}~Íè§Î3m›¹1n_½ZÚà?¿|óî¿ü/>ùôε¦ŸÖ¯ïîÑßÏÏÛ3Íÿþ“ý¯Z(ÔµmÕÝHöra–7n¾žüìýÃËû‡_•¦ß¤úsóö•Vòòªù7éíCßûþyµÊéÄg¿ùäõí×oõs?ÿr®ó½ùî‹›¿>änœiÿüÅݯoò×ÁúáÌïœ?ˆéWŸ½}5 µ#ï¾úóÍ«tè\Só›Ó[çª[ùóùŸçÏ>}ùÕŸñü×óÿ~~ú¿ùSéåÃüq};Ïpwzè¯ÓGi·7÷/_›INÏÇÛ‡gú9¸|1õéÝk­ÍÏ^¾¾ý*ýò8ãÝ/§Ø÷·¾ùb^Þo¿þFßòÕýí»„ÿñç/ß¾×çi9·q]úÐ}ZìáÅûç?Þ¥Ç+}ñOµH~àQË‚ýÐcÒŠýЃ~yûòë»·/_ÿàa7ùç|lþc­ýA¸xgY…;l?ìÆë—óKÏ~yó§—ß¾~øüößü~©ÛË—v(îÝwõ£œüìòuPúŒÝ¼¾ùjYÚ÷ÏþåÛû÷w÷>}ôwùó§üœû>ãºóç[W~¶Ÿ/·#._˜­/„>yúBèÇ÷…úBèé ¡ËÇ<}!ôô…ÐÓBõCž¾*ßñô…Ðÿ5_]ü6}HÒTÇÏ~ùòáå3ý`ݼúâåOè‡ëåë¯æ¯”ÒóñÛ—o¿}ùúp3cëg÷¯Þ¾œ? x®&wš<½á½þqúìô†/î^Ï¿zûÕ2õϺ.}ˆë_ïîÿüÇ»»?üþÛSzvòustr-1.0.4/Documentation/structs.txt0000644000076400007640000000303510642321543016563 0ustar jamesjamesSection: Members of Ustr_pool Function: pool_sys_malloc() Returns: Allocated data Type: void * Parameter[1]: Ustr pool object Type[1]: void * Parameter[2]: Length of new allocation Type[2]: size_t Explanation: This is a callback to provide a similar usage to malloc(). This works like malloc() but allocates at least size (Parameter[2]) memory from the pool (Parameter[1]), or it returns NULL on failure. Function: pool_sys_realloc() Returns: Re-allocated data Type: void * Parameter[1]: Ustr pool object Type[1]: void * Parameter[2]: Pointer to the old data Type[2]: void * Parameter[3]: Length of old allocation Type[3]: size_t Parameter[4]: Length of new allocation Type[4]: size_t Explanation: This is a callback to provide a similar usage to realloc(). The Ustr ustr_pool_make() varient works like realloc() but allocates at least size (Parameter[4]) memory from the pool (Parameter[1]) and copies the old data into it, or it returns NULL on failure. Note: If the old data was the last thing allocated from the pool, it might be resized on success. If the old data was larger than the new data, the pointer to the old data is always returned. Function: pool_sys_free() Returns: Nothing Type: void Parameter[1]: Ustr pool object Type[1]: void * Parameter[2]: Pointer to the data Type[2]: void * Explanation: This is a callback to provide a similar usage to free(). The Ustr ustr_pool_make() varient free's the data, if it was the last thing allocated from the pool. Otherwise it does nothing. ustr-1.0.4/Documentation/tutorial.html0000644000076400007640000004603010763663475017067 0ustar jamesjames Tutorial on ustr APIs

      Tutorial on ustr APIs

      ustr is a string library designed to be very space efficient, and easily integrate with "normal" C string handling code. This means that it is designed to allow the programer to create the "strings" from allocated memory, the stack and read-only memory.

      Also note that all error checking is included in every example, it may make the examples somewhat easier to read if it wasn't included ... however including error checking is what the code must look like in a real application.

      Skeleton code required to run the tutorial examples

      This is the skeleton code required to run all the tutorial examples, the full versions may require a few more headers though.

      #include "ustr.h"
      
      #include <errno.h>
      
      static void die(const char *prog_name, const char *msg)
      {
        fprintf(stderr, "%s: %s\n", prog_name, msg);
        exit (EXIT_FAILURE);
      }
      

      Hello World - const

      This example is the simplest possible, basically being the same as calling puts(). Note however that the length of the string is passed through to the IO function without any compiler magic by using the USTR1_CHK (checked constant ustr creation) macro, if it looks a little weird at first you can use the custr example program, to create constant ustr's automatically).

      Note: Although the USTR1_CHK() macro is handed constant data and should be able to determine at compile time whether the length check is correct, GCC doesn't think this is constant and so for file scope variables you'll need to use the USTR1 (non-checking constant ustr creation) macro. Or even the simple USTR("") macro for empty ustr strings.

      /* simplest, just "create" a Ustr from a constant string */
      static void hello_world_one(void)
      {
        Ustr *hello_world = USTR1_CHK(\xC, "Hello world!");
      
        if (!ustr_io_putfileline(&hello_world, stdout))
          die("hello_world", strerror(errno));
      }
      

      Hello World - dup

      This example creates the string before writting it out. Note that although the ustr is allocated, it doesn't need to be free'd because a default configured string of zero length is represented by "".

      static void hello_world_two(void)
      { /* next, create a Ustr from a printf() like format. This needs to be
         * free'd. */
        Ustr *out = ustr_dup_fmt("%s %s", "Hello", "world!");
      
        if (!out || !ustr_io_putfileline(&out, stdout))
          die("hello_world", strerror(errno));
      }
      

      Hello World - multiple parts

      This example creates the string using multiple functions. The interesting part to notice is the call to ustr_enomem(), this checks if any allocation failures have happened to this particular ustr. Also note that we create a specifically configured ustr, which includes a size and a 4 byte reference count.

      static void hello_world_three(void)
      { /* manually create a Ustr, from multiple parts. Often "significantly faster"
         * than using ustr_*_fmt(), due to printf overhead. Still needs to allocate
         * memory, and maybe resize it. Still need to free it. */
        Ustr *hello = USTR1(\5, "Hello");
        Ustr *sp    = USTR1(\1, " ");
        Ustr *world = USTR1(\6, "world!");
        Ustr *out   = ustr_dupx_empty(1, 4, USTR_FALSE, USTR_FALSE);
      
        if (!out)
          die("hello_world", strerror(ENOMEM));
        
        ustr_add(&out, hello);
        ustr_add(&out, sp);
        ustr_add(&out, world);
        
        if (ustr_enomem(out)) /* check all 3 additions at once */
          die("hello_world", strerror(ENOMEM));
      
        if (!ustr_io_putfileline(&out, stdout))
          die("hello_world", strerror(errno));
        
        ustr_free(out);
      }
      

      Hello World - stack based allocation

      This example also creates a string from multiple functions, however the storage for the ustr is on the stack and so we don't need to de-allocate the ustr (although, as with the constant ustr, it does no harm).

      static void hello_world_four(void)
      { /* manually create a Ustr, but use "auto" allocated storage
         * (stack instead of heap). As long as you don't use more than ustr_size()
         * you don't need to free. Also note that ustr_dup() will now always copy. */
        Ustr *sp    = USTR1(\1, " ");
        Ustr *world = USTR1(\6, "world!");
        char buf_out[1024] = USTR_BEG_FIXED2 "Hello";
        Ustr *out = USTR_SC_INIT_AUTO(buf_out, USTR_TRUE, 5);
      
        ustr_add(&out, sp);
        ustr_add(&out, world);
      
        /* in this can we know !ustr_enomem() as there is more than enough space */
        
        if (!ustr_io_putfileline(&out, stdout))
          die("hello_world", strerror(errno));
        
        /* ustr_free() not needed, because nothing was allocated.
         * Although it's often good to call it anyway, as it does no harm. */
      }
      

      fgrep

      This example works like GNU's fgrep --color. There are two main things to notice here. The first is that searching, or searching and replacing with a colourized variant, and reading lines are all just ustr API calls. The second is that the line data is allocated on the stack, by default.

      Both of these significantly improve the ease of use and speed of the resulting code, as ustr_io_getline() is significantly faster than fgets() (due to not having the length of data returned) and allocating from the stack can be a huge performance win (note that all functions, including ustr_free(), do the correct thing ... so we don't suffer complexity for that performance).

      static int fgrep(Ustr **ps1, Ustr *fgrep_srch, Ustr *fgrep_repl,
                       int first_only)
      {
        size_t num = 0;
      
        if (fgrep_repl)
          num = ustr_srch_fwd(*ps1, 0, fgrep_srch);
        else if (!(num = ustr_replace(ps1, fgrep_srch, fgrep_repl,
                                      !first_only)) && errno)
          die("fgrep", strerror(ENOMEM));
        
        if (!num)
          ustr_sc_del(ps1);
      
        return (!!num);
      }
      
      static void fgrep_fp_loop(FILE *in, 
                                Ustr *fgrep_srch, Ustr *fgrep_repl)
      {
        char buf[USTR_SIZE_FIXED(160)]; /* enough for two "normal" lines,
                                           after that we alloc. */
        Ustr *line = USTR_SC_INIT_AUTO(buf, USTR_FALSE, 0);
        
        while (ustr_io_getline(&line, in))
        {
          if (!fgrep(&line, fgrep_srch, fgrep_repl, USTR_FALSE))
            ustr_sc_del(&line);
          else if (!ustr_io_putfile(&line, stdout))
            die("fgrep", strerror(errno));
          
          if (line != USTR(buf)) /* re-init */
            ustr_sc_free2(&line, USTR_SC_INIT_AUTO(buf, USTR_FALSE, 0));
        }
        if (errno)
          die("fgrep", strerror(errno));
      
        ustr_free(line);
      }
      

      mkdir -p function

      This example shows how a single function can take both an allocated (and modifiable) ustr and a constant string ustr, to efficiently modify data.

      static int fu__mkdir_p(const Ustr *s1, int mode, size_t off, int ret)
      {
        Ustr *allocd = USTR_NULL;
        char *ptr = NULL;
      
        if (mkdir(ustr_cstr(s1), mode) != -1)
          return (ret + 1);
      
        switch (errno)
        {
          case EEXIST: return (ret);
            
          case ENOENT: break;
          
          default:     return (-1);
        }
      
        if ((off = ustr_srch_chr_rev(s1, off, '/')) <= 1)
        {
          errno = EINVAL;
          return (-1);
        }
        --off; /* NOTE: offset moves from beg. to end */
        
        if (!ustr_owner(s1))
        { /* do it this way, so we can pass constant Ustr's to this function
           * and don't use ustr_sc_ensure_owner() so that we don't release a
           * reference */
          if (!(allocd = ustr_dup_buf(ustr_cstr(s1), ustr_len(s1))))
            return (-1); /* errno == ENOMEM, done by ustr */
          s1 = allocd;
        }
        
        ptr = ustr_wstr((Ustr *)s1);
        ptr[off] = 0;
        if ((ret = fu__mkdir_p(s1, mode, ustr_len(s1) - off, ret + 1)) != -1)
        {
          ptr[off] = '/';
          if (mkdir(ustr_cstr(s1), mode) == -1)
            ret = -1;
        }
        ustr_free(allocd);
      
        return (ret);
      }
      
      /* This returns -1, on error, or the number of directories created. */
      static int mkdir_p(const Ustr *s1, int mode)
      {
        return (fu__mkdir_p(s1, mode, 0, 0));
      }
      

      In other words:

       mkdir_p(USTR1(\x9, "12/45/789"), 0700)
      

      ...will create/free a single ustr for all 3 of the seperate paths required.

      text into similar looking html converter

      This is a function program showing how you can do the perl code (written by, tchrist@perl.com - Sunday, December 19th, 1999):

      /* 
      # first kill all the tabs
      1 while s{ \t + }
               { " " x (length($&)*8 - length($`)%8) }ex;
      
      # then the four standard naughty bits 
      s/&/&amp;/g;        # must remember to do this one first!
      s/</&lt;/g;         # this is the most important one
      s/>/&gt;/g;         # don't close too early
      s/"/&quot;/g;       # only in embedded tags, i guess
      
      # make lines break where they should
      s/^\s*$/<P>/ || s/$/<BR>/;
      
      # make sure spaces aren't squishticated so we
      # can do indentation and properly align comments
      s/( {2,})/'&nbsp;' x length($1)/ge;
      */
      

      The interesting points here are how simple most of the ustr code is, tab conversion is 2 lines in the original perl and 5 (1 could be dropped for a speed loss) with ustr. The "four std. naughty bits" take a single line in both perl and ustr. The only major difference is in the final perl 1 liner, which is 8 interesting lines (due to the two or more spaces constraint, or we could just use ustr_replace()).

      It's also worth noting that the ustr version is significantly faster than the smaller perl code.

      static void txt2html(Ustr **pline)
      {
        Ustr *line = *pline;
        size_t tab_pos = 0;
        size_t tab_off = 0;
        int has_ret = 0;
        
        /* convert tabs to spaces */
        while ((tab_pos = ustr_srch_chr_fwd(line, tab_off, '\t')))
        {
          size_t tabs_len = ustr_spn_chr_fwd(line, tab_pos - 1, '\t');
          size_t spcs_len = (tabs_len * 8) - ((tab_pos - 1) % 8);
          
          ustr_sc_sub_rep_chr(&line, tab_pos, tabs_len, ' ', spcs_len);
          
          tab_off = tab_pos + spcs_len - 1;
        }
      
        if (ustr_cstr(line)[ustr_len(line) - 1] == '\n')
          has_ret = 1;
        
        if (ustr_spn_chr_fwd(line, 0, ' ') == (ustr_len(line) - has_ret))
          ustr_set(&line, USTR1(\3, "<P>")); /* blank lines start new paragraph */
        else
        {
          size_t spcs_off = 0;
          size_t spcs_pos = 0;
          char buf_rep[USTR_SIZE_FIXED(40 * 6)] = USTR_BEG_FIXED2 "&nbsp;";
          
          ustr_replace_cstr(&line, "&",  "&amp;",  0);
          ustr_replace_cstr(&line, "<",  "&lt;",   0);
          ustr_replace_cstr(&line, ">",  "&gt;",   0);
          ustr_replace_cstr(&line, "\"", "&quot;", 0);
          ustr_del(&line, has_ret);
          ustr_add_cstr(&line, "<BR>\n");
      
          /* convert runs of two or more spaces into runs of &nbsp; */
          while ((spcs_pos = ustr_srch_cstr_fwd(line, spcs_off, "  ")))
          {
            size_t spcs_len = ustr_spn_chr_fwd(line, spcs_pos - 1, ' ');
            size_t rep = spcs_len;
            size_t more = 0;
            Ustr *rep_nbsp = USTR_SC_INIT_AUTO(buf_rep, USTR_FALSE, 0);
      
            while (rep--)
              ustr_add_cstr(&rep_nbsp, "&nbsp;");
      
            if (ustr_enomem(rep_nbsp) ||
                !ustr_sc_sub(&line, spcs_pos, spcs_len, rep_nbsp))
              die(prog_name, strerror(ENOMEM));
      
            spcs_off = spcs_pos + (spcs_len * strlen("&nbsp;")) - 1;
      
            ustr_free(rep_nbsp);
          }
        }
        
        if (ustr_enomem(line))
          die("txt2html", strerror(errno));
      
        *pline = line;
      }
      

      James Antill
      Last modified: Tue Oct 30 01:20:07 EDT 2007 ustr-1.0.4/ustr-conf-multilib-linux.h0000644000076400007640000000031510723716353016554 0ustar jamesjames/* This might be Linux/GLibc specific */ #include #if __WORDSIZE == 32 #include #elif __WORDSIZE == 64 #include #else #error "Unknown word size" #endif ustr-1.0.4/ustr-cmp.h0000644000076400007640000006626410673025031013437 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_CMP_H #define USTR_CMP_H 1 #ifndef USTR_MAIN_H #error " You should have already included ustr-main.h, or just include ustr.h." #endif /* normal strcmp() like, deals with embeded NILs */ USTR_CONF_E_PROTO int ustr_cmp_buf(const struct Ustr *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp(const struct Ustr *, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_cmp_subustr(const struct Ustr *, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_cstr(const struct Ustr *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* faster compare, sorts in a very non-human way */ USTR_CONF_EI_PROTO int ustr_cmp_fast_buf(const struct Ustr*, const void*,size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_fast(const struct Ustr *, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_cmp_fast_subustr(const struct Ustr *, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_fast_cstr(const struct Ustr *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* normal ASCII strcasecmp() like, deals with embeded NILs */ USTR_CONF_E_PROTO int ustr_cmp_case_buf(const struct Ustr *,const void *,size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case(const struct Ustr *, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_cmp_case_subustr(const struct Ustr *, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case_cstr(const struct Ustr *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* EQ functions to make code readable ... also faster due to ustr_cmp_fast() */ USTR_CONF_EI_PROTO int ustr_cmp_eq(const struct Ustr *, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_buf_eq(const struct Ustr *, const void *,size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_subustr_eq(const struct Ustr *, const struct Ustr *, size_t,size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_cstr_eq(const struct Ustr *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case_eq(const struct Ustr *,const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case_buf_eq(const struct Ustr *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case_subustr_eq(const struct Ustr *, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case_cstr_eq(const struct Ustr *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_prefix_eq(const struct Ustr *, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_prefix_buf_eq(const struct Ustr *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_prefix_cstr_eq(const struct Ustr *,const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_cmp_prefix_subustr_eq(const struct Ustr *, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case_prefix_eq(const struct Ustr *, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_cmp_case_prefix_buf_eq(const struct Ustr *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case_prefix_cstr_eq(const struct Ustr *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_cmp_case_prefix_subustr_eq(const struct Ustr *, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_suffix_eq(const struct Ustr *, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_suffix_buf_eq(const struct Ustr *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_suffix_cstr_eq(const struct Ustr *,const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_cmp_suffix_subustr_eq(const struct Ustr *, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case_suffix_eq(const struct Ustr *, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case_suffix_buf_eq(const struct Ustr *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_cmp_case_suffix_cstr_eq(const struct Ustr *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_cmp_case_suffix_subustr_eq(const struct Ustr *, const struct Ustr *, size_t, size_t) 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 int ustr_cmp_fast_buf(const struct Ustr *s1, const void *buf, size_t len2) { size_t len1 = 0; USTR_ASSERT(ustr_assert_valid(s1) && buf); len1 = ustr_len(s1); if (len1 == len2) return (memcmp(ustr_cstr(s1), buf, len1)); else if (len1 > len2) return (1); else return (-1); } USTR_CONF_II_PROTO int ustr_cmp_prefix_buf_eq(const struct Ustr *s1, const void *buf, size_t len2) { size_t len1 = 0; USTR_ASSERT(ustr_assert_valid(s1) && buf); len1 = ustr_len(s1); if (len1 < len2) return (USTR_FALSE); return (!memcmp(ustr_cstr(s1), buf, len2)); } USTR_CONF_II_PROTO int ustr_cmp_suffix_buf_eq(const struct Ustr *s1, const void *buf, size_t len2) { size_t len1 = 0; USTR_ASSERT(ustr_assert_valid(s1) && buf); len1 = ustr_len(s1); if (len1 < len2) return (USTR_FALSE); return (!memcmp(ustr_cstr(s1) + (len1 - len2), buf, len2)); } #endif #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-cmp-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-cmp-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO int ustr_cmp(const struct Ustr *s1, const struct Ustr *s2) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (s1 == s2) return (0); return (ustr_cmp_buf(s1, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO int ustr_cmp_fast(const struct Ustr *s1,const struct Ustr*s2) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (s1 == s2) return (0); return (ustr_cmp_fast_buf(s1, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO int ustr_cmp_case(const struct Ustr *s1,const struct Ustr*s2) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (s1 == s2) return (0); return (ustr_cmp_case_buf(s1, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO int ustr_cmp_cstr(const struct Ustr *s1, const char *s2) { return (ustr_cmp_buf(s1, s2, strlen(s2))); } USTR_CONF_II_PROTO int ustr_cmp_fast_cstr(const struct Ustr *s1, const char *s2) { return (ustr_cmp_fast_buf(s1, s2, strlen(s2))); } USTR_CONF_II_PROTO int ustr_cmp_case_cstr(const struct Ustr *s1, const char *s2) { return (ustr_cmp_case_buf(s1, s2, strlen(s2))); } USTR_CONF_II_PROTO int ustr_cmp_eq(const struct Ustr *s1, const struct Ustr *s2) { return (!ustr_cmp_fast(s1, s2)); } USTR_CONF_II_PROTO int ustr_cmp_buf_eq(const struct Ustr *s1, const void *buf, size_t len) { return (!ustr_cmp_fast_buf(s1, buf, len)); } USTR_CONF_II_PROTO int ustr_cmp_subustr_eq(const struct Ustr *s1, const struct Ustr *s2, size_t pos, size_t len) { return (!ustr_cmp_fast_subustr(s1, s2, pos, len)); } USTR_CONF_II_PROTO int ustr_cmp_cstr_eq(const struct Ustr *s1, const char *cstr) { return (!ustr_cmp_fast_buf(s1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustr_cmp_case_eq(const struct Ustr *s1, const struct Ustr *s2) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (s1 == s2) return (USTR_TRUE); return ((ustr_len(s1) == ustr_len(s2)) && !ustr_cmp_case(s1, s2)); } USTR_CONF_II_PROTO int ustr_cmp_case_buf_eq(const struct Ustr *s1, const void *buf, size_t len) { USTR_ASSERT(ustr_assert_valid(s1)); return ((ustr_len(s1) == len) && !ustr_cmp_case_buf(s1, buf, len)); } USTR_CONF_II_PROTO int ustr_cmp_case_subustr_eq(const struct Ustr *s1, const struct Ustr *s2, size_t pos, size_t len) { USTR_ASSERT(ustr_assert_valid(s1)); return ((ustr_len(s1) == len) && !ustr_cmp_case_subustr(s1, s2, pos, len)); } USTR_CONF_II_PROTO int ustr_cmp_case_cstr_eq(const struct Ustr *s1, const char *cstr) { size_t len = strlen(cstr); USTR_ASSERT(ustr_assert_valid(s1)); return ((ustr_len(s1) == len) && !ustr_cmp_case_buf(s1, cstr, len)); } USTR_CONF_II_PROTO int ustr_cmp_prefix_eq(const struct Ustr *s1, const struct Ustr *s2) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (s1 == s2) return (USTR_TRUE); return (ustr_cmp_prefix_buf_eq(s1, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO int ustr_cmp_prefix_cstr_eq(const struct Ustr *s1, const char *cstr) { return (ustr_cmp_prefix_buf_eq(s1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustr_cmp_case_prefix_eq(const struct Ustr *s1, const struct Ustr *s2) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (s1 == s2) return (USTR_TRUE); return (ustr_cmp_case_prefix_buf_eq(s1, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO int ustr_cmp_case_prefix_cstr_eq(const struct Ustr *s1, const char *cstr) { return (ustr_cmp_case_prefix_buf_eq(s1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustr_cmp_suffix_eq(const struct Ustr *s1, const struct Ustr *s2) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (s1 == s2) return (USTR_TRUE); return (ustr_cmp_suffix_buf_eq(s1, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO int ustr_cmp_suffix_cstr_eq(const struct Ustr *s1, const char *cstr) { return (ustr_cmp_suffix_buf_eq(s1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustr_cmp_case_suffix_eq(const struct Ustr *s1, const struct Ustr *s2) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (s1 == s2) return (USTR_TRUE); return (ustr_cmp_case_suffix_buf_eq(s1, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO int ustr_cmp_case_suffix_cstr_eq(const struct Ustr *s1, const char *cstr) { return (ustr_cmp_case_suffix_buf_eq(s1, cstr, strlen(cstr))); } #endif /* ---------------- pool wrapper APIs ---------------- */ /* normal strcmp() like, deals with embeded NILs */ USTR_CONF_EI_PROTO int ustrp_cmp_buf(const struct Ustrp *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp(const struct Ustrp *, const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_subustrp(const struct Ustrp *, 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 int ustrp_cmp_cstr(const struct Ustrp *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* faster compare, sorts in a very non-human way */ USTR_CONF_EI_PROTO int ustrp_cmp_fast_buf(const struct Ustrp *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_fast(const struct Ustrp *, const struct Ustrp*) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_fast_subustrp(const struct Ustrp *, 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 int ustrp_cmp_fast_cstr(const struct Ustrp *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* normal ASCII strcasecmp() like, deals with embeded NILs */ USTR_CONF_EI_PROTO int ustrp_cmp_case_buf(const struct Ustrp *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case(const struct Ustrp *,const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case_subustrp(const struct Ustrp *, 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 int ustrp_cmp_case_cstr(const struct Ustrp *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); /* EQ functions to make code readable ... also faster due to ustr_cmp_fast() */ USTR_CONF_EI_PROTO int ustrp_cmp_eq(const struct Ustrp *, const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_buf_eq(const struct Ustrp *,const void*,size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_subustrp_eq(const struct Ustrp *, 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 int ustrp_cmp_cstr_eq(const struct Ustrp *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case_eq(const struct Ustrp *, const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case_buf_eq(const struct Ustrp *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case_subustrp_eq(const struct Ustrp *, 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 int ustrp_cmp_case_cstr_eq(const struct Ustrp *,const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_prefix_eq(const struct Ustrp *, const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_prefix_buf_eq(const struct Ustrp *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_prefix_cstr_eq(const struct Ustrp *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_prefix_subustrp_eq(const struct Ustrp *, 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 int ustrp_cmp_case_prefix_eq(const struct Ustrp *, const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case_prefix_buf_eq(const struct Ustrp *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case_prefix_cstr_eq(const struct Ustrp *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case_prefix_subustrp_eq(const struct Ustrp *, 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 int ustrp_cmp_suffix_eq(const struct Ustrp *, const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_suffix_buf_eq(const struct Ustrp *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_suffix_cstr_eq(const struct Ustrp *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_suffix_subustrp_eq(const struct Ustrp *, 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 int ustrp_cmp_case_suffix_eq(const struct Ustrp *, const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case_suffix_buf_eq(const struct Ustrp *, const void *, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case_suffix_cstr_eq(const struct Ustrp *, const char *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustrp_cmp_case_suffix_subustrp_eq(const struct Ustrp *, const struct Ustrp *, size_t, size_t) 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 int ustrp_cmp_buf(const struct Ustrp *s1, const void *s2, size_t len) { return (ustr_cmp_buf(&s1->s, s2, len)); } USTR_CONF_II_PROTO int ustrp_cmp(const struct Ustrp *s1, const struct Ustrp *s2) { return (ustr_cmp(&s1->s, &s2->s)); } USTR_CONF_II_PROTO int ustrp_cmp_subustrp(const struct Ustrp *s1, const struct Ustrp *s2, size_t pos, size_t len) { return (ustr_cmp_subustr(&s1->s, &s2->s, pos, len)); } USTR_CONF_II_PROTO int ustrp_cmp_cstr(const struct Ustrp *s1, const char *s2) { return (ustrp_cmp_buf(s1, s2, strlen(s2))); } USTR_CONF_II_PROTO int ustrp_cmp_fast_buf(const struct Ustrp *s1, const void *s2, size_t len) { return (ustr_cmp_fast_buf(&s1->s, s2, len)); } USTR_CONF_II_PROTO int ustrp_cmp_fast(const struct Ustrp *s1, const struct Ustrp *s2) { return (ustr_cmp_fast(&s1->s, &s2->s)); } USTR_CONF_II_PROTO int ustrp_cmp_fast_subustrp(const struct Ustrp *s1, const struct Ustrp *s2, size_t pos, size_t len) { return (ustr_cmp_fast_subustr(&s1->s, &s2->s, pos, len)); } USTR_CONF_II_PROTO int ustrp_cmp_fast_cstr(const struct Ustrp *s1, const char *s2) { return (ustrp_cmp_fast_buf(s1, s2, strlen(s2))); } USTR_CONF_II_PROTO int ustrp_cmp_case_buf(const struct Ustrp *s1, const void *s2, size_t len) { return (ustr_cmp_case_buf(&s1->s, s2, len)); } USTR_CONF_II_PROTO int ustrp_cmp_case(const struct Ustrp *s1, const struct Ustrp *s2) { return (ustr_cmp_case(&s1->s, &s2->s)); } USTR_CONF_II_PROTO int ustrp_cmp_case_subustrp(const struct Ustrp *s1, const struct Ustrp *s2, size_t pos, size_t len) { return (ustr_cmp_case_subustr(&s1->s, &s2->s, pos, len)); } USTR_CONF_II_PROTO int ustrp_cmp_case_cstr(const struct Ustrp *s1,const char*s2) { return (ustrp_cmp_case_buf(s1, s2, strlen(s2))); } USTR_CONF_II_PROTO int ustrp_cmp_eq(const struct Ustrp *s1, const struct Ustrp *s2) { return (!ustrp_cmp_fast(s1, s2)); } USTR_CONF_II_PROTO int ustrp_cmp_buf_eq(const struct Ustrp *s1, const void *buf, size_t len) { return (!ustrp_cmp_fast_buf(s1, buf, len)); } USTR_CONF_II_PROTO int ustrp_cmp_subustrp_eq(const struct Ustrp *s1, const struct Ustrp *s2, size_t pos, size_t len) { return (!ustrp_cmp_fast_subustrp(s1, s2, pos, len)); } USTR_CONF_II_PROTO int ustrp_cmp_cstr_eq(const struct Ustrp *s1, const char *cstr) { return (!ustrp_cmp_fast_buf(s1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustrp_cmp_case_eq(const struct Ustrp *s1, const struct Ustrp *s2) { return (ustr_cmp_case_eq(&s1->s, &s2->s)); } USTR_CONF_II_PROTO int ustrp_cmp_case_buf_eq(const struct Ustrp *s1, const void *buf, size_t len) { return (ustr_cmp_case_buf_eq(&s1->s, buf, len)); } USTR_CONF_II_PROTO int ustrp_cmp_case_subustrp_eq(const struct Ustrp *s1, const struct Ustrp *s2, size_t pos, size_t len) { return (ustr_cmp_case_subustr_eq(&s1->s, &s2->s, pos, len)); } USTR_CONF_II_PROTO int ustrp_cmp_case_cstr_eq(const struct Ustrp *s1, const char *cstr) { return (ustr_cmp_case_buf_eq(&s1->s, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustrp_cmp_prefix_eq(const struct Ustrp *s1, const struct Ustrp *s2) { return (ustr_cmp_prefix_eq(&s1->s, &s2->s)); } USTR_CONF_II_PROTO int ustrp_cmp_prefix_buf_eq(const struct Ustrp *s1, const void *buf, size_t len) { return (ustr_cmp_prefix_buf_eq(&s1->s, buf, len)); } USTR_CONF_II_PROTO int ustrp_cmp_prefix_subustrp_eq(const struct Ustrp *s1, const struct Ustrp *s2, size_t p,size_t l) { return (ustr_cmp_prefix_subustr_eq(&s1->s, &s2->s, p, l)); } USTR_CONF_II_PROTO int ustrp_cmp_prefix_cstr_eq(const struct Ustrp *s1, const char *cstr) { return (ustrp_cmp_prefix_buf_eq(s1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustrp_cmp_case_prefix_eq(const struct Ustrp *s1, const struct Ustrp *s2) { return (ustr_cmp_case_prefix_eq(&s1->s, &s2->s)); } USTR_CONF_II_PROTO int ustrp_cmp_case_prefix_buf_eq(const struct Ustrp *s1, const void *buf, size_t len) { return (ustr_cmp_case_prefix_buf_eq(&s1->s, buf, len)); } USTR_CONF_II_PROTO int ustrp_cmp_case_prefix_subustrp_eq(const struct Ustrp *s1, const struct Ustrp *s2, size_t p,size_t l) { return (ustr_cmp_case_prefix_subustr_eq(&s1->s, &s2->s, p, l)); } USTR_CONF_II_PROTO int ustrp_cmp_case_prefix_cstr_eq(const struct Ustrp *s1, const char *cstr) { return (ustrp_cmp_case_prefix_buf_eq(s1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustrp_cmp_suffix_eq(const struct Ustrp *s1, const struct Ustrp *s2) { return (ustr_cmp_suffix_eq(&s1->s, &s2->s)); } USTR_CONF_II_PROTO int ustrp_cmp_suffix_buf_eq(const struct Ustrp *s1, const void *buf, size_t len) { return (ustr_cmp_suffix_buf_eq(&s1->s, buf, len)); } USTR_CONF_II_PROTO int ustrp_cmp_suffix_subustrp_eq(const struct Ustrp *s1, const struct Ustrp *s2, size_t p,size_t l) { return (ustr_cmp_suffix_subustr_eq(&s1->s, &s2->s, p, l)); } USTR_CONF_II_PROTO int ustrp_cmp_suffix_cstr_eq(const struct Ustrp *s1, const char *cstr) { return (ustrp_cmp_suffix_buf_eq(s1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustrp_cmp_case_suffix_eq(const struct Ustrp *s1, const struct Ustrp *s2) { return (ustr_cmp_case_suffix_eq(&s1->s, &s2->s)); } USTR_CONF_II_PROTO int ustrp_cmp_case_suffix_buf_eq(const struct Ustrp *s1, const void *buf, size_t len) { return (ustr_cmp_case_suffix_buf_eq(&s1->s, buf, len)); } USTR_CONF_II_PROTO int ustrp_cmp_case_suffix_subustrp_eq(const struct Ustrp *s1, const struct Ustrp *s2, size_t p,size_t l) { return (ustr_cmp_case_suffix_subustr_eq(&s1->s, &s2->s, p, l)); } USTR_CONF_II_PROTO int ustrp_cmp_case_suffix_cstr_eq(const struct Ustrp *s1, const char *cstr) { return (ustrp_cmp_case_suffix_buf_eq(s1, cstr, strlen(cstr))); } #endif #endif ustr-1.0.4/ustr-utf8.h0000644000076400007640000000563510723715662013555 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_UTF8_H #define USTR_UTF8_H 1 #ifndef USTR_MAIN_H #error " You should have already included ustr-main.h, or just include ustr.h." #endif #ifdef __unix__ /* FIXME: Hacky, but this isn't a 9899:1999 type */ #define USTR__SSIZE ssize_t #else #define USTR__SSIZE long #endif USTR_CONF_E_PROTO int ustr_utf8_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_utf8_len(const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO USTR__SSIZE ustr_utf8_width(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_utf8_chars2bytes(const struct Ustr *, size_t, size_t, size_t *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO size_t ustr_utf8_bytes2chars(const struct Ustr *, size_t, size_t, size_t *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO int ustrp_utf8_valid(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_utf8_len(const struct Ustrp *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO USTR__SSIZE ustrp_utf8_width(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_utf8_chars2bytes(const struct Ustrp *, size_t, size_t, size_t *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_EI_PROTO size_t ustrp_utf8_bytes2chars(const struct Ustrp *, size_t, size_t, size_t *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-utf8-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-utf8-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO int ustrp_utf8_valid(const struct Ustrp *s1) { return (ustr_utf8_valid(&s1->s)); } USTR_CONF_II_PROTO size_t ustrp_utf8_len(const struct Ustrp *s1) { return (ustr_utf8_len(&s1->s)); } USTR_CONF_II_PROTO USTR__SSIZE ustrp_utf8_width(const struct Ustrp *s1) { return (ustr_utf8_width(&s1->s)); } USTR_CONF_II_PROTO size_t ustrp_utf8_chars2bytes(const struct Ustrp *s1, size_t pos, size_t len, size_t *ret_pos) { return (ustr_utf8_chars2bytes(&s1->s, pos, len, ret_pos)); } USTR_CONF_II_PROTO size_t ustrp_utf8_bytes2chars(const struct Ustrp *s1, size_t pos, size_t len, size_t *ret_pos) { return (ustr_utf8_bytes2chars(&s1->s, pos, len, ret_pos)); } #endif #endif ustr-1.0.4/ustr-main.h0000644000076400007640000012552510763121002013573 0ustar jamesjames/* 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 ustr-1.0.4/malloc-check.h0000644000076400007640000003314610711000310014162 0ustar jamesjames#ifndef MALLOC_CHECK_H #define MALLOC_CHECK_H 1 #ifndef MALLOC_CHECK__ATTR_USED #if defined(__GNUC__) && (__GNUC__ > 3) /* not sure */ # define MALLOC_CHECK__ATTR_USED() __attribute__((__used__)) #else # define MALLOC_CHECK__ATTR_USED() /* do nothing */ #endif #endif #ifndef MALLOC_CHECK__ATTR_H #if defined(__GNUC__) && (__GNUC__ > 3) /* not sure */ # define MALLOC_CHECK__ATTR_H() __attribute__((__visibility__("hidden"))) #else # define MALLOC_CHECK__ATTR_H() /* do nothing */ #endif #endif #ifndef MALLOC_CHECK__ATTR_MALLOC #if defined(__GNUC__) && (__GNUC__ > 3) /* not sure */ # define MALLOC_CHECK__ATTR_MALLOC() __attribute__ ((__malloc__)) #else # define MALLOC_CHECK__ATTR_MALLOC() /* do nothing */ #endif #endif #ifndef MALLOC_CHECK_API_M_SCRUB /* memset data at ptr's on malloc */ #define MALLOC_CHECK_API_M_SCRUB 0 #endif #ifndef MALLOC_CHECK_API_F_SCRUB /* memset data at ptr's on free */ #define MALLOC_CHECK_API_F_SCRUB 0 #endif #ifndef MALLOC_CHECK_API_R_SCRUB /* never really call realloc() */ #define MALLOC_CHECK_API_R_SCRUB 0 #endif #ifndef MALLOC_CHECK_STORE #define MALLOC_CHECK_STORE malloc_check__app_store #endif /* NOTE: don't reset fail nums */ #define MALLOC_CHECK_REINIT() \ MALLOC_CHECK_STORE.mem_sz = 0; \ MALLOC_CHECK_STORE.mem_num = 0; \ MALLOC_CHECK_STORE.mem_vals = NULL #define MALLOC_CHECK_INIT() \ MALLOC_CHECK_STORE.mem_fail_num = 0; \ MALLOC_CHECK_REINIT() #ifndef USE_MALLOC_CHECK #ifndef NDEBUG # define USE_MALLOC_CHECK 1 # else # define USE_MALLOC_CHECK 0 # endif #endif #ifndef MALLOC_CHECK_FUNC_NAME #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ (defined(__GNUC__) && (__GNUC__ > 3) && !defined(__STRICT_ANSI__)) # define MALLOC_CHECK_FUNC_NAME __func__ #else # define MALLOC_CHECK_FUNC_NAME "" #endif #endif #define MALLOC_CHECK_MEM(x) \ malloc_check_mem(x, __FILE__, __LINE__, MALLOC_CHECK_FUNC_NAME) #define MALLOC_CHECK_MEM_SZ(x, y) \ malloc_check_mem_sz(x, y, __FILE__, __LINE__, MALLOC_CHECK_FUNC_NAME) #define MALLOC_CHECK_MEM_MINSZ(x, y) \ malloc_check_mem_minsz(x, y, __FILE__, __LINE__, MALLOC_CHECK_FUNC_NAME) #define MALLOC_CHECK_EMPTY() \ malloc_check_empty(__FILE__, __LINE__, MALLOC_CHECK_FUNC_NAME) /* smaller because they will be called a _lot_ */ #define MC_MALLOC(x) \ malloc_check_malloc(x, __FILE__, __LINE__, MALLOC_CHECK_FUNC_NAME) #define MC_CALLOC(x, y) \ malloc_check_calloc(x, y, __FILE__, __LINE__, MALLOC_CHECK_FUNC_NAME) #define MC_REALLOC(x, y) \ malloc_check_realloc(x, y, __FILE__, __LINE__, MALLOC_CHECK_FUNC_NAME) #define MC_FREE(x) \ malloc_check_free(x, __FILE__, __LINE__, MALLOC_CHECK_FUNC_NAME) #if !(USE_MALLOC_CHECK) #define MALLOC_CHECK_DECL() \ static Malloc_check_store MALLOC_CHECK_STORE = {0, 0, 0, NULL} # define MALLOC_CHECK_FAIL_IN(x) /* nothing */ # define MALLOC_CHECK_SCRUB_PTR(x, y) /* nothing */ # define malloc_check_mem(x, Fi, L, Fu) (1) # define malloc_check_mem_sz(x, y, Fi, L, Fu) (1) # define malloc_check_mem_minsz(x, y, Fi, L, Fu) (1) # define malloc_check_empty(Fi, L, Fu) /* nothing */ # define malloc_check_malloc(x, Fi, L, Fu) malloc(x) # define malloc_check_calloc(x, y, Fi, L, Fu) calloc(x, y) # define malloc_check_realloc(x, y, Fi, L, Fu) realloc(x, y) # define malloc_check_free(x, Fi, L, Fu) free(x) #else #include #include #include typedef struct Malloc_check_vals { void *ptr; size_t sz; const char *file; unsigned int line; const char *func; } Malloc_check_vals; typedef struct Malloc_check_store { unsigned long mem_sz; unsigned long mem_num; unsigned long mem_fail_num; Malloc_check_vals *mem_vals; } Malloc_check_store; #ifndef MALLOC_CHECK_SCOPE_EXTERN #define MALLOC_CHECK_SCOPE_EXTERN 1 #endif #if MALLOC_CHECK_SCOPE_EXTERN extern Malloc_check_store MALLOC_CHECK__ATTR_H() MALLOC_CHECK_STORE; #else static Malloc_check_store MALLOC_CHECK_STORE; #endif /* custom assert's so that we get the file/line numbers right, always ON */ #define malloc_check_assert(x) do { \ if (x) {} else { \ fprintf(stderr, " -=> mc_assert (%s) failed, caller=%s:%s:%d.\n", \ #x , func, file, line); \ abort(); } \ } while (0) #define MALLOC_CHECK_ASSERT(x) do { \ if (x) {} else { \ fprintf(stderr, " -=> MC_ASSERT (%s) failed, caller=%s:%s:%d.\n", \ #x , func, file, line); \ abort(); } \ } while (0) #if MALLOC_CHECK_SCOPE_EXTERN #define MALLOC_CHECK_DECL() \ Malloc_check_store MALLOC_CHECK_STORE = {0, 0, 0, NULL} #else #define MALLOC_CHECK_DECL() \ static Malloc_check_store MALLOC_CHECK_STORE = {0, 0, 0, NULL} #endif # define MALLOC_CHECK_DEC() \ (MALLOC_CHECK_STORE.mem_fail_num && !--MALLOC_CHECK_STORE.mem_fail_num) # define MALLOC_CHECK_FAIL_IN(x) MALLOC_CHECK_STORE.mem_fail_num = (x) # define MALLOC_CHECK_SCRUB_PTR(x, y) memset(x, 0xa5, y) #ifndef MALLOC_CHECK_PRINT #define MALLOC_CHECK_PRINT 1 #endif #ifndef MALLOC_CHECK_TRACE #define MALLOC_CHECK_TRACE 0 #endif #ifndef MALLOC_CHECK_SWAP_TYPE #define MALLOC_CHECK_SWAP_TYPE(x, y, type) do { \ type internal_local_tmp = (x); \ (x) = (y); \ (y) = internal_local_tmp; \ } while (0) #endif static void malloc_check_alloc(const char *, unsigned int, const char *) MALLOC_CHECK__ATTR_USED(); static unsigned int malloc_check_mem(const void *, const char *, unsigned int, const char *) MALLOC_CHECK__ATTR_USED(); static unsigned int malloc_check_mem_sz(const void *, size_t, const char *, unsigned int, const char *) MALLOC_CHECK__ATTR_USED(); static unsigned int malloc_check_mem_minsz(const void *, size_t, const char *, unsigned int, const char *) MALLOC_CHECK__ATTR_USED(); static void *malloc_check_malloc(size_t, const char *, unsigned int, const char *) MALLOC_CHECK__ATTR_MALLOC() MALLOC_CHECK__ATTR_USED(); static void *malloc_check_calloc(size_t, size_t, const char *, unsigned int, const char *) MALLOC_CHECK__ATTR_MALLOC() MALLOC_CHECK__ATTR_USED(); static void malloc_check_free(void *, const char *, unsigned int, const char *) MALLOC_CHECK__ATTR_USED(); static void *malloc_check_realloc(void *, size_t, const char *, unsigned int, const char *) MALLOC_CHECK__ATTR_MALLOC() MALLOC_CHECK__ATTR_USED(); static void malloc_check_empty(const char *, unsigned int, const char *) MALLOC_CHECK__ATTR_USED(); static void malloc_check_alloc(const char *file, unsigned int line, const char *func) { size_t sz = MALLOC_CHECK_STORE.mem_sz; ++MALLOC_CHECK_STORE.mem_num; if (!MALLOC_CHECK_STORE.mem_sz) { sz = 8; MALLOC_CHECK_STORE.mem_vals = malloc(sizeof(Malloc_check_vals) * sz); } else if (MALLOC_CHECK_STORE.mem_num > MALLOC_CHECK_STORE.mem_sz) { sz *= 2; MALLOC_CHECK_STORE.mem_vals = realloc(MALLOC_CHECK_STORE.mem_vals, sizeof(Malloc_check_vals) * sz); } malloc_check_assert(MALLOC_CHECK_STORE.mem_num <= sz); malloc_check_assert(MALLOC_CHECK_STORE.mem_vals); MALLOC_CHECK_STORE.mem_sz = sz; } static unsigned int malloc_check_mem(const void *ptr, const char *file, unsigned int line, const char *func) { unsigned int scan = 0; malloc_check_assert(MALLOC_CHECK_STORE.mem_num); while (MALLOC_CHECK_STORE.mem_vals[scan].ptr && (MALLOC_CHECK_STORE.mem_vals[scan].ptr != ptr)) ++scan; malloc_check_assert(MALLOC_CHECK_STORE.mem_vals[scan].ptr); return (scan); } static unsigned int malloc_check_mem_sz(const void *ptr, size_t sz, const char *file, unsigned int line, const char *func) { unsigned int scan = malloc_check_mem(ptr, file, line, func); malloc_check_assert(MALLOC_CHECK_STORE.mem_vals[scan].sz == sz); return (scan); } static unsigned int malloc_check_mem_minsz(const void *ptr, size_t sz, const char *file, unsigned int line, const char *func) { unsigned int scan = malloc_check_mem(ptr, file, line, func); malloc_check_assert(MALLOC_CHECK_STORE.mem_vals[scan].sz >= sz); return (scan); } static void *malloc_check_malloc(size_t sz, const char *file, unsigned int line, const char *func) { void *ret = NULL; if (MALLOC_CHECK_DEC()) return (NULL); malloc_check_alloc(file, line, func); MALLOC_CHECK_ASSERT(sz); ret = malloc(sz); MALLOC_CHECK_ASSERT(ret); if (!ret) /* just in case */ return (NULL); if (MALLOC_CHECK_TRACE) fprintf(stderr, "mc_make(%zu, %s, %u, %s) = %p\n", sz, file,line,func, ret); if (MALLOC_CHECK_API_M_SCRUB) MALLOC_CHECK_SCRUB_PTR(ret, sz); MALLOC_CHECK_STORE.mem_vals[MALLOC_CHECK_STORE.mem_num - 1].ptr = ret; MALLOC_CHECK_STORE.mem_vals[MALLOC_CHECK_STORE.mem_num - 1].sz = sz; MALLOC_CHECK_STORE.mem_vals[MALLOC_CHECK_STORE.mem_num - 1].file = file; MALLOC_CHECK_STORE.mem_vals[MALLOC_CHECK_STORE.mem_num - 1].line = line; MALLOC_CHECK_STORE.mem_vals[MALLOC_CHECK_STORE.mem_num - 1].func = func; return (ret); } static void *malloc_check_calloc(size_t num, size_t sz, const char *file, unsigned int line, const char *func) { size_t real_sz = num * sz; void *ret = NULL; if ((num != 0) && ((real_sz / sz) != num)) return (NULL); if (!(ret = malloc_check_malloc(real_sz, file, line, func))) return (NULL); memset(ret, 0, real_sz); return (ret); } static void malloc_check_free(void *ptr, const char *file, unsigned int line, const char *func) { if (MALLOC_CHECK_TRACE) fprintf(stderr, "mc_free(%s, %u, %s, %p)\n", file, line, func, ptr); if (ptr) { unsigned int scan = malloc_check_mem(ptr, file, line, func); size_t sz = 0; malloc_check_assert(MALLOC_CHECK_STORE.mem_num > 0); --MALLOC_CHECK_STORE.mem_num; sz = MALLOC_CHECK_STORE.mem_vals[scan].sz; if (scan != MALLOC_CHECK_STORE.mem_num) { unsigned int num = MALLOC_CHECK_STORE.mem_num; Malloc_check_vals *val1 = &MALLOC_CHECK_STORE.mem_vals[scan]; Malloc_check_vals *val2 = &MALLOC_CHECK_STORE.mem_vals[num]; MALLOC_CHECK_SWAP_TYPE(val1->ptr, val2->ptr, void *); MALLOC_CHECK_SWAP_TYPE(val1->sz, val2->sz, size_t); MALLOC_CHECK_SWAP_TYPE(val1->file, val2->file, const char *); MALLOC_CHECK_SWAP_TYPE(val1->line, val2->line, unsigned int); MALLOC_CHECK_SWAP_TYPE(val1->func, val2->func, const char *); } MALLOC_CHECK_STORE.mem_vals[MALLOC_CHECK_STORE.mem_num].ptr = NULL; if (MALLOC_CHECK_API_F_SCRUB) MALLOC_CHECK_SCRUB_PTR(ptr, sz); free(ptr); } } static void *malloc_check_realloc(void *ptr, size_t sz, const char *file, unsigned int line, const char *func) { void *ret = NULL; unsigned int scan = malloc_check_mem(ptr, file, line, func); MALLOC_CHECK_ASSERT(ptr && sz); if (MALLOC_CHECK_API_R_SCRUB) { if (!(ret = malloc_check_malloc(sz, file, line, func))) return (NULL); if (sz >= MALLOC_CHECK_STORE.mem_vals[scan].sz) sz = MALLOC_CHECK_STORE.mem_vals[scan].sz; if (sz) memcpy(ret, ptr, sz); malloc_check_free(ptr, file, line, func); return (ret); } if (MALLOC_CHECK_DEC()) return (NULL); ret = realloc(ptr, sz); MALLOC_CHECK_ASSERT(ret); if (!ret) /* just in case */ return (NULL); if (MALLOC_CHECK_TRACE) fprintf(stderr, "mc_realloc(%p, %zu, %s, %u) = %p\n", ptr, sz, file, line, ret); /* note we can't scrub ... :( */ MALLOC_CHECK_STORE.mem_vals[scan].ptr = ret; MALLOC_CHECK_STORE.mem_vals[scan].sz = sz; MALLOC_CHECK_STORE.mem_vals[scan].file = file; MALLOC_CHECK_STORE.mem_vals[scan].line = line; MALLOC_CHECK_STORE.mem_vals[scan].func = func; return (ret); } static void malloc_check_empty(const char *file, unsigned int line, const char *func) { if (MALLOC_CHECK_PRINT && MALLOC_CHECK_STORE.mem_num) { unsigned int scan = 0; while (MALLOC_CHECK_STORE.mem_vals[scan].ptr) { /* NOTE: Using system *printf, so can't use %zu as Solaris is retarded */ fprintf(stderr," MEM CHECK NOT EMPTY: ptr %p, sz %lu, from %s:%u:%s\n", MALLOC_CHECK_STORE.mem_vals[scan].ptr, (unsigned long)MALLOC_CHECK_STORE.mem_vals[scan].sz, MALLOC_CHECK_STORE.mem_vals[scan].func, MALLOC_CHECK_STORE.mem_vals[scan].line, MALLOC_CHECK_STORE.mem_vals[scan].file); ++scan; } } malloc_check_assert(!MALLOC_CHECK_STORE.mem_num); } #endif #endif ustr-1.0.4/ustr-fmt-code.h0000644000076400007640000002153210754705714014360 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_FMT_H #error " Include ustr-fmt.h before this file." #endif #if USTR_CONF_HAVE_VA_COPY # if USTR_CONF_HAVE_RETARDED_VSNPRINTF USTR_CONF_i_PROTO int ustr__retard_vfmt_ret(const char *fmt, va_list ap) { size_t sz = USTR__RETARDED_SNPRINTF_MIN; char *ptr = 0; int ret = -1; va_list nap; if (USTR_CONF_VSNPRINTF_BEG != vsnprintf) return (-1); if (!(ptr = USTR_CONF_MALLOC(sz))) return (-1); USTR__VA_COPY(nap, ap); while ((ret = vsnprintf(ptr, sz, fmt, nap)) == -1) { char *tmp = 0; va_end(nap); sz *= 2; if ((sz >= USTR__RETARDED_SNPRINTF_MAX) || !(tmp = USTR_CONF_REALLOC(ptr, sz))) { USTR_CONF_FREE(ptr); return (-1); } USTR__VA_COPY(nap, ap); } va_end(nap); /* We could probably do the memcpy optimization here, with a bit of jumping * through hoops (and a different interface ... but I prefer the single code * path to sane platforms that I'm likely to be testing on. */ USTR_CONF_FREE(ptr); return (ret); } # endif USTR_CONF_i_PROTO int ustrp__add_vfmt_lim(struct Ustr_pool *p, struct Ustr **ps1, size_t lim, const char *fmt, va_list ap) { /* you might think we want to just use ustr_wstr() * if ustr_size() - ustr_len() > 0 ... however the problem there is about * screwing up the data when we fail. Which we just don't do */ char *tmp = 0; size_t os1len = 0; va_list nap; int rc = -1; char buf[USTR__SNPRINTF_LOCAL]; USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); USTR__VA_COPY(nap, ap); rc = USTR_CONF_VSNPRINTF_BEG(buf, sizeof(buf), fmt, nap); va_end(nap); if ((rc == -1) && ((rc = ustr__retard_vfmt_ret(fmt, ap)) == -1)) return (USTR_FALSE); if (lim && ((size_t)rc > lim)) rc = lim; if ((size_t)rc < sizeof(buf)) /* everything is done */ return (ustrp__add_buf(p, ps1, buf, rc)); os1len = ustr_len(*ps1); if (!ustrp__add_undef(p, ps1, rc)) return (USTR_FALSE); tmp = ustr_wstr(*ps1) + os1len; USTR_CONF_VSNPRINTF_END(tmp, rc + 1, fmt, ap); USTR_ASSERT(ustrp__assert_valid(!!p, *ps1)); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_add_vfmt_lim(struct Ustr **ps1, size_t lim, const char *fmt,va_list ap) { return (ustrp__add_vfmt_lim(0, ps1, lim, fmt, ap)); } USTR_CONF_I_PROTO int ustrp_add_vfmt_lim(struct Ustr_pool *p,struct Ustrp **ps1, size_t lim, const char *fmt,va_list ap) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__add_vfmt_lim(p, &tmp, lim, fmt, ap); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_I_PROTO int ustr_add_fmt_lim(struct Ustr **ps1, size_t lim, const char *fmt, ...) { va_list ap; int ret = -1; va_start(ap, fmt); ret = ustr_add_vfmt_lim(ps1, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustrp_add_fmt_lim(struct Ustr_pool *p, struct Ustrp **ps1, size_t lim, const char *fmt, ...) { va_list ap; int ret = -1; va_start(ap, fmt); ret = ustrp_add_vfmt_lim(p, ps1, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustr_add_vfmt(struct Ustr **ps1,const char*fmt,va_list ap) { return (ustr_add_vfmt_lim(ps1, 0, fmt, ap)); } USTR_CONF_I_PROTO int ustrp_add_vfmt(struct Ustr_pool *p, struct Ustrp **ps1, const char *fmt, va_list ap) { return (ustrp_add_vfmt_lim(p, ps1, 0, fmt, ap)); } USTR_CONF_I_PROTO int ustr_add_fmt(struct Ustr **ps1, const char *fmt, ...) { va_list ap; int ret = -1; va_start(ap, fmt); ret = ustr_add_vfmt(ps1, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO int ustrp_add_fmt(struct Ustr_pool *p, struct Ustrp **ps1, const char *fmt, ...) { va_list ap; int ret = -1; va_start(ap, fmt); ret = ustrp_add_vfmt(p, ps1, fmt, ap); va_end(ap); return (ret); } USTR_CONF_i_PROTO struct Ustr *ustrp__dupx_vfmt_lim(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, size_t lim, const char *fmt, va_list ap) { /* NOTE: Copy and pasted so we don't have to allocate twice, just to get the * options */ struct Ustr *ret = USTR_NULL; va_list nap; int rc = -1; char buf[USTR__SNPRINTF_LOCAL]; USTR__VA_COPY(nap, ap); rc = USTR_CONF_VSNPRINTF_BEG(buf, sizeof(buf), fmt, nap); va_end(nap); if ((rc == -1) && ((rc = ustr__retard_vfmt_ret(fmt, ap)) == -1)) return (USTR_FALSE); if (lim && ((size_t)rc > lim)) rc = lim; if ((size_t)rc < sizeof(buf)) /* everything is done */ return (ustrp__dupx_buf(p, sz, rbytes, exact, emem, buf, rc)); if (!(ret = ustrp__dupx_undef(p, sz, rbytes, exact, emem, rc))) return (USTR_FALSE); USTR_CONF_VSNPRINTF_END(ustr_wstr(ret), rc + 1, fmt, ap); USTR_ASSERT(ustrp__assert_valid(!!p, ret)); return (ret); } USTR_CONF_I_PROTO struct Ustr *ustr_dupx_vfmt_lim(size_t sz, size_t rbytes, int exact, int emem,size_t lim,const char *fmt, va_list ap) { return (ustrp__dupx_vfmt_lim(0, sz, rbytes, exact, emem, lim, fmt, ap)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_dupx_vfmt_lim(struct Ustr_pool *p, size_t sz, size_t rb, int exact, int emem, size_t lim, const char *fmt, va_list ap) { return (USTRP(ustrp__dupx_vfmt_lim(p, sz, rb, exact, emem, lim, fmt, ap))); } USTR_CONF_I_PROTO struct Ustr *ustr_dupx_fmt_lim(size_t sz, size_t rbytes, int exact, int emem, size_t lim, const char *fmt, ...) { va_list ap; struct Ustr *ret = USTR_NULL; va_start(ap, fmt); ret = ustr_dupx_vfmt_lim(sz, rbytes, exact, emem, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustrp *ustrp_dupx_fmt_lim(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, size_t lim, const char *fmt, ...) { va_list ap; struct Ustrp *ret = USTRP_NULL; va_start(ap, fmt); ret = ustrp_dupx_vfmt_lim(p, sz, rbytes, exact, emem, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustr *ustr_dupx_vfmt(size_t sz, size_t rbytes, int exact, int emem, const char *fmt, va_list ap) { return (ustr_dupx_vfmt_lim(sz, rbytes, exact, emem, 0, fmt, ap)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_dupx_vfmt(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, const char *fmt, va_list ap) { return (ustrp_dupx_vfmt_lim(p, sz, rbytes, exact, emem, 0, fmt, ap)); } USTR_CONF_I_PROTO struct Ustr *ustr_dupx_fmt(size_t sz, size_t rbytes,int exact, int emem, const char *fmt, ...) { va_list ap; struct Ustr *ret = USTR_NULL; va_start(ap, fmt); ret = ustr_dupx_vfmt(sz, rbytes, exact, emem, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustrp *ustrp_dupx_fmt(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, const char *fmt, ...) { va_list ap; struct Ustrp *ret = USTRP_NULL; va_start(ap, fmt); ret = ustrp_dupx_vfmt(p, sz, rbytes, exact, emem, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustr *ustr_dup_vfmt_lim(size_t lim, const char *fmt, va_list ap) { return (ustr_dupx_vfmt_lim(USTR__DUPX_DEF, lim, fmt, ap)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_dup_vfmt_lim(struct Ustr_pool *p, size_t lim, const char *fmt, va_list ap) { return (ustrp_dupx_vfmt_lim(p, USTR__DUPX_DEF, lim, fmt, ap)); } USTR_CONF_I_PROTO struct Ustr *ustr_dup_fmt_lim(size_t lim, const char *fmt, ...) { va_list ap; struct Ustr *ret = USTR_NULL; va_start(ap, fmt); ret = ustr_dup_vfmt_lim(lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustrp *ustrp_dup_fmt_lim(struct Ustr_pool *p, size_t lim, const char *fmt, ...) { va_list ap; struct Ustrp *ret = USTRP_NULL; va_start(ap, fmt); ret = ustrp_dup_vfmt_lim(p, lim, fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustr *ustr_dup_vfmt(const char *fmt, va_list ap) { return (ustr_dupx_vfmt(USTR__DUPX_DEF, fmt, ap)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_dup_vfmt(struct Ustr_pool *p, const char *fmt, va_list ap) { return (ustrp_dupx_vfmt(p, USTR__DUPX_DEF, fmt, ap)); } USTR_CONF_I_PROTO struct Ustr *ustr_dup_fmt(const char *fmt, ...) { va_list ap; struct Ustr *ret = USTR_NULL; va_start(ap, fmt); ret = ustr_dup_vfmt(fmt, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustrp *ustrp_dup_fmt(struct Ustr_pool *p, const char *fmt, ...) { va_list ap; struct Ustrp *ret = USTRP_NULL; va_start(ap, fmt); ret = ustrp_dup_vfmt(p, fmt, ap); va_end(ap); return (ret); } #endif ustr-1.0.4/AUTHORS0000644000076400007640000000014010646000147012542 0ustar jamesjamesJames Antill Markus Kuhn - utf8 work. Paul Rosenfeld - ustr_sub / ustr_sc_sub / ustr_sc_replace ustr-1.0.4/ustr-replace-opt-code.c0000644000076400007640000000140410674563614015776 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-set.h" #include "ustr-srch.h" #include "ustr-sub.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-replace.h" ustr-1.0.4/README-DEVELOPERS0000644000076400007640000000624510645572675014057 0ustar jamesjames There are four main ways you, as a developer, can use this library: 1. Have a dependancy, #include and link with -lustr 2. Use pkg-config normally, like: $(pkg-config --cflags --libs ustr) 3. Run ustr-import -c all, once, and then add the ustr*.c files to your build system and #include "ustr.h" 4. Run ustr-import all, once, and then just #include "ustr.h" -------------------------------------------- If you want to add something to this library -------------------------------------------- Probably the first thing to do is: git clone http://www.and.org/ustr/ustr.git ...then you unless what you're doing obviously fits into one of the existing files create a new namespace, lets say ustr-foo, to do that create the files: ustr-foo.h ustr-foo-code.h ustr-foo-dbg-code.c ustr-foo-opt-code.c ...and possibly, if you want another ustr-* namespace to be able to access your internal functions: ustr-foo-internal.h ...the easiest way to make them is to copy the top and bottom from say ustr-srch* and change the names to protect the innocent :). When creating functions there are six pre-defined constants you should use: USTR_CONF_E_PROTO This is the one for the extern definition USTR_CONF_I_PROTO This is the one for the implementation USTR_CONF_EI_PROTO This is the one for the extern definition, when you want inline'ing in the library. USTR_CONF_II_PROTO This is the one for the implementation, when you want inline'ing in the library. USTR_CONF_e_PROTO This is the one for the extern definition, for internal symbols. USTR_CONF_i_PROTO This is the one for the implementation, for internal symbols. When creating functions they are usually done in a set, so for every one task you want to do you create about five or six functions: ustr_add; ustr_add_buf; ustr_add_cstr; ustr_add_rep_chr; ustr_add_subustr; ustr_add_undef; A quick reference would be: *_undef() == malloc() / realloc(). *_buf() == *_undef() + memcpy() *_rep_chr() == *_undef() + memset() *_cstr() == strlen() + *_buf() *() == small optimizations or ustr_len() + *_buf(). *_subustr() == Like *() but with limits in the data. ...the current documentation also has them documented, to some extent. Next you'll want to alter the Makefile, again the easiest thing to do is search for something similar like "ustr_srch" and add your file to each variable. You should also do the same for examples/Makefile, if any of the examples will use the new functions. You then want to add your namespace to the end of the file lists in: scripts/list_functions_src.pl scripts/gen_doc_templ_from_protos.pl ...after which you can run: ./scripts/cmp_symbols_ver.sh ...to see what symbols you need to add to the linker map file, and: ./scripts/cmp_symbols_doc.sh ...to see which functions aren't documented. You can add unit tests as T/*.c, the ones begining with ctst_*.c are linked against a local library and T/tst_*.c use just the header files (and the C source for them is generated by appending the ctst_*.c file of the same name). After all that you can run: ./scripts/coverage.sh ...which will generate a testing coverage report, using lcov, in the directory ./lcov-output/lib ustr-1.0.4/ustr-cmp-code.h0000644000076400007640000001166210673041563014347 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_CMP_H #error " You should have already included ustr-cmp.h, or just include ustr.h." #endif USTR_CONF_I_PROTO int ustr_cmp_buf(const struct Ustr *s1, const void *buf, size_t len2) { size_t len1 = 0; size_t lenm = 0; int ret = 0; int def = 0; USTR_ASSERT(ustr_assert_valid(s1) && buf); len1 = ustr_len(s1); if (len1 == len2) return (memcmp(ustr_cstr(s1), buf, len1)); if (len1 > len2) { lenm = len2; def = 1; } else { lenm = len1; def = -1; } if (lenm && (ret = memcmp(ustr_cstr(s1), buf, lenm))) return (ret); return (def); } USTR_CONF_I_PROTO int ustr_cmp_subustr(const struct Ustr *s1, const struct Ustr *s2, size_t pos, size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_cmp_buf(s1, "", 0)); return (ustr_cmp_buf(s1, ustr_cstr(s2) + --pos, len)); } USTR_CONF_i_PROTO int ustr__memcasecmp(const void *passed_s1, const void *passed_s2, size_t len) { const unsigned char *s1 = passed_s1; const unsigned char *s2 = passed_s2; while (len) { unsigned char c1 = *s1; unsigned char c2 = *s2; if ((c1 >= 0x61) && (c1 <= 0x7a)) c1 ^= 0x20; if ((c2 >= 0x61) && (c2 <= 0x7a)) c2 ^= 0x20; if (c1 != c2) return (c1 - c2); ++s1; ++s2; --len; } return (0); } USTR_CONF_I_PROTO int ustr_cmp_case_buf(const struct Ustr *s1, const void *buf, size_t len2) { size_t len1 = 0; size_t lenm = 0; int ret = 0; int def = 0; USTR_ASSERT(ustr_assert_valid(s1) && buf); len1 = ustr_len(s1); if (len1 == len2) return (ustr__memcasecmp(ustr_cstr(s1), buf, len1)); if (len1 > len2) { lenm = len2; def = 1; } else { lenm = len1; def = -1; } if (lenm && (ret = ustr__memcasecmp(ustr_cstr(s1), buf, lenm))) return (ret); return (def); } USTR_CONF_I_PROTO int ustr_cmp_case_subustr(const struct Ustr *s1, const struct Ustr *s2, size_t pos, size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_cmp_case_buf(s1, "", 0)); return (ustr_cmp_case_buf(s1, ustr_cstr(s2) + --pos, len)); } USTR_CONF_I_PROTO int ustr_cmp_case_prefix_buf_eq(const struct Ustr *s1, const void *buf, size_t len2) { size_t len1 = 0; USTR_ASSERT(ustr_assert_valid(s1) && buf); len1 = ustr_len(s1); if (len1 < len2) return (USTR_FALSE); return (!ustr__memcasecmp(ustr_cstr(s1), buf, len2)); } USTR_CONF_I_PROTO int ustr_cmp_case_suffix_buf_eq(const struct Ustr *s1, const void *buf, size_t len2) { size_t len1 = 0; USTR_ASSERT(ustr_assert_valid(s1) && buf); len1 = ustr_len(s1); if (len1 < len2) return (USTR_FALSE); return (!ustr__memcasecmp(ustr_cstr(s1) + (len1 - len2), buf, len2)); } USTR_CONF_I_PROTO int ustr_cmp_fast_subustr(const struct Ustr *s1, const struct Ustr *s2, size_t pos, size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_cmp_fast_buf(s1, "", 0)); return (ustr_cmp_fast_buf(s1, ustr_cstr(s2) + --pos, len)); } USTR_CONF_I_PROTO int ustr_cmp_prefix_subustr_eq(const struct Ustr *s1, const struct Ustr *s2, size_t pos, size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_cmp_prefix_buf_eq(s1, "", 0)); return (ustr_cmp_prefix_buf_eq(s1, ustr_cstr(s2) + --pos, len)); } USTR_CONF_I_PROTO int ustr_cmp_suffix_subustr_eq(const struct Ustr *s1, const struct Ustr *s2, size_t pos, size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_cmp_suffix_buf_eq(s1, "", 0)); return (ustr_cmp_suffix_buf_eq(s1, ustr_cstr(s2) + --pos, len)); } USTR_CONF_I_PROTO int ustr_cmp_case_prefix_subustr_eq(const struct Ustr *s1, const struct Ustr *s2,size_t pos,size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_cmp_case_prefix_buf_eq(s1, "", 0)); return (ustr_cmp_case_prefix_buf_eq(s1, ustr_cstr(s2) + --pos, len)); } USTR_CONF_I_PROTO int ustr_cmp_case_suffix_subustr_eq(const struct Ustr *s1, const struct Ustr *s2,size_t pos,size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_cmp_case_suffix_buf_eq(s1, "", 0)); return (ustr_cmp_case_suffix_buf_eq(s1, ustr_cstr(s2) + --pos, len)); } ustr-1.0.4/ustr-sc-internal.h0000644000076400007640000000543410755652434015105 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SC_INTERNAL_H #define USTR_SC_INTERNAL_H 1 #ifndef USTR_SC_H # error " You should have already included ustr-sc.h, or just include ustr.h" #endif USTR_CONF_e_PROTO struct Ustr *ustrp__sc_dupx(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, struct Ustr **ps1) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); USTR_CONF_e_PROTO struct Ustr *ustrp__sc_dup(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO void ustrp__sc_free_shared(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO void ustr__reverse(char *ptr, size_t pos, size_t len) USTR__COMPILE_ATTR_NONNULL_A(); #ifdef USTR_UTF8_H USTR_CONF_e_PROTO int ustrp__sc_utf8_reverse(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); #endif USTR_CONF_e_PROTO int ustrp__sc_reverse(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__sc_tolower(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__sc_toupper(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO char *ustrp__sc_export_subustr(struct Ustr_pool *, const struct Ustr *, size_t, size_t, void *(*)(size_t)) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__sc_ltrim_chrs(struct Ustr_pool *, struct Ustr **,const char *,size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__sc_rtrim_chrs(struct Ustr_pool *, struct Ustr **,const char *,size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__sc_trim_chrs(struct Ustr_pool *, struct Ustr **,const char *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO struct Ustr *ustrp__sc_vjoinx(struct Ustr_pool *, size_t, size_t, int, int, const struct Ustr *, const struct Ustr *, const struct Ustr *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6, 7, 8)); USTR_CONF_e_PROTO struct Ustr *ustrp__sc_vconcatx(struct Ustr_pool *, size_t, size_t, int, int, const struct Ustr *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); #endif ustr-1.0.4/ustr-ins-dbg-code.c0000644000076400007640000000133110674563614015105 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-fmt.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-ins.h" ustr-1.0.4/ustr-conf.h.in0000644000076400007640000000414310707036227014205 0ustar jamesjames#ifndef USTR_CONF_H #define USTR_CONF_H 1 /* this is the custom version for the library itself, for everyone else * ustr-import generates one depending on the options. */ /* The default is now to link against libc. */ #ifndef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #endif /* We can't: if defined(__GLIBC__) && (!defined(_GNU_SOURCE) || !_GNU_SOURCE) * because by the time we've included a libc header it's too late. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif /* maybe move memmem / memrchr here? */ #if ! USTR_CONF_INCLUDE_CODEONLY_HEADERS /* If you aren't just using the headers, these should match the .c's */ # define USTR_CONF_HAVE_64bit_SIZE_MAX @HAVE_64bit_SIZE_MAX@ # define USTR_CONF_HAVE_RETARDED_VSNPRINTF @HAVE_RETARDED_VSNPRINTF@ # define USTR_CONF_HAVE_STDINT_H @HAVE_STDINT_H@ # define USTR_CONF_HAVE_DYNAMIC_CONF 1 # define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF # define USTR_CONF_REF_BYTES 1 # define USTR_CONF_EXACT_BYTES 0 # define USTR_CONF_USE_SIZE 0 # define USTR_CONF_USE_ASSERT @USE_ASSERT@ # define USTR_CONF_USE_EOS_MARK @USE_EOS_MARK@ #else /* Same defaults, but can be altered at will. */ /* Note that you really shouldn't alter the _HAVE_* ones, but whatever */ # ifndef USTR_CONF_HAVE_64bit_SIZE_MAX # define USTR_CONF_HAVE_64bit_SIZE_MAX @HAVE_64bit_SIZE_MAX@ # endif # ifndef USTR_CONF_HAVE_RETARDED_VSNPRINTF # define USTR_CONF_HAVE_RETARDED_VSNPRINTF @HAVE_RETARDED_VSNPRINTF@ # endif # ifndef USTR_CONF_HAVE_STDINT_H # define USTR_CONF_HAVE_STDINT_H @HAVE_STDINT_H@ # endif # ifndef USTR_CONF_HAVE_DYNAMIC_CONF # define USTR_CONF_HAVE_DYNAMIC_CONF 1 # endif /* no USE_DYNAMIC_CONF ... use default in ustr-main.h */ # ifndef USTR_CONF_REF_BYTES # define USTR_CONF_REF_BYTES 1 # endif # ifndef USTR_CONF_EXACT_BYTES # define USTR_CONF_EXACT_BYTES 0 # endif # ifndef USTR_CONF_USE_SIZE # define USTR_CONF_USE_SIZE 0 # endif # ifndef USTR_CONF_USE_ASSERT # define USTR_CONF_USE_ASSERT @USE_ASSERT@ # endif # ifndef USTR_CONF_USE_EOS_MARK # define USTR_CONF_USE_EOS_MARK @USE_EOS_MARK@ # endif #endif #endif ustr-1.0.4/ustr.spec0000644000076400007640000001310410763663475013372 0ustar jamesjames %define show_all_cmds 0 %define broken_fed_dbg_opts 0 %define multilib_inst 1 %if %{show_all_cmds} %define policy_cflags_hide HIDE= %else %define policy_cflags_hide %{nil} %endif %if %{broken_fed_dbg_opts} # Variable name explains itself. %define policy_cflags_broken DBG_ONLY_BAD_POLICIES_HAVE_THIS_EMPTY_CFLAGS= %else %define policy_cflags_broken %{nil} %endif %define policy_cflags %{policy_cflags_hide} %{policy_cflags_broken} %if %{multilib_inst} %define ustr_make_install install-multilib-linux %else %define ustr_make_install install %endif Name: ustr Version: 1.0.4 Release: 1%{?dist} Summary: String library, very low memory overhead, simple to import Group: System Environment/Libraries License: MIT or LGPLv2+ or BSD URL: http://www.and.org/ustr/ Source0: http://www.and.org/ustr/%{version}/%{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) # BuildRequires: make gcc sed %description Micro string library, very low overhead from plain strdup() (Ave. 44% for 0-20B strings). Very easy to use in existing C code. At it's simplest you can just include a single header file into your .c and start using it. This package also distributes pre-built shared libraries. %package devel Summary: Development files for %{name} Group: Development/Libraries # This isn't required, but Fedora policy makes it so Requires: pkgconfig >= 0.14 Requires: %{name} = %{version}-%{release} %description devel Header files for the Ustr string library, and the .so to link with. Also includes a %{name}.pc file for pkg-config usage. Includes the ustr-import tool, for if you jsut want to include the code in your projects ... you don't have to link to the shared lib. %package static Summary: Static development files for %{name} Group: Development/Libraries Requires: %{name}-devel = %{version}-%{release} %description static Static library for the Ustr string library. %package debug Summary: Development files for %{name}, with debugging options turned on Group: Development/Libraries # This isn't required, but Fedora policy makes it so Requires: pkgconfig >= 0.14 Requires: %{name}-devel = %{version}-%{release} %description debug Header files and dynamic libraries for a debug build of the Ustr string library. Also includes a %{name}-debug.pc file for pkg-config usage. %package debug-static Summary: Static development files for %{name}, with debugging options turned on Group: Development/Libraries Requires: %{name}-debug = %{version}-%{release} %description debug-static Static library for the debug build of the Ustr string library. %prep %setup -q %build make %{?_smp_mflags} all-shared CFLAGS="${CFLAGS:-%optflags}" %{policy_cflags} %check %if %{?chk}%{!?chk:1} make %{?_smp_mflags} check CFLAGS="${CFLAGS:-%optflags}" %{policy_cflags} %endif %install rm -rf $RPM_BUILD_ROOT make $@ %{ustr_make_install} prefix=%{_prefix} \ bindir=%{_bindir} mandir=%{_mandir} \ datadir=%{_datadir} libdir=%{_libdir} \ includedir=%{_includedir} libexecdir=%{_libexecdir} \ DESTDIR=$RPM_BUILD_ROOT LDCONFIG=/bin/true HIDE= %clean rm -rf $RPM_BUILD_ROOT %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %post debug -p /sbin/ldconfig %postun debug -p /sbin/ldconfig %files %defattr(-,root,root,-) %{_libdir}/libustr-1.0.so.* %doc ChangeLog LICENSE* README NEWS %files devel %defattr(-,root,root,-) %{_datadir}/ustr-%{version} %{_bindir}/ustr-import %if %{multilib_inst} %{_libexecdir}/ustr-%{version}/ustr-import* %endif %{_includedir}/ustr.h %{_includedir}/ustr-*.h %exclude %{_includedir}/ustr*debug*.h %{_libdir}/pkgconfig/ustr.pc %{_libdir}/libustr.so %{_datadir}/doc/ustr-devel-%{version} %{_mandir}/man1/* %{_mandir}/man3/* %files static %{_libdir}/libustr.a %files debug %defattr(-,root,root,-) %{_libdir}/libustr-debug-1.0.so.* %{_libdir}/libustr-debug.so %{_includedir}/ustr*debug*.h %{_libdir}/pkgconfig/ustr-debug.pc %files debug-static %{_libdir}/libustr-debug.a %changelog * Mon Oct 29 2007 James Antill - 1.0.2-1 - New release * Tue Aug 28 2007 James Antill - 1.0.1-6 - Add options for fedora policy brokeness, so it's easy to undo. - Rebuild for buildid. * Wed Aug 8 2007 James Antill - 1.0.1-5 - Import fix for ustr-import, wrt. repl <=> replace * Sun Aug 5 2007 James Antill - 1.0.1-4 - Patches for minor GIT HEAD documentation fixes. - Install mkdir_p and fgrep examples. * Sat Aug 4 2007 James Antill - 1.0.1-2 - First upload to Fedora repos. * Fri Aug 3 2007 James Antill - 1.0.1-0.10.fc7 - Re-fix dups in -devel and -debug file lists. - Change license to new format * Thu Aug 2 2007 James Antill - 1.0.1-0.9.fc7 - Fix dups in -devel and -debug file lists. * Wed Aug 1 2007 James Antill - 1.0.1-0.8.fc7 - Required to make DBG_ONLY_BAD_POLICIES_HAVE_THIS_EMPTY_CFLAGS empty - due to so called "review" * Fri Jul 27 2007 James Antill - 1.0.1-0.2.fc7 - Next test release of 1.0.1, lots of fixes from Fedora review. * Wed Jul 25 2007 James Antill - 1.0.1-0 - Test release of 1.0.1. * Wed Jul 11 2007 James Antill - 1.0.0-1 - Upgrade to 1.0.0 - Minor fixes on specfile * Sun Jun 3 2007 James Antill - 0.99.2-1 - Upgrade to 0.99.2 * Thu May 24 2007 James Antill - 0.99.1-2 - Fix ver typo to be version. * Fri May 18 2007 James Antill - 0.99.1-1 - Use all-shared to get GCC-ish specific shared libs. * Mon May 14 2007 James Antill - 0.98.1-0 - Initial spec ustr-1.0.4/NEWS0000644000076400007640000000262610763650630012214 0ustar jamesjames1.0.4 - 2008-03-05 Fix bug in ustr_cspn_chr_rev. Added join/concat functions. Better multilib. support. Make sub/ins/replace work with non-ref'd self. More docs. 1.0.3 - 2008-01-14 Added trim functions. Multi-lib support. Added support to swap out system vsnprintf calls. Don't delete sized Ustr's when we don't need to. Added linecat example. 1.0.2 - 2007-10-29 Documentation improvements. Added some more functions, for ASCII caseless compare/search, exporting data from a ustr easily and getting a ustr's configuration. Integrated malloc checking into the library itself, making debugging much easier. Added some new examples and a tutorial. Some bugfixes. 1.0.1 - 2007-08-04 Documentation improvements. Add a lot of new functions: insert, replace, split, substitute, io_getdelim and more. Build fixes for win32. Fedora review for rpms. 1.0.0 - 2007-07-13 Lots of API and implementation fixes. Lots of documentation. Now has 100% code coverage. 0.99.3 - 2007-06-24 Added lots of functions, including utf8 and parsing integers. Increased unit test coverage to over 99%. Added "hexdump" and "nums" example programs. Remove internal functions from linker export map. 0.99.2 - 2007-06-03 Added IO functions. Added runtime configuration for libraries. Many bugfixes. Cleanup documentation. Added some examples. Started API reference documentation. 0.99.1 - 2007-05-23 First real release. ustr-1.0.4/ustr-split-opt-code.c0000644000076400007640000000140210674563614015514 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-set.h" #include "ustr-spn.h" #include "ustr-srch.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-split.h" ustr-1.0.4/ustr-replace-code.h0000644000076400007640000002271010755423427015203 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_REPLACE_H #error " Include ustr-replace.h before this file." #endif USTR_CONF_i_PROTO size_t ustrp__replace_inline_buf(struct Ustr_pool *p, struct Ustr **ps1, const void *optr, size_t olen, const void *nptr, size_t nlen, size_t lim) { /* "fast path" ... we can't fail, so ignore the return values */ size_t num = 0; size_t pos = 0; USTR_ASSERT(ustr_owner(*ps1)); USTR_ASSERT((nlen == olen) || !ustr_alloc(*ps1)); while ((pos = ustr_srch_buf_fwd(*ps1, pos, optr, olen))) { USTR_ASSERT((nlen == olen) || (ustr_fixed(*ps1) && (ustr_size(*ps1) >= (ustr_len(*ps1) + (nlen - olen))))); ustrp__sc_sub_buf(p, ps1, pos, olen, nptr, nlen); pos += nlen - 1; ++num; if (lim && (num == lim)) break; } if (!num) errno = 0; /* only way to tell between FAILURE and NO REPLACEMENTS */ return (num); } USTR_CONF_i_PROTO size_t ustrp__replace_buf(struct Ustr_pool *p, struct Ustr **ps1, const void *optr, size_t olen, const void *nptr, size_t nlen, size_t lim) { size_t num = 0; size_t tlen = 0; size_t pos = 0; struct Ustr *ret = USTR_NULL; const char *rptr; size_t lpos = 0; size_t roff = 0; USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); if ((nlen == olen) && ustr_owner(*ps1)) return (ustrp__replace_inline_buf(p, ps1, optr, olen, nptr, nlen, lim)); /* pre-calc size, and do single alloc and then memcpy. * Using dup()/ustr_sc_sub() is much simpler but very slow * for large strings. */ tlen = ustr_len(*ps1); while ((pos = ustr_srch_buf_fwd(*ps1, pos, optr, olen))) { pos += olen - 1; if (nlen < olen) /* can go up or down */ tlen -= (olen - nlen); else { if (tlen > (tlen + (nlen - olen))) { errno = USTR__ENOMEM; return (0); } tlen += (nlen - olen); } ++num; if (lim && (num == lim)) break; } if (!num) /* minor speed hack */ { errno = 0; /* only way to tell between FAILURE and NO REPLACEMENTS */ return (0); } if (!tlen) /* minor speed hack */ return (ustrp__del(p, ps1, ustr_len(*ps1)) ? num : 0); if (ustr_fixed(*ps1) && ((num <= 2) || ustr_limited(*ps1))) { /* if we will have to memmove() a lot, double copy */ if (tlen <= ustr_size(*ps1)) return (ustrp__replace_inline_buf(p, ps1, optr, olen, nptr, nlen, lim)); if (ustr_limited(*ps1)) goto fail_alloc; } if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(*ps1), tlen))) goto fail_alloc; rptr = ustr_cstr(*ps1); lpos = 1; roff = 0; pos = 0; num = 0; while ((pos = ustr_srch_buf_fwd(*ps1, pos, optr, olen))) { const char *tptr = rptr + roff; size_t blen = pos - (roff + 1); pos += olen - 1; USTR_ASSERT(pos == (roff + blen + olen)); ustrp__sub_buf(p, &ret, lpos, tptr, blen); lpos += blen; ustrp__sub_buf(p, &ret, lpos, nptr, nlen); lpos += nlen; roff = pos; ++num; if (lim && (num == lim)) break; } ustrp__sub_buf(p, &ret, lpos, rptr + roff, ustr_len(*ps1) - roff); if (!ustr_fixed(*ps1) || (tlen > ustr_size(*ps1))) ustrp__sc_free2(p, ps1, ret); else { /* fixed buffer, with multiple replacements ... but fits */ ustrp__set(p, ps1, ret); ustrp__free(p, ret); } return (num); fail_alloc: ustr_setf_enomem_err(*ps1); return (0); } USTR_CONF_I_PROTO size_t ustr_replace_buf(struct Ustr **ps1, const void *optr, size_t olen, const void *nptr, size_t nlen, size_t lim) { return (ustrp__replace_buf(0, ps1, optr, olen, nptr, nlen, lim)); } USTR_CONF_I_PROTO size_t ustrp_replace_buf(struct Ustr_pool *p, struct Ustrp **ps1, const void *optr, size_t olen, const void *nptr, size_t nlen, size_t lim) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__replace_buf(p, &tmp, optr, olen, nptr, nlen, lim); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO size_t ustrp__replace(struct Ustr_pool *p, struct Ustr **ps1, const struct Ustr *srch, const struct Ustr *repl, size_t lim) { struct Ustr *t1 = USTR_NULL; struct Ustr *t2 = USTR_NULL; size_t ret = 0; USTR_ASSERT(ustrp__assert_valid(!!p, srch)); USTR_ASSERT(ustrp__assert_valid(!!p, repl)); if (srch == *ps1) srch = t1 = ustrp__dup(p, *ps1); if (repl == *ps1) repl = t2 = ustrp__dup(p, *ps1); if (srch && repl) ret = ustrp__replace_buf(p, ps1, ustr_cstr(srch), ustr_len(srch), ustr_cstr(repl), ustr_len(repl), lim); ustrp__free(p, t1); ustrp__free(p, t2); return (ret); } USTR_CONF_I_PROTO size_t ustr_replace(struct Ustr **ps1, const struct Ustr *srch, const struct Ustr *repl, size_t lim) { return (ustrp__replace(0, ps1, srch, repl, lim)); } USTR_CONF_I_PROTO size_t ustrp_replace(struct Ustr_pool *p, struct Ustrp **ps1, const struct Ustrp *srch, const struct Ustrp *repl, size_t lim) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__replace(p, &tmp, &srch->s, &repl->s, lim); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO size_t ustrp__replace_inline_rep_chr(struct Ustr_pool *p, struct Ustr **ps1, char odata, size_t olen, char ndata, size_t nlen, size_t lim) { /* "fast path" ... as we can't fail after we are the owner(). In theory * we can do nlen <= olen, but then we'll spend a lot of time calling * memmove(). Which might be painful, so let that fall through to dupx(). */ size_t num = 0; size_t pos = 0; USTR_ASSERT(ustr_owner(*ps1)); USTR_ASSERT((nlen == olen) || !ustr_alloc(*ps1)); while ((pos = ustr_srch_rep_chr_fwd(*ps1, pos, odata, olen))) { USTR_ASSERT((nlen == olen) || (ustr_fixed(*ps1) && (ustr_size(*ps1) >= (ustr_len(*ps1) + (nlen - olen))))); ustrp__sc_sub_rep_chr(p, ps1, pos, olen, ndata, nlen); pos += nlen - 1; ++num; if (lim && (num == lim)) break; } if (!num) errno = 0; /* only way to tell between FAILURE and NO REPLACEMENTS */ return (num); } USTR_CONF_i_PROTO size_t ustrp__replace_rep_chr(struct Ustr_pool *p, struct Ustr **ps1, char odata, size_t olen, char ndata, size_t nlen, size_t lim) { size_t num = 0; size_t tlen = 0; size_t pos = 0; struct Ustr *ret = USTR_NULL; const char *rptr; size_t lpos = 0; size_t roff = 0; USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); if ((nlen == olen) && ustr_owner(*ps1)) return (ustrp__replace_inline_rep_chr(p, ps1, odata,olen, ndata,nlen, lim)); /* pre-calc size, and do single alloc and then memcpy. * Using dup()/ustr_sc_sub() is much simpler but very slow * for large strings. */ tlen = ustr_len(*ps1); while ((pos = ustr_srch_rep_chr_fwd(*ps1, pos, odata, olen))) { pos += olen - 1; if (nlen < olen) /* can go up or down */ tlen -= (olen - nlen); else { if (tlen > (tlen + (nlen - olen))) { errno = USTR__ENOMEM; return (0); } tlen += (nlen - olen); } ++num; if (lim && (num == lim)) break; } if (!num) /* minor speed hack */ { errno = 0; /* only way to tell between FAILURE and NO REPLACEMENTS */ return (0); } if (!tlen) /* minor speed hack */ return (ustrp__del(p, ps1, ustr_len(*ps1)) ? num : 0); if (ustr_fixed(*ps1) && ((num <= 2) || ustr_limited(*ps1))) { /* if we will have to memmove() a lot, double copy */ if (tlen <= ustr_size(*ps1)) return (ustrp__replace_inline_rep_chr(p, ps1, odata,olen,ndata,nlen,lim)); if (ustr_limited(*ps1)) goto fail_alloc; } if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(*ps1), tlen))) goto fail_alloc; rptr = ustr_cstr(*ps1); lpos = 1; roff = 0; pos = 0; num = 0; while ((pos = ustr_srch_rep_chr_fwd(*ps1, pos, odata, olen))) { const char *tptr = rptr + roff; size_t blen = pos - (roff + 1); pos += olen - 1; USTR_ASSERT(pos == (roff + blen + olen)); ustrp__sub_buf(p, &ret, lpos, tptr, blen); lpos += blen; ustrp__sub_rep_chr(p, &ret, lpos, ndata, nlen); lpos += nlen; roff = pos; ++num; if (lim && (num == lim)) break; } ustrp__sub_buf(p, &ret, lpos, rptr + roff, ustr_len(*ps1) - roff); if (!ustr_fixed(*ps1) || (tlen > ustr_size(*ps1))) ustrp__sc_free2(p, ps1, ret); else { /* fixed buffer, with multiple replacements ... but fits */ ustrp__set(p, ps1, ret); ustrp__free(p, ret); } return (num); fail_alloc: ustr_setf_enomem_err(*ps1); return (0); } USTR_CONF_I_PROTO size_t ustr_replace_rep_chr(struct Ustr **ps1, char odata, size_t olen, char ndata, size_t nlen, size_t lim) { return (ustrp__replace_rep_chr(0, ps1, odata, olen, ndata, nlen, lim)); } USTR_CONF_I_PROTO size_t ustrp_replace_rep_chr(struct Ustr_pool *p, struct Ustrp **ps1, char odata, size_t olen, char ndata, size_t nlen, size_t lim) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__replace_rep_chr(p, &tmp, odata, olen, ndata, nlen, lim); *ps1 = USTRP(tmp); return (ret); } ustr-1.0.4/ustr-parse-dbg-code.c0000644000076400007640000000130510674563614015427 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-parse.h" ustr-1.0.4/autoconf_vsnprintf.c0000644000076400007640000000573210630111754015601 0ustar jamesjames#include #include #include #include #include #define USE_FMT_1_3 0 static int my_autoconf(const char *fmt, ...) { va_list ap; char buf[1] = ""; int ret = -1; va_start(ap, fmt); ret = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); return (ret); } #if 0 static char *my_fmt0(const char *fmt, ...) { char *tmp = NULL; va_list ap; int ret = -1; size_t lim = 32; char buf[1024] = ""; va_start(ap, fmt); ret = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); printf("fmt0\n"); printf("%d\n", ret); if (ret == -1) return (NULL); if ((size_t)ret > lim) return (NULL); if (!(tmp = malloc(ret + 1))) exit(1); va_start(ap, fmt); ret = vsnprintf(tmp, ret + 1, fmt, ap); /* assuming it works now */ va_end(ap); printf("%d\n", ret); printf("\n"); return (tmp); } static char *my_fmt1(const char *fmt, ...) { char *tmp = NULL; va_list ap; int ret = -1; size_t sz = 1; printf("fmt1\n"); if (!(tmp = malloc(sz))) exit(1); tmp[0] = 0; va_start(ap, fmt); while ((ret = vsnprintf(tmp, sz, fmt, ap)) == -1) { printf("%d - %lu\n", ret, (unsigned long)strlen(tmp)); sz <<= 1; if (!(tmp = realloc(tmp, sz))) exit(1); if (sz > 1024) exit(2); va_end(ap); va_start(ap, fmt); } va_end(ap); if (sz <= (unsigned)ret) { sz = ret + 1; if (!(tmp = realloc(tmp, sz))) exit(1); va_start(ap, fmt); ret = vsnprintf(tmp, sz, fmt, ap); va_end(ap); } printf("%d\n", ret); printf("\n"); return (tmp); } #endif #if USE_FMT_1_3 static char *myx_vfmt(size_t lim, const char *fmt, va_list ap) { char *tmp = NULL; va_list nap; int ret = -1; va_copy(nap, ap); ret = vsnprintf(NULL, 0, fmt, nap); va_end(nap); printf("%d\n", ret); if (ret == -1) return (NULL); if ((size_t)ret > lim) return (NULL); if (!(tmp = malloc(ret + 1))) { errno = ENOMEM; /* for EILSEQ etc. */ return (NULL); } ret = vsnprintf(tmp, ret + 1, fmt, ap); /* assuming it works now */ printf("%d\n", ret); printf("\n"); return (tmp); } static char *my_fmt2(const char *fmt, ...) { va_list ap; char *ret = NULL; va_start(ap, fmt); ret = myx_vfmt(32, fmt, ap); va_end(ap); return (ret); } static char *my_vfmt(const char *fmt, va_list ap) { return (myx_vfmt(32, fmt, ap)); } static char *my_fmt3(const char *fmt, ...) { va_list ap; char *ret = NULL; va_start(ap, fmt); ret = my_vfmt(fmt, ap); va_end(ap); return (ret); } #endif int main(void) { #if 0 char *tmp0 = my_fmt0("a b %d c d", 42); char *tmp1 = my_fmt1("a b %d c d", 42); #if USE_FMT_1_3 char *tmp2 = my_fmt2("a b %d c d", 42); char *tmp3 = my_fmt3("a b %d c d", 42); #endif if (tmp0) puts(tmp0); free(tmp0); if (tmp1) puts(tmp1); free(tmp1); #if USE_FMT_1_3 if (tmp2) puts(tmp2); free(tmp2); if (tmp3) puts(tmp3); free(tmp3); #endif #endif if (my_autoconf("12") == -1) puts("1"); else puts("0"); return 0; } ustr-1.0.4/ustr.h0000644000076400007640000000102410722116014012636 0ustar jamesjames#ifndef USTR_H #define USTR_H 1 #ifndef USTR_DEBUG #define USTR_DEBUG 0 #endif #if USTR_DEBUG # include "ustr-conf-debug.h" #else # include "ustr-conf.h" #endif #include "ustr-main.h" #include "ustr-b.h" #include "ustr-cmp.h" #include "ustr-fmt.h" #include "ustr-io.h" #include "ustr-ins.h" #include "ustr-parse.h" #include "ustr-pool.h" #include "ustr-set.h" #include "ustr-srch.h" #include "ustr-utf8.h" #include "ustr-spn.h" #include "ustr-sub.h" #include "ustr-replace.h" #include "ustr-split.h" #include "ustr-sc.h" #endif ustr-1.0.4/ustr-sc.h0000644000076400007640000003114410755652554013273 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SC_H #define USTR_SC_H 1 #ifndef USTR_MAIN_H # error " You should include ustr-main.h before this file, or just ustr.h" #endif USTR_CONF_E_PROTO struct Ustr *ustr_sc_dupx(size_t, size_t, int, int, struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustr *ustr_sc_dup(struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO void ustr_sc_free_shared(struct Ustr **) USTR__COMPILE_ATTR_NONNULL_A(); /* USTR_CONF_E_PROTO struct Ustr *ustr_sc_reconf(struct Ustr **, size_t, size_t, int, int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); */ USTR_CONF_E_PROTO int ustr_sc_reverse(struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #ifdef USTR_UTF8_H USTR_CONF_E_PROTO int ustr_sc_utf8_reverse(struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #endif USTR_CONF_E_PROTO int ustr_sc_tolower(struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sc_toupper(struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO char *ustr_sc_export_subustr(const struct Ustr*,size_t,size_t, void *(*)(size_t)) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO char *ustr_sc_export(const struct Ustr *, void *(*)(size_t)) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sc_ltrim_chrs(struct Ustr **, const char *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_sc_ltrim(struct Ustr **, const struct Ustr *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_sc_ltrim_cstr(struct Ustr **, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sc_rtrim_chrs(struct Ustr **, const char *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_sc_rtrim(struct Ustr **, const struct Ustr *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_sc_rtrim_cstr(struct Ustr **, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustr_sc_trim_chrs(struct Ustr **, const char *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_sc_trim(struct Ustr **, const struct Ustr *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_EI_PROTO int ustr_sc_trim_cstr(struct Ustr **, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO struct Ustr *ustr_sc_vjoin(const struct Ustr *, const struct Ustr *, const struct Ustr *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 2,3)); USTR_CONF_E_PROTO struct Ustr *ustr_sc_join(const struct Ustr *, const struct Ustr *, const struct Ustr *, ...) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1, 2, 3)) USTR__COMPILE_ATTR_SENTINEL(0); USTR_CONF_E_PROTO struct Ustr *ustr_sc_vjoinx(size_t, size_t, int, int, const struct Ustr *, const struct Ustr *, const struct Ustr *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((5, 6,7)); USTR_CONF_E_PROTO struct Ustr *ustr_sc_joinx(size_t, size_t, int, int, const struct Ustr *, const struct Ustr *, const struct Ustr *, ...) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((5, 6, 7)) USTR__COMPILE_ATTR_SENTINEL(0); USTR_CONF_E_PROTO struct Ustr *ustr_sc_vconcat(const struct Ustr *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_E_PROTO struct Ustr *ustr_sc_concat(const struct Ustr *, ...) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)) USTR__COMPILE_ATTR_SENTINEL(0); USTR_CONF_E_PROTO struct Ustr *ustr_sc_vconcatx(size_t, size_t, int, int, const struct Ustr *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((5)); USTR_CONF_E_PROTO struct Ustr *ustr_sc_concatx(size_t, size_t, int, int, const struct Ustr *, ...) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((5)) USTR__COMPILE_ATTR_SENTINEL(0); USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_dupx(struct Ustr_pool *, size_t, size_t, int, int, struct Ustrp **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_dup(struct Ustr_pool *,struct Ustrp **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO void ustrp_sc_free_shared(struct Ustr_pool *, struct Ustrp **) USTR__COMPILE_ATTR_NONNULL_L((2)); /* USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_reconf(struct Ustr_pool *, struct Ustrp **, size_t, size_t, int, int) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); */ USTR_CONF_E_PROTO int ustrp_sc_reverse(struct Ustr_pool *, struct Ustrp **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); #ifdef USTR_UTF8_H USTR_CONF_E_PROTO int ustrp_sc_utf8_reverse(struct Ustr_pool *, struct Ustrp **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); #endif USTR_CONF_E_PROTO int ustrp_sc_tolower(struct Ustr_pool *, struct Ustrp **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO int ustrp_sc_toupper(struct Ustr_pool *, struct Ustrp **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_E_PROTO char *ustrp_sc_export_subustrp(struct Ustr_pool *, const struct Ustrp *, size_t, size_t, void *(*)(size_t)) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_EI_PROTO char *ustrp_sc_export(struct Ustr_pool *p,const struct Ustrp*,void *(*)(size_t)) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO int ustrp_sc_ltrim_chrs(struct Ustr_pool *, struct Ustrp **,const char*,size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_EI_PROTO int ustrp_sc_ltrim(struct Ustr_pool *, struct Ustrp **, const struct Ustrp *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_EI_PROTO int ustrp_sc_ltrim_cstr(struct Ustr_pool *p, struct Ustrp **, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_sc_rtrim_chrs(struct Ustr_pool *, struct Ustrp **,const char*,size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_EI_PROTO int ustrp_sc_rtrim(struct Ustr_pool *, struct Ustrp **, const struct Ustrp *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_EI_PROTO int ustrp_sc_rtrim_cstr(struct Ustr_pool *p, struct Ustrp **, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO int ustrp_sc_trim_chrs(struct Ustr_pool *, struct Ustrp **,const char *,size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_EI_PROTO int ustrp_sc_trim(struct Ustr_pool *, struct Ustrp **, const struct Ustrp *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_EI_PROTO int ustrp_sc_trim_cstr(struct Ustr_pool *, struct Ustrp **, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_vjoin(struct Ustr_pool *, const struct Ustrp *, const struct Ustrp *, const struct Ustrp *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3,4)); USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_join(struct Ustr_pool *, const struct Ustrp *, const struct Ustrp *, const struct Ustrp *, ...) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3, 4)) USTR__COMPILE_ATTR_SENTINEL(0); USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_vjoinx(struct Ustr_pool *, size_t,size_t,int,int, const struct Ustrp *, const struct Ustrp *, const struct Ustrp *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6, 7,8)); USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_joinx(struct Ustr_pool *, size_t, size_t, int, int, const struct Ustrp *, const struct Ustrp *, const struct Ustrp *, ...) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6, 7, 8)) USTR__COMPILE_ATTR_SENTINEL(0); USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_vconcat(struct Ustr_pool *, const struct Ustrp *,va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_concat(struct Ustr_pool *, const struct Ustrp *, ...) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)) USTR__COMPILE_ATTR_SENTINEL(0); USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_vconcatx(struct Ustr_pool *, size_t,size_t,int,int, const struct Ustrp *, va_list) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); USTR_CONF_E_PROTO struct Ustrp *ustrp_sc_concatx(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__COMPILE_ATTR_SENTINEL(0); #if USTR_CONF_INCLUDE_INTERNAL_HEADERS # include "ustr-sc-internal.h" #endif #if USTR_CONF_INCLUDE_CODEONLY_HEADERS # include "ustr-sc-code.h" #endif #if USTR_CONF_COMPILE_USE_INLINE USTR_CONF_II_PROTO char *ustr_sc_export(const struct Ustr *s1, void *(*my_alloc)(size_t)) { return (ustr_sc_export_subustr(s1, 1, ustr_len(s1), my_alloc)); } USTR_CONF_II_PROTO char *ustrp_sc_export(struct Ustr_pool *p, const struct Ustrp *s1, void *(*my_alloc)(size_t)) { return (ustrp_sc_export_subustrp(p, s1, 1, ustrp_len(s1), my_alloc)); } USTR_CONF_II_PROTO int ustr_sc_ltrim(struct Ustr **ps1, const struct Ustr *s2) { return (ustr_sc_ltrim_chrs(ps1, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO int ustr_sc_ltrim_cstr(struct Ustr **ps1, const char *cstr) { return (ustr_sc_ltrim_chrs(ps1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustr_sc_rtrim(struct Ustr **ps1, const struct Ustr *s2) { return (ustr_sc_rtrim_chrs(ps1, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO int ustr_sc_rtrim_cstr(struct Ustr **ps1, const char *cstr) { return (ustr_sc_rtrim_chrs(ps1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustr_sc_trim(struct Ustr **ps1, const struct Ustr *s2) { return (ustr_sc_trim_chrs(ps1, ustr_cstr(s2), ustr_len(s2))); } USTR_CONF_II_PROTO int ustr_sc_trim_cstr(struct Ustr **ps1, const char *cstr) { return (ustr_sc_trim_chrs(ps1, cstr, strlen(cstr))); } USTR_CONF_II_PROTO int ustrp_sc_ltrim(struct Ustr_pool *p, struct Ustrp **ps1, const struct Ustrp *s2) { return (ustrp_sc_ltrim_chrs(p, ps1, ustrp_cstr(s2), ustrp_len(s2))); } USTR_CONF_II_PROTO int ustrp_sc_ltrim_cstr(struct Ustr_pool *p, struct Ustrp **ps1, const char *c) { return (ustrp_sc_ltrim_chrs(p, ps1, c, strlen(c))); } USTR_CONF_II_PROTO int ustrp_sc_rtrim(struct Ustr_pool *p, struct Ustrp **ps1, const struct Ustrp *s2) { return (ustrp_sc_rtrim_chrs(p, ps1, ustrp_cstr(s2), ustrp_len(s2))); } USTR_CONF_II_PROTO int ustrp_sc_rtrim_cstr(struct Ustr_pool *p, struct Ustrp **ps1, const char *c) { return (ustrp_sc_rtrim_chrs(p, ps1, c, strlen(c))); } USTR_CONF_II_PROTO int ustrp_sc_trim(struct Ustr_pool *p, struct Ustrp **ps1, const struct Ustrp *s2) { return (ustrp_sc_trim_chrs(p, ps1, ustrp_cstr(s2), ustrp_len(s2))); } USTR_CONF_II_PROTO int ustrp_sc_trim_cstr(struct Ustr_pool *p, struct Ustrp **ps1, const char *c) { return (ustrp_sc_trim_chrs(p, ps1, c, strlen(c))); } #endif #endif ustr-1.0.4/ustr-sc-code.h0000644000076400007640000004022410755654276014205 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SC_H #error " Include ustr-sc.h before this file." #endif USTR_CONF_i_PROTO void ustrp__sc_free_shared(struct Ustr_pool *p, struct Ustr **ps1) { USTR_ASSERT(ps1); if (!*ps1) return; USTR_ASSERT(ustr_shared(*ps1)); ustr_setf_owner(*ps1); ustrp__sc_free(p, ps1); } USTR_CONF_I_PROTO void ustr_sc_free_shared(struct Ustr **ps1) { ustrp__sc_free_shared(0, ps1); } USTR_CONF_I_PROTO void ustrp_sc_free_shared(struct Ustr_pool *p, struct Ustrp **ps1) { struct Ustr *tmp = &(*ps1)->s; ustrp__sc_free_shared(p, &tmp); *ps1 = USTRP(tmp); } USTR_CONF_i_PROTO struct Ustr *ustrp__sc_dupx(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, struct Ustr **ps1) { struct Ustr *ret = ustrp__dupx(p, sz, rbytes, exact, emem, *ps1); struct Ustr *tmp = USTR_NULL; if (!ret) return (USTR_NULL); if (!ustr__dupx_cmp_eq(sz, rbytes, exact, emem, USTR__DUPX_FROM(*ps1))) return (ret); /* different config. so just return */ /* swap, we only _need_ to do this when ret != *ps1 ... but it doesn't matter * if we always do it. */ tmp = *ps1; *ps1 = ret; ret = tmp; return (ret); } USTR_CONF_I_PROTO struct Ustr *ustr_sc_dupx(size_t sz, size_t rbytes, int exact, int emem, struct Ustr **ps1) { return (ustrp__sc_dupx(0, sz, rbytes, exact, emem, ps1)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_sc_dupx(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, struct Ustrp **ps1) { struct Ustr *tmp = &(*ps1)->s; struct Ustr *ret = ustrp__sc_dupx(p, sz, rbytes, exact, emem, &tmp); *ps1 = USTRP(tmp); return (USTRP(ret)); } USTR_CONF_i_PROTO struct Ustr *ustrp__sc_dup(struct Ustr_pool *p, struct Ustr **ps1) { struct Ustr *ret = ustrp__dup(p, *ps1); struct Ustr *tmp = USTR_NULL; if (!ret) return (USTR_NULL); /* swap, we only _need_ to do this when ret != *ps1 ... but it doesn't matter * if we always do it. */ tmp = *ps1; *ps1 = ret; ret = tmp; return (ret); } USTR_CONF_I_PROTO struct Ustr *ustr_sc_dup(struct Ustr **ps1) { return (ustrp__sc_dup(0, ps1)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_sc_dup(struct Ustr_pool *p, struct Ustrp **ps1) { struct Ustr *tmp = &(*ps1)->s; struct Ustr *ret = ustrp__sc_dup(p, &tmp); *ps1 = USTRP(tmp); return (USTRP(ret)); } USTR_CONF_i_PROTO void ustr__reverse(char *ptr, size_t pos, size_t len) { size_t clen = len; --pos; while (len > (clen / 2)) { const size_t boff = pos + (clen - len); const size_t eoff = pos + (len - 1); char tmp = ptr[boff]; ptr[boff] = ptr[eoff]; ptr[eoff] = tmp; --len; } } USTR_CONF_i_PROTO int ustrp__sc_reverse(struct Ustr_pool *p, struct Ustr **ps1) { if (!ustrp__sc_ensure_owner(p, ps1)) return (USTR_FALSE); ustr__reverse(ustr_wstr(*ps1), 1, ustr_len(*ps1)); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_sc_reverse(struct Ustr **ps1) { return (ustrp__sc_reverse(0, ps1)); } USTR_CONF_I_PROTO int ustrp_sc_reverse(struct Ustr_pool *p, struct Ustrp **ps1) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_reverse(p, &tmp); *ps1 = USTRP(tmp); return (ret); } #ifdef USTR_UTF8_H USTR_CONF_i_PROTO int ustrp__sc_utf8_reverse(struct Ustr_pool *p, struct Ustr **ps1) { /* UTF-8 reversing is like word order reversing. The simple way is to reverse * each "character", in place, and then reverse the entire string. */ char *ptr; const unsigned char *beg; const unsigned char *scan; USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); if (!(ptr = ustrp__sc_wstr(p, ps1))) return (USTR_FALSE); scan = beg = (const unsigned char *)ptr; while (*scan) { const unsigned char *prev = scan; USTR_ASSERT(ustr_len(*ps1) > (size_t)(scan - beg)); scan = ustr__utf8_next(scan); ustr__reverse(ptr, 1 + (prev - beg), (scan - prev)); } ustr__reverse(ptr, 1, (scan - beg)); return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_sc_utf8_reverse(struct Ustr **ps1) { return (ustrp__sc_utf8_reverse(0, ps1)); } USTR_CONF_I_PROTO int ustrp_sc_utf8_reverse(struct Ustr_pool *p, struct Ustrp **ps1) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_utf8_reverse(p, &tmp); *ps1 = USTRP(tmp); return (ret); } #endif USTR_CONF_i_PROTO int ustrp__sc_tolower(struct Ustr_pool *p, struct Ustr **ps1) { size_t clen; size_t len; char *ptr; if (!(ptr = ustrp__sc_wstr(p, ps1))) return (USTR_FALSE); clen = len = ustr_len(*ps1); while (len) { if ((*ptr >= 0x41) && (*ptr <= 0x5a)) *ptr ^= 0x20; ++ptr; --len; } return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_sc_tolower(struct Ustr **ps1) { return (ustrp__sc_tolower(0, ps1)); } USTR_CONF_I_PROTO int ustrp_sc_tolower(struct Ustr_pool *p, struct Ustrp **ps1) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_tolower(p, &tmp); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sc_toupper(struct Ustr_pool *p, struct Ustr **ps1) { size_t clen; size_t len; char *ptr; if (!(ptr = ustrp__sc_wstr(p, ps1))) return (USTR_FALSE); clen = len = ustr_len(*ps1); while (len) { if ((*ptr >= 0x61) && (*ptr <= 0x7a)) *ptr ^= 0x20; ++ptr; --len; } return (USTR_TRUE); } USTR_CONF_I_PROTO int ustr_sc_toupper(struct Ustr **ps1) { return (ustrp__sc_toupper(0, ps1)); } USTR_CONF_I_PROTO int ustrp_sc_toupper(struct Ustr_pool *p, struct Ustrp **ps1) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_toupper(p, &tmp); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO char *ustrp__sc_export_subustr(struct Ustr_pool *p, const struct Ustr *s1, size_t pos,size_t len, void *(*my_alloc)(size_t)) { char *ret = 0; USTR_ASSERT(my_alloc || p); if (!ustrp__assert_valid_subustr(!!p, s1, pos, len)) { errno = USTR__EINVAL; return (ret); } --pos; if (my_alloc) /* Alloc ustrp_*() to use normal export too */ ret = (*my_alloc)(len + 1); else ret = p->pool_sys_malloc(p, len + 1); if (!ret) { errno = ENOMEM; return (ret); } memcpy(ret, ustr_cstr(s1) + pos, len); ret[len] = 0; return (ret); } USTR_CONF_I_PROTO char *ustr_sc_export_subustr(const struct Ustr *s1, size_t pos, size_t len, void *(*my_alloc)(size_t)) { USTR_ASSERT(my_alloc); return (ustrp__sc_export_subustr(0, s1, pos, len, my_alloc)); } USTR_CONF_I_PROTO char *ustrp_sc_export_subustrp(struct Ustr_pool *p, const struct Ustrp *s1, size_t pos,size_t len, void *(*my_alloc)(size_t)) { return (ustrp__sc_export_subustr(p, &s1->s, pos, len, my_alloc)); } USTR_CONF_i_PROTO int ustrp__sc_ltrim_chrs(struct Ustr_pool *p, struct Ustr **ps1, const char *chrs, size_t len) { return (ustrp__del_subustr(p, ps1, 1, ustr_spn_chrs_fwd(*ps1, 0, chrs, len))); } USTR_CONF_I_PROTO int ustr_sc_ltrim_chrs(struct Ustr **ps1, const char *chrs, size_t len) { return (ustrp__sc_ltrim_chrs(0, ps1, chrs, len)); } USTR_CONF_I_PROTO int ustrp_sc_ltrim_chrs(struct Ustr_pool *p, struct Ustrp **ps1, const char *chrs, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_ltrim_chrs(p, &tmp, chrs, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sc_rtrim_chrs(struct Ustr_pool *p, struct Ustr **ps1, const char *chrs, size_t len) { return (ustrp__del(p, ps1, ustr_spn_chrs_rev(*ps1, 0, chrs, len))); } USTR_CONF_I_PROTO int ustr_sc_rtrim_chrs(struct Ustr **ps1, const char *chrs, size_t len) { return (ustrp__sc_rtrim_chrs(0, ps1, chrs, len)); } USTR_CONF_I_PROTO int ustrp_sc_rtrim_chrs(struct Ustr_pool *p, struct Ustrp **ps1, const char *chrs, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_rtrim_chrs(p, &tmp, chrs, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO int ustrp__sc_trim_chrs(struct Ustr_pool *p, struct Ustr **ps1, const char *chrs, size_t len) { size_t ltrim = ustr_spn_chrs_fwd(*ps1, 0, chrs, len); size_t rtrim = 0; size_t clen = ustr_len(*ps1); size_t nlen = 0; char *ptr; USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1)); if (ltrim == clen) return (ustrp__del(p, ps1, ltrim)); rtrim = ustr_spn_chrs_rev(*ps1, 0, chrs, len); if (!ltrim && !rtrim) return (USTR_TRUE); /* minor speed hack */ nlen = clen - (ltrim + rtrim); if (!ustr_owner(*ps1)) { struct Ustr *ret = ustrp__dup_subustr(p, *ps1, 1 + ltrim, nlen); if (ret) ustrp__sc_free2(p, ps1, ret); return (!!ret); } ptr = ustr_wstr(*ps1); memmove(ptr, ptr + ltrim, nlen); return (ustrp__del(p, ps1, ltrim + rtrim)); } USTR_CONF_I_PROTO int ustr_sc_trim_chrs(struct Ustr **ps1, const char *chrs, size_t len) { return (ustrp__sc_trim_chrs(0, ps1, chrs, len)); } USTR_CONF_I_PROTO int ustrp_sc_trim_chrs(struct Ustr_pool *p, struct Ustrp **ps1, const char *chrs, size_t len) { struct Ustr *tmp = &(*ps1)->s; int ret = ustrp__sc_trim_chrs(p, &tmp, chrs, len); *ps1 = USTRP(tmp); return (ret); } USTR_CONF_i_PROTO struct Ustr *ustrp__sc_vjoinx(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, const struct Ustr *sep, const struct Ustr *s2, const struct Ustr *s3, va_list ap) { struct Ustr *s1 = USTR_NULL; const char *sptr = ustr_cstr(sep); size_t slen = ustr_len(sep); #if USTR_CONF_HAVE_VA_COPY /* do a single allocation */ size_t olen = 0; size_t len = 0; struct Ustr *tmp = USTR_NULL; int sz_bad = USTR_FALSE; va_list nap; USTR_ASSERT(ustrp__assert_valid(0, sep)); USTR__VA_COPY(nap, ap); len += ustr_len(s2); sz_bad |= (len < olen); olen = len; len += slen; sz_bad |= (len < olen); olen = len; len += ustr_len(s3); sz_bad |= (len < olen); olen = len; while ((tmp = va_arg(nap, struct Ustr *))) { len += slen; sz_bad |= (len < olen); olen = len; len += ustr_len(tmp); sz_bad |= (len < olen); olen = len; } va_end(nap); if (sz_bad || !(s1 = ustrp__dupx_undef(p, sz, rbytes, exact, emem, len))) { errno = USTR__ENOMEM; return (USTR_NULL); } len = 0; ustr__memcpy(s1, len, ustr_cstr(s2), ustr_len(s2)); len += ustr_len(s2); do { ustr__memcpy(s1, len, sptr, slen); len += slen; ustr__memcpy(s1, len, ustr_cstr(s3), ustr_len(s3)); len += ustr_len(s3); } while ((s3 = va_arg(ap, struct Ustr *))); USTR_ASSERT(olen == len); #else USTR_ASSERT(ustrp__assert_valid(0, sep)); if (!(s1 = ustrp__dupx(p, sz, rbytes, exact, USTR_FALSE, s2))) return (USTR_NULL); do { ustrp__add_buf(p, &s1, sptr, slen); ustrp__add(p, &s1, s3); } while ((s3 = va_arg(ap, struct Ustr *))); if (ustr_enomem(s1)) { ustrp__sc_free(p, &s1); errno = USTR__ENOMEM; return (USTR_NULL); } if (emem) ustr_setf_enomem_err(s1); #endif USTR_ASSERT(ustrp__assert_valid(!!p, s1)); return (s1); } USTR_CONF_I_PROTO struct Ustr *ustr_sc_vjoinx(size_t sz, size_t rbytes, int exact, int emem, const struct Ustr *sep, const struct Ustr *s2, const struct Ustr *s3, va_list ap) { return (ustrp__sc_vjoinx(0, sz, rbytes, exact, emem, sep, s2, s3, ap)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_sc_vjoinx(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, const struct Ustrp *sp,const struct Ustrp *s2, const struct Ustrp *s3, va_list ap) { return (USTRP(ustrp__sc_vjoinx(p, sz, rbytes, exact, emem, &sp->s, &s2->s, &s3->s, ap))); } USTR_CONF_I_PROTO struct Ustr *ustr_sc_joinx(size_t sz, size_t rbytes, int exact, int emem, const struct Ustr *sep, const struct Ustr *s2, const struct Ustr *s3, ...) { struct Ustr *ret = USTR_NULL; va_list ap; va_start(ap, s3); ret = ustr_sc_vjoinx(sz, rbytes, exact, emem, sep, s2, s3, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustrp *ustrp_sc_joinx(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, const struct Ustrp *sep,const struct Ustrp *s2, const struct Ustrp *s3, ...) { struct Ustrp *ret = USTRP_NULL; va_list ap; va_start(ap, s3); ret = ustrp_sc_vjoinx(p, sz, rbytes, exact, emem, sep, s2, s3, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustr *ustr_sc_vjoin(const struct Ustr *sep, const struct Ustr *s2, const struct Ustr *s3, va_list ap) { return (ustrp__sc_vjoinx(0, USTR__DUPX_DEF, sep, s2, s3, ap)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_sc_vjoin(struct Ustr_pool *p, const struct Ustrp *sep, const struct Ustrp *s2,const struct Ustrp *s3, va_list ap) { return (USTRP(ustrp__sc_vjoinx(p,USTR__DUPX_DEF,&sep->s,&s2->s,&s3->s,ap))); } USTR_CONF_I_PROTO struct Ustr *ustr_sc_join(const struct Ustr *sep, const struct Ustr *s2, const struct Ustr *s3, ...) { struct Ustr *ret = USTR_NULL; va_list ap; va_start(ap, s3); ret = ustr_sc_vjoin(sep, s2, s3, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustrp * ustrp_sc_join(struct Ustr_pool *p, const struct Ustrp *sep, const struct Ustrp *s2, const struct Ustrp *s3, ...) { struct Ustrp *ret = USTRP_NULL; va_list ap; va_start(ap, s3); ret = ustrp_sc_vjoin(p, sep, s2, s3, ap); va_end(ap); return (ret); } /* ---- concat ---- */ USTR_CONF_i_PROTO struct Ustr *ustrp__sc_vconcatx(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, const struct Ustr *s2, va_list ap) { return (ustrp__sc_vjoinx(p, sz,rbytes,exact,emem, USTR(""),USTR(""),s2,ap)); } USTR_CONF_I_PROTO struct Ustr *ustr_sc_vconcatx(size_t sz, size_t rbytes, int exact, int emem, const struct Ustr *s2, va_list ap) { return (ustrp__sc_vconcatx(0, sz, rbytes, exact, emem, s2, ap)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_sc_vconcatx(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, const struct Ustrp *s2, va_list ap) { return (USTRP(ustrp__sc_vconcatx(p, sz,rbytes,exact,emem, &s2->s, ap))); } USTR_CONF_I_PROTO struct Ustr *ustr_sc_concatx(size_t sz, size_t rbytes, int exact, int emem, const struct Ustr *s2, ...) { struct Ustr *ret = USTR_NULL; va_list ap; va_start(ap, s2); ret = ustr_sc_vconcatx(sz, rbytes, exact, emem, s2, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustrp *ustrp_sc_concatx(struct Ustr_pool *p, size_t sz, size_t rbytes, int exact, int emem, const struct Ustrp *s2, ...) { struct Ustrp *ret = USTRP_NULL; va_list ap; va_start(ap, s2); ret = ustrp_sc_vconcatx(p, sz, rbytes, exact, emem, s2, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustr *ustr_sc_vconcat(const struct Ustr *s2, va_list ap) { return (ustrp__sc_vconcatx(0, USTR__DUPX_DEF, s2, ap)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_sc_vconcat(struct Ustr_pool *p, const struct Ustrp *s2, va_list ap) { return (USTRP(ustrp__sc_vconcatx(p, USTR__DUPX_DEF, &s2->s, ap))); } USTR_CONF_I_PROTO struct Ustr *ustr_sc_concat(const struct Ustr *s2, ...) { struct Ustr *ret = USTR_NULL; va_list ap; va_start(ap, s2); ret = ustr_sc_vconcat(s2, ap); va_end(ap); return (ret); } USTR_CONF_I_PROTO struct Ustrp *ustrp_sc_concat(struct Ustr_pool *p, const struct Ustrp *s2, ...) { struct Ustrp *ret = USTRP_NULL; va_list ap; va_start(ap, s2); ret = ustrp_sc_vconcat(p, s2, ap); va_end(ap); return (ret); } ustr-1.0.4/ustr-pool-dbg-code.c0000644000076400007640000000130410674563614015265 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-pool.h" ustr-1.0.4/ustr-split-code.h0000644000076400007640000001504110711254755014720 0ustar jamesjames/* Copyright (c) 2007 Paul Rosenfeld James Antill -- See LICENSE file for terms. */ #ifndef USTR_SPLIT_H #error " Include ustr-split.h before this file." #endif #if !defined(USTR_FMT_INTERNAL_H) && !defined(USTR_IO_H) #include #endif USTR_CONF_i_PROTO struct Ustr *ustrp__split_buf(struct Ustr_pool *p, const struct Ustr *s1, size_t *poff, const void *sep, size_t slen, struct Ustr *ret, unsigned int flags) { size_t len = ustr_len(s1); size_t off = *poff; size_t found_pos = 0; size_t ret_len = 0; USTR_ASSERT(ustrp__assert_valid(!!p, s1)); USTR_ASSERT_RET(off <= len, USTR_NULL); if (!slen || (off == len)) { ustrp__free(p, ret); errno = 0; /* only way to tell between FAILURE and END */ return (USTR_NULL); } /* Separator not found, just return the rest of the string */ if (!(found_pos = ustr_srch_buf_fwd(s1, off, sep, slen))) { ret_len = len - off; *poff = len; goto copy_buf; } /* Set the offset for the next, must skip sep */ *poff = (found_pos - 1) + slen; if (!(flags & (USTR_FLAG_SPLIT_RET_SEP | USTR_FLAG_SPLIT_RET_NON))) { const char *ptr = ustr_cstr(s1); while (((len - *poff) >= slen) && !memcmp(ptr + *poff, sep, slen)) *poff += slen; } /* If we don't wish to return blanks or separators, we might get "a,,b" with * sep="," so we need to skip the first "found" separator -- so just try * again */ if (((found_pos - 1) == off) && !(flags & (USTR_FLAG_SPLIT_RET_SEP | USTR_FLAG_SPLIT_RET_NON))) return (ustrp__split_buf(p, s1, poff, sep, slen, ret, flags)); ret_len = (found_pos - 1) - off; if (flags & USTR_FLAG_SPLIT_RET_SEP) /* Include sep in the return value */ ret_len += slen; copy_buf: if (ret) { if (!ustrp__set_subustr(p, &ret, s1, off + 1, ret_len)) { ustrp__free(p, ret); return (USTR_NULL); } return (ret); } if (flags & USTR_FLAG_SPLIT_KEEP_CONF) return (ustrp__dup_subustr(p, s1, off + 1, ret_len)); return (ustrp__dupx_buf(p, USTR__DUPX_DEF, ustr_cstr(s1) + off, ret_len)); } USTR_CONF_I_PROTO struct Ustr *ustr_split_buf(const struct Ustr *s1, size_t *off, const void *sep, size_t slen, struct Ustr *ret, unsigned int flags) { return (ustrp__split_buf(0, s1, off, sep, slen, ret, flags)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_split_buf(struct Ustr_pool *p, const struct Ustrp *s1, size_t *off, const void *sep, size_t slen, struct Ustrp *ret, unsigned int flags) { return (USTRP(ustrp__split_buf(p, &s1->s, off, sep, slen, &ret->s, flags))); } USTR_CONF_I_PROTO struct Ustr *ustr_split(const struct Ustr *s1, size_t *off, const struct Ustr *sep, struct Ustr *ret, unsigned int flags) { USTR_ASSERT(ustrp__assert_valid(0, sep)); return (ustrp__split_buf(0, s1,off,ustr_cstr(sep),ustr_len(sep), ret, flags)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_split(struct Ustr_pool *p, const struct Ustrp *s1, size_t *off, const struct Ustrp *sep, struct Ustrp *ret, unsigned int flags) { USTR_ASSERT(ustrp_assert_valid(sep)); return (USTRP(ustrp__split_buf(p, &s1->s, off, ustrp_cstr(sep),ustrp_len(sep), &ret->s, flags))); } USTR_CONF_i_PROTO struct Ustr *ustrp__split_spn_chrs(struct Ustr_pool *p, const struct Ustr *s1, size_t *poff, const char *seps, size_t slen, struct Ustr *ret, unsigned int flags) { size_t len = ustr_len(s1); size_t off = *poff; size_t spn = 0; size_t sep = 0; size_t ret_len = 0; USTR_ASSERT(ustrp__assert_valid(!!p, s1)); USTR_ASSERT_RET(off <= len, USTR_NULL); if (!slen || (off == len)) { ustrp__free(p, ret); errno = 0; /* only way to tell between FAILURE and END */ return (USTR_NULL); } spn = ustr_cspn_chrs_fwd(s1, off, seps, slen); if (!spn && !(flags & (USTR_FLAG_SPLIT_RET_SEP | USTR_FLAG_SPLIT_RET_NON))) { *poff += ustr_spn_chrs_fwd(s1, off, seps, slen); return (ustrp__split_spn_chrs(p, s1, poff, seps, slen, ret, flags)); } /* if there's any data left the first byte must be in seps */ if (flags & (USTR_FLAG_SPLIT_RET_SEP | USTR_FLAG_SPLIT_RET_NON)) sep = !((off + spn) == len); else sep = ustr_spn_chrs_fwd(s1, off + spn, seps, slen); USTR_ASSERT(!sep == !ustr_spn_chrs_fwd(s1, off + spn, seps, slen)); *poff += spn + sep; ret_len = spn; if (flags & USTR_FLAG_SPLIT_RET_SEP) /* Include seps in the return value */ ret_len += sep; if (ret) { if (!ustrp__set_subustr(p, &ret, s1, off + 1, ret_len)) return (USTR_NULL); return (ret); } if (flags & USTR_FLAG_SPLIT_KEEP_CONF) return (ustrp__dup_subustr(p, s1, off + 1, ret_len)); return (ustrp__dupx_buf(p, USTR__DUPX_DEF, ustr_cstr(s1) + off, ret_len)); } USTR_CONF_I_PROTO struct Ustr *ustr_split_spn_chrs(const struct Ustr *s1, size_t *poff, const char *seps, size_t slen, struct Ustr *ret, unsigned int flags) { return (ustrp__split_spn_chrs(0, s1, poff, seps, slen, ret, flags)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_split_spn_chrs(struct Ustr_pool *p, const struct Ustrp *s1, size_t *poff, const char *seps, size_t slen, struct Ustrp *ret, unsigned int flags) { return (USTRP(ustrp__split_spn_chrs(p, &s1->s, poff, seps, slen, &ret->s, flags))); } USTR_CONF_I_PROTO struct Ustr *ustr_split_spn(const struct Ustr *s1, size_t *off, const struct Ustr *sep, struct Ustr *ret, unsigned int flags) { USTR_ASSERT(ustrp__assert_valid(0, sep)); return (ustrp__split_spn_chrs(0, s1, off, ustr_cstr(sep), ustr_len(sep), ret, flags)); } USTR_CONF_I_PROTO struct Ustrp *ustrp_split_spn(struct Ustr_pool *p, const struct Ustrp *s1, size_t *off, const struct Ustrp *sep, struct Ustrp *ret, unsigned int flags) { USTR_ASSERT(ustrp_assert_valid(sep)); return (USTRP(ustrp__split_spn_chrs(p, &s1->s, off, ustrp_cstr(sep), ustrp_len(sep), &ret->s, flags))); } ustr-1.0.4/ustr-parse-code.h0000644000076400007640000002200710642537236014700 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_PARSE_H #error " You should have already included ustr-parse.h, or just include ustr.h." #endif #if ! USTR_CONF_HAVE_STDINT_H # define USTR__UMAX unsigned long #else # define USTR__UMAX uintmax_t #endif /* basically uses: [ ]*[-+](0b|0B|0o|0O|0x|0X|0)[0-9a-z_]+ */ USTR_CONF_e_PROTO int ustr__parse_num_beg(const char **ptr, size_t *len, unsigned int flags, int *tst_neg, int *tst_0, unsigned int *ern) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_i_PROTO int ustr__parse_num_beg(const char **ptr, size_t *len, unsigned int flags, int *tst_neg, int *tst_0, unsigned int *ern) { unsigned int base = flags & USTR__MASK_PARSE_NUM_BASE; int auto_base = USTR_FALSE; if (!base) auto_base = USTR_TRUE; else if (base > 36) base = 36; else if (base == 1) ++base; if (flags & USTR_FLAG_PARSE_NUM_SPACE) { while (*len && (**ptr == ' ')) { ++*ptr; --*len; } if (!*len) { *ern = USTR_TYPE_PARSE_NUM_ERR_ONLY_S; return (0); } } if (!(flags & USTR_FLAG_PARSE_NUM_NO_BEG_PM)) { switch (**ptr) { case '-': *tst_neg = USTR_TRUE; case '+': ++*ptr; --*len; } if (!*len) { *ern = USTR_TYPE_PARSE_NUM_ERR_ONLY_SPM; return (0); } } if (**ptr != '0') { if (base) return (base); return (10); } ++*ptr; --*len; if (!*len) { *tst_0 = USTR_TRUE; return (10); } else if ((auto_base || (base == 2)) && ((**ptr == 'b') || (**ptr == 'B'))) base = 2; else if ((auto_base || (base == 8)) && ((**ptr == 'o') || (**ptr == 'O'))) base = 8; else if ((auto_base || (base == 16)) && ((**ptr == 'x') || (**ptr == 'X'))) base = 16; else if ((flags & USTR_FLAG_PARSE_NUM_NO_BEG_ZERO) && (!auto_base || (**ptr == '0'))) { *ern = USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO; return (0); } else { *tst_0 = USTR_TRUE; if (base) return (base); return (8); } ++*ptr; --*len; if (!*len) { *ern = USTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX; return (0); } if ((flags & USTR_FLAG_PARSE_NUM_NO_BEG_ZERO) && (**ptr == '0') && (*len > 1)) { *ern = USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO; return (0); } return (base); } #if USTR_CONF_HAVE_STDINT_H USTR_CONF_I_PROTO #else USTR_CONF_e_PROTO USTR__UMAX ustr_parse_uintmaxx(const struct Ustr *, size_t, unsigned int, USTR__UMAX, USTR__UMAX, char, size_t *, unsigned int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1)); USTR_CONF_i_PROTO #endif USTR__UMAX ustr_parse_uintmaxx(const struct Ustr *s1, size_t off, unsigned int flags, USTR__UMAX num_min, USTR__UMAX num_max, const char *sep, size_t *ret_len, unsigned int *ern) { static const char local_let_low[] = "abcdefghijklmnopqrstuvwxyz"; static const char local_let_high[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; unsigned int dummy_ern; unsigned int num_base = 0; int tst_neg = USTR_FALSE; int tst_0 = USTR_FALSE; int done_once = USTR_FALSE; char num_end = '9'; const char *ptr = ustr_cstr(s1); size_t len = ustr_len(s1); size_t orig_len; USTR__UMAX ret = 0; size_t slen = strlen(sep); USTR_ASSERT(ustr_assert_valid(s1)); USTR_ASSERT(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE) || !num_min); if (!ern) ern = &dummy_ern; *ern = USTR_TYPE_PARSE_NUM_ERR_NONE; USTR_ASSERT_RET(off <= len, 0); ptr += off; len -= off; orig_len = len; if (!(num_base = ustr__parse_num_beg(&ptr,&len, flags, &tst_neg,&tst_0, ern))) return (0); if (tst_neg && (flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE)) { *ern = USTR_TYPE_PARSE_NUM_ERR_NEGATIVE; return (0); } if (num_base < 10) num_end = '0' + num_base - 1; if (tst_neg) num_max = num_min; done_once = tst_0; while (len) { const char *end = 0; unsigned int add_num = 0; USTR__UMAX old_ret = ret; if (done_once && (flags & USTR_FLAG_PARSE_NUM_SEP) && (*ptr == *sep) && (len >= slen) && !memcmp(ptr, sep, slen)) { ptr += slen; len -= slen; continue; } else { if ((*ptr >= '0') && (*ptr <= num_end)) add_num = (*ptr - '0'); else if (num_base <= 10) break; else if ((end = memchr(local_let_low, *ptr, num_base - 10))) add_num = 10 + (end - local_let_low); else if ((end = memchr(local_let_high, *ptr, num_base - 10))) add_num = 10 + (end - local_let_high); else break; } ret = (ret * num_base) + add_num; if ((flags & USTR_FLAG_PARSE_NUM_OVERFLOW) && (((ret - add_num) / num_base) != old_ret)) { *ern = USTR_TYPE_PARSE_NUM_ERR_OVERFLOW; ret = 0; break; } ++ptr; --len; done_once = USTR_TRUE; } if (!done_once) { *ern = USTR_TYPE_PARSE_NUM_ERR_OOB; return (0); } if (!*ern && (flags & USTR_FLAG_PARSE_NUM_EXACT) && len) *ern = USTR_TYPE_PARSE_NUM_ERR_OOB; if (ret > num_max) { ret = num_max; if (flags & USTR_FLAG_PARSE_NUM_OVERFLOW) { if (!*ern) *ern = USTR_TYPE_PARSE_NUM_ERR_OVERFLOW; ret = 0; } } if (ret_len) *ret_len = orig_len - len; if (tst_neg) return (-ret); return (ret); } #if USTR_CONF_HAVE_STDINT_H USTR_CONF_I_PROTO uintmax_t ustr_parse_uintmax(const struct Ustr *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE)); flags |= USTR_FLAG_PARSE_NUM_NO_NEGATIVE; return (ustr_parse_uintmaxx(s1, off, flags, 0, UINTMAX_MAX, "_", len, ern)); } USTR_CONF_I_PROTO intmax_t ustr_parse_intmax(const struct Ustr *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { uintmax_t num_min = INTMAX_MIN; ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE)); return (ustr_parse_uintmaxx(s1,off, flags, -num_min,INTMAX_MAX, "_",len,ern)); } #endif USTR_CONF_I_PROTO unsigned long ustr_parse_ulongx(const struct Ustr *s1, size_t off, unsigned int flags, unsigned long num_min, unsigned long num_max, const char *sep, size_t *len, unsigned int *ern) { return (ustr_parse_uintmaxx(s1,off, flags, num_min,num_max, sep, len, ern)); } USTR_CONF_I_PROTO unsigned long ustr_parse_ulong(const struct Ustr *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE)); flags |= USTR_FLAG_PARSE_NUM_NO_NEGATIVE; return (ustr_parse_uintmaxx(s1, off, flags, 0, ULONG_MAX, "_", len, ern)); } USTR_CONF_I_PROTO long ustr_parse_long(const struct Ustr *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { unsigned long num_min = LONG_MIN; ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE)); return (ustr_parse_uintmaxx(s1,off, flags, -num_min, LONG_MAX, "_", len,ern)); } USTR_CONF_I_PROTO unsigned int ustr_parse_uint(const struct Ustr *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE)); flags |= USTR_FLAG_PARSE_NUM_NO_NEGATIVE; return (ustr_parse_uintmaxx(s1, off, flags, 0, UINT_MAX, "_", len, ern)); } USTR_CONF_I_PROTO int ustr_parse_int(const struct Ustr *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { unsigned int num_min = INT_MIN; ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE)); return (ustr_parse_uintmaxx(s1,off, flags, -num_min, INT_MAX, "_", len, ern)); } USTR_CONF_I_PROTO unsigned short ustr_parse_ushort(const struct Ustr *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE)); flags |= USTR_FLAG_PARSE_NUM_NO_NEGATIVE; return (ustr_parse_uintmaxx(s1, off, flags, 0, USHRT_MAX, "_", len, ern)); } USTR_CONF_I_PROTO short ustr_parse_short(const struct Ustr *s1, size_t off, unsigned int flags, size_t *len, unsigned int *ern) { unsigned short num_min = SHRT_MIN; ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE)); return (ustr_parse_uintmaxx(s1,off, flags, -num_min, SHRT_MAX, "_", len,ern)); } /* void *ustr_parse_num(const struct Ustr *s1, unsigned int flags, unsigned int *ern, void *(*func)(unsigned int, int,unsigned int *, void *), void *data) if (is_neg) add_num = -add_num; if (!(ret = func(num_base, add_num, err, ret)) && !*err) return (NULL); */ ustr-1.0.4/ustr-replace-dbg-code.c0000644000076400007640000000141210674563614015727 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #include "ustr-set.h" #include "ustr-srch.h" #include "ustr-sub.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-replace.h" ustr-1.0.4/perf-sizes.c0000644000076400007640000000677310630111754013747 0ustar jamesjames #include "ustr.h" #include struct NM_Ustr { const char *ptr; size_t reference_count; size_t length; unsigned char flag_is_readonly : 1; unsigned char flag_exact_byte_allocations : 1; unsigned char flag_has_enomem_error : 1; unsigned char flag_reference_count_is_inf : 1; }; #define TST "Hello!" /* for retarded Solaris printf */ #define CLU(x) ((unsigned long) x) static void tst_ustr(const char *tst, size_t num, size_t rb, int exact) { struct Ustr *s1 = ustr_dupx_cstr(rb, exact, 0, tst); /* NOTE: Using system *printf, so can't use %zu as Solaris is retarded */ printf("\t Ustr%lu(%lu, %s) %s= (%8lu / %-8lu = %5.2f%% )\n", CLU(num), CLU(rb), exact ? "TRUE" : "FALSE", exact ? " " : "", CLU(ustr_overhead(s1) + ustr_size(s1)), CLU(ustr_overhead(s1) + ustr_len(s1)), (100. * (ustr_overhead(s1) + ustr_size(s1))) / ustr_len(s1)); ustr_sc_free(&s1); } static size_t min_pow(size_t num) { size_t min_sz = 1; if (num > (USTR__SIZE_MAX / 2)) return (USTR__SIZE_MAX); while (min_sz < num) min_sz <<= 1; return (min_sz); } static size_t min_size(size_t num) { size_t min_sz = 1; if (num > ((USTR__SIZE_MAX / 4) * 3)) return (USTR__SIZE_MAX); /* *2 is too much, we end up wasting a lot of RAM. So we do *1.5. */ while (min_sz < num) { size_t adder = min_sz / 2; if (!adder) { min_sz = 2; continue; } min_sz += adder; if (min_sz >= num) break; min_sz += adder; } return (min_sz); } int main(int argc, char *argv[]) { struct Ustr *s1 = USTR(""); static const char txt[] = "123456789 "; size_t beg = 0; size_t end = 6; size_t count = 0; if (argc == 3) { beg = atoi(argv[1]); end = atoi(argv[2]); } while (count < beg) { ustr_add_rep_chr(&s1, txt[count++ % 10], 1); } while (count < end) { ustr_add_rep_chr(&s1, txt[count++ % 10], 1); printf("String: %lu \"%s\"\n", CLU(ustr_len(s1)), ustr_cstr(s1)); tst_ustr(ustr_cstr(s1), 0, 0, USTR_TRUE); tst_ustr(ustr_cstr(s1), 1, 0, USTR_FALSE); tst_ustr(ustr_cstr(s1), 2, 1, USTR_TRUE); tst_ustr(ustr_cstr(s1), 3, 1, USTR_FALSE); tst_ustr(ustr_cstr(s1), 4, 2, USTR_TRUE); tst_ustr(ustr_cstr(s1), 5, 2, USTR_FALSE); tst_ustr(ustr_cstr(s1), 6, 4, USTR_TRUE); tst_ustr(ustr_cstr(s1), 7, 4, USTR_FALSE); if (USTR_CONF_HAVE_68bit_SIZE_MAX) { tst_ustr(ustr_cstr(s1), 8, 8, USTR_TRUE); tst_ustr(ustr_cstr(s1), 9, 8, USTR_FALSE); } printf("\t strdup() = (%8lu / %-8lu = %5.2f%% )\n", CLU(ustr_len(s1) + 1), CLU(ustr_len(s1)), 100. * ((1 + ustr_len(s1)) / ustr_len(s1))); printf("\t NM_Ustr = (%8lu / %-8lu = %5.2f%% )\n", CLU(sizeof(struct NM_Ustr) + ustr_len(s1) + 1), CLU(sizeof(struct NM_Ustr) + ustr_len(s1)), (100. * (sizeof(struct NM_Ustr) + ustr_len(s1) + 1)) / ustr_len(s1)); printf("\t NM_Ustr x2 = (%8lu / %-8lu = %5.2f%% )\n", CLU(sizeof(struct NM_Ustr) + min_pow(ustr_len(s1) + 1)), CLU(sizeof(struct NM_Ustr) + ustr_len(s1)), (100. * (sizeof(struct NM_Ustr) + min_pow(ustr_len(s1) + 1))) / ustr_len(s1)); printf("\t NM_Ustr xUstr = (%8lu / %-8lu = %5.2f%% )\n", CLU(sizeof(struct NM_Ustr) + min_size(ustr_len(s1) + 1)), CLU(sizeof(struct NM_Ustr) + ustr_len(s1)), (100. * (sizeof(struct NM_Ustr) + min_size(ustr_len(s1) + 1))) / ustr_len(s1)); } ustr_sc_free(&s1); return 0; } ustr-1.0.4/ustr-parse-opt-code.c0000644000076400007640000000127710674563614015505 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-parse.h" ustr-1.0.4/ustr-io-internal.h0000644000076400007640000000275410654543450015104 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_IO_INTERNAL_H #define USTR_IO_INTERNAL_H 1 #ifndef USTR_IO_H # error " You should have already included ustr-io.h, or just include ustr.h" #endif USTR_CONF_e_PROTO int ustrp__io_get(struct Ustr_pool *, struct Ustr **, FILE *, size_t, size_t *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__io_getfile(struct Ustr_pool *, struct Ustr**,FILE*) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__io_getfilename(struct Ustr_pool *,struct Ustr **, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__io_getdelim(struct Ustr_pool *, struct Ustr **, FILE *, char) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__io_put(struct Ustr_pool *, struct Ustr **, FILE *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__io_putline(struct Ustr_pool *, struct Ustr **, FILE *, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__io_putfilename(struct Ustr_pool *, struct Ustr **, const char *, const char *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2, 3, 4)); #endif ustr-1.0.4/ustr-set-internal.h0000644000076400007640000000247510646601600015261 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SET_INTERNAL_H #define USTR_SET_INTERNAL_H 1 #ifndef USTR_SET_H # error " You should have already included ustr-set.h, or just include ustr.h" #endif USTR_CONF_e_PROTO int ustrp__set_undef(struct Ustr_pool *, struct Ustr **, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__set_empty(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__set_buf(struct Ustr_pool *, struct Ustr **, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__set(struct Ustr_pool *, struct Ustr **, const struct Ustr *) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__set_subustr(struct Ustr_pool *, struct Ustr **, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__set_rep_chr(struct Ustr_pool *, struct Ustr **, char, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); #ifdef USTR_FMT_H # if USTR_CONF_HAVE_VA_COPY USTR_CONF_e_PROTO int ustrp__set_vfmt_lim(struct Ustr_pool *, struct Ustr **, size_t, const char *, va_list) USTR__COMPILE_ATTR_NONNULL_L((2, 4)) USTR__COMPILE_ATTR_FMT(4, 0); # endif #endif #endif ustr-1.0.4/ustr-main-internal.h0000644000076400007640000001600110722115731015400 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_MAIN_INTERNAL_H #define USTR_MAIN_INTERNAL_H 1 #ifndef USTR_MAIN_H # error " You should include ustr-main.h before this file, or just ustr.h" #endif #include /* EDOM, EILSEQ, ERANGE, hopefully ENOMEM, etc. */ #ifdef ENOMEM # define USTR__ENOMEM ENOMEM #else # define USTR__ENOMEM EDOM /* ENOMEM isn't in ISO 9899:1999, *sigh* */ #endif #ifdef EINVAL # define USTR__EINVAL EINVAL #else # define USTR__EINVAL ERANGE /* EINVAL isn't in ISO 9899:1999, *sigh* */ #endif /* default sized is 1 byte... */ #define USTR__DUPX_DEF \ USTR_CONF_HAS_SIZE, USTR_CONF_REF_BYTES, \ USTR_CONF_EXACT_BYTES, USTR_FALSE #define USTR__DUPX_FROM(x) \ (ustr_alloc(x) ? \ (ustr_sized(x) ? ustr__sz_get(x) : 0) : USTR_CONF_HAS_SIZE), \ (ustr_alloc(x) ? USTR__REF_LEN(x) : USTR_CONF_REF_BYTES), \ (ustr_alloc(x) ? ustr_exact(x) : USTR_CONF_EXACT_BYTES), ustr_enomem(x) #define USTR__ASSERT_MALLOC_CHECK_MEM(p, s1) ((p) || \ USTR_CNTL_MALLOC_CHECK_MEM_USTR(s1)) USTR_CONF_e_PROTO int ustr__dupx_cmp_eq(size_t, size_t, int, int, size_t, size_t, int, int) USTR__COMPILE_ATTR_CONST() USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_e_PROTO size_t ustr__sz_get(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__nb(size_t num) USTR__COMPILE_ATTR_CONST() USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_e_PROTO int ustrp__assert_valid(int, const struct Ustr *) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO size_t ustrp__assert_valid_subustr(int, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_PURE() USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO void ustr__embed_val_set(unsigned char *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO int ustr__ref_set(struct Ustr *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO void ustr__len_set(struct Ustr *s1, size_t len) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO void ustr__sz_set(struct Ustr *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO int ustr__ref_add(struct Ustr *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO size_t ustr__ref_del(struct Ustr *s1) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO void ustrp__free(struct Ustr_pool *, struct Ustr *); USTR_CONF_e_PROTO void ustrp__sc_free2(struct Ustr_pool *p, struct Ustr **ps1, struct Ustr *s2) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO size_t ustr__ns(size_t num) USTR__COMPILE_ATTR_CONST() USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_e_PROTO void ustr__terminate(unsigned char *, int, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO struct Ustr *ustrp__dupx_undef(struct Ustr_pool *, size_t, size_t, int, int, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_e_PROTO int ustrp__rw_realloc(struct Ustr_pool *, struct Ustr **, int, size_t, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO void ustr__memcpy(struct Ustr *, size_t, const void *,size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO void ustr__memset(struct Ustr *, size_t, int, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO int ustrp__realloc(struct Ustr_pool *, struct Ustr **, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustr__rw_mod(struct Ustr *, size_t, size_t *, size_t *, size_t *, size_t *, int *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO int ustrp__del(struct Ustr_pool *, struct Ustr **, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__del_subustr(struct Ustr_pool *, struct Ustr **, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO struct Ustr *ustrp__dupx_empty(struct Ustr_pool *, size_t, size_t, int, int) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_e_PROTO struct Ustr *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 Ustr *ustrp__dup(struct Ustr_pool *, const struct Ustr *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO struct Ustr *ustrp__dupx(struct Ustr_pool *, size_t, size_t, int , int, const struct Ustr *) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); USTR_CONF_e_PROTO struct Ustr *ustrp__dupx_subustr(struct Ustr_pool *, size_t, size_t, int, int, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((6)); USTR_CONF_e_PROTO struct Ustr *ustrp__dup_subustr(struct Ustr_pool *, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO struct Ustr *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 int ustrp__add_undef(struct Ustr_pool *, struct Ustr **, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__add_buf(struct Ustr_pool *, struct Ustr **, const void *, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustr__treat_as_buf(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__add(struct Ustr_pool *, struct Ustr **, const struct Ustr *) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__add_subustr(struct Ustr_pool *, struct Ustr **, const struct Ustr *, size_t, size_t) USTR__COMPILE_ATTR_NONNULL_L((2, 3)); USTR_CONF_e_PROTO int ustrp__add_rep_chr(struct Ustr_pool *p, struct Ustr **, char, size_t) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO void ustrp__sc_del(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO void ustrp__sc_free(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO int ustrp__sc_ensure_owner(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); USTR_CONF_e_PROTO char *ustrp__sc_wstr(struct Ustr_pool *, struct Ustr **) USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((2)); #endif ustr-1.0.4/perf/0000755000076400007640000000000010710724540012435 5ustar jamesjamesustr-1.0.4/perf/sizes_out_32bit.tsv0000644000076400007640000006132010630111754016222 0ustar jamesjames# set style data lines # set xrange [0:259] # set yrange [100:500] # # set xlabel "Length" # set ylabel "Percent bigger" # # plot "sizes_out_64bit.tsv" using 1:2 title 'Ss0', # "sizes_out_64bit.tsv" using 1:3 title 'Ss1', # "sizes_out_64bit.tsv" using 1:4 title 'Ss2', # "sizes_out_64bit.tsv" using 1:5 title 'Ss3', # "sizes_out_64bit.tsv" using 1:6 title 'Ss4', # "sizes_out_64bit.tsv" using 1:7 title 'Ss5', # "sizes_out_64bit.tsv" using 1:8 title 'Ss6', # "sizes_out_64bit.tsv" using 1:9 title 'Ss7', # "sizes_out_64bit.tsv" using 1:10 title 'Ss8', # "sizes_out_64bit.tsv" using 1:11 title 'Ss9', # "sizes_out_64bit.tsv" using 1:12 title 'strdup', # "sizes_out_64bit.tsv" using 1:13 title 'NM_Ss', # "sizes_out_64bit.tsv" using 1:14 title 'NM_Ss x2', # "sizes_out_64bit.tsv" using 1:15 title 'NM_Ss xSs' # # plot "sizes_out_32bit.tsv" using 1:2 title 'Ss0', # "sizes_out_32bit.tsv" using 1:3 title 'Ss1', # "sizes_out_32bit.tsv" using 1:4 title 'Ss2', # "sizes_out_32bit.tsv" using 1:5 title 'Ss3', # "sizes_out_32bit.tsv" using 1:6 title 'Ss4', # "sizes_out_32bit.tsv" using 1:7 title 'Ss5', # "sizes_out_64bit.tsv" using 1:8 title 'Ss6', # "sizes_out_64bit.tsv" using 1:9 title 'Ss7', # "sizes_out_64bit.tsv" using 1:12 title 'strdup', # "sizes_out_64bit.tsv" using 1:13 title 'NM_Ss', # "sizes_out_64bit.tsv" using 1:14 title 'NM_Ss x2', # "sizes_out_64bit.tsv" using 1:15 title 'NM_Ss xSs' # # set xrange [1:59] # set yrange [100:800] # replot # 1 400.00 400.00 500.00 600.00 600.00 600.00 800.00 800.00 0 0 200.00 1700.00 1700.00 1700.00 2 250.00 300.00 300.00 300.00 350.00 400.00 450.00 600.00 0 0 150.00 900.00 900.00 900.00 3 200.00 200.00 233.33 266.67 266.67 266.67 333.33 400.00 0 0 133.33 633.33 666.67 633.33 4 175.00 200.00 200.00 200.00 225.00 300.00 275.00 300.00 0 0 125.00 500.00 500.00 500.00 5 160.00 160.00 180.00 240.00 200.00 240.00 240.00 240.00 0 0 120.00 420.00 480.00 440.00 6 150.00 200.00 166.67 200.00 183.33 200.00 216.67 266.67 0 0 116.67 366.67 400.00 366.67 7 142.86 171.43 157.14 171.43 171.43 171.43 200.00 228.57 0 0 114.29 328.57 342.86 342.86 8 137.50 150.00 150.00 150.00 162.50 200.00 187.50 200.00 0 0 112.50 300.00 300.00 300.00 9 133.33 133.33 144.44 177.78 155.56 177.78 177.78 177.78 0 0 111.11 277.78 355.56 311.11 10 130.00 160.00 140.00 160.00 150.00 160.00 170.00 240.00 0 0 110.00 260.00 320.00 280.00 11 127.27 145.45 136.36 145.45 145.45 145.45 163.64 218.18 0 0 109.09 245.45 290.91 254.55 12 125.00 133.33 133.33 133.33 141.67 200.00 158.33 200.00 0 0 108.33 233.33 266.67 233.33 13 123.08 123.08 130.77 184.62 138.46 184.62 153.85 184.62 0 0 107.69 223.08 246.15 246.15 14 121.43 171.43 128.57 171.43 135.71 171.43 150.00 171.43 0 0 107.14 214.29 228.57 228.57 15 120.00 160.00 126.67 160.00 133.33 160.00 146.67 160.00 0 0 106.67 206.67 213.33 213.33 16 118.75 150.00 125.00 150.00 131.25 150.00 143.75 150.00 0 0 106.25 200.00 200.00 200.00 17 117.65 141.18 123.53 141.18 129.41 141.18 141.18 141.18 0 0 105.88 194.12 282.35 235.29 18 116.67 133.33 122.22 133.33 127.78 133.33 138.89 177.78 0 0 105.56 188.89 266.67 222.22 19 115.79 126.32 121.05 126.32 126.32 126.32 136.84 168.42 0 0 105.26 184.21 252.63 210.53 20 115.00 120.00 120.00 120.00 125.00 160.00 135.00 160.00 0 0 105.00 180.00 240.00 200.00 21 114.29 114.29 119.05 152.38 123.81 152.38 133.33 152.38 0 0 104.76 176.19 228.57 190.48 22 113.64 145.45 118.18 145.45 122.73 145.45 131.82 145.45 0 0 104.55 172.73 218.18 181.82 23 113.04 139.13 117.39 139.13 121.74 139.13 130.43 139.13 0 0 104.35 169.57 208.70 173.91 24 112.50 133.33 116.67 133.33 120.83 133.33 129.17 133.33 0 0 104.17 166.67 200.00 166.67 25 112.00 128.00 116.00 128.00 120.00 128.00 128.00 128.00 0 0 104.00 164.00 192.00 192.00 26 111.54 123.08 115.38 123.08 119.23 123.08 126.92 184.62 0 0 103.85 161.54 184.62 184.62 27 111.11 118.52 114.81 118.52 118.52 118.52 125.93 177.78 0 0 103.70 159.26 177.78 177.78 28 110.71 114.29 114.29 114.29 117.86 171.43 125.00 171.43 0 0 103.57 157.14 171.43 171.43 29 110.34 110.34 113.79 165.52 117.24 165.52 124.14 165.52 0 0 103.45 155.17 165.52 165.52 30 110.00 160.00 113.33 160.00 116.67 160.00 123.33 160.00 0 0 103.33 153.33 160.00 160.00 31 109.68 154.84 112.90 154.84 116.13 154.84 122.58 154.84 0 0 103.23 151.61 154.84 154.84 32 109.38 150.00 112.50 150.00 115.62 150.00 121.88 150.00 0 0 103.12 150.00 150.00 150.00 33 109.09 145.45 112.12 145.45 115.15 145.45 121.21 145.45 0 0 103.03 148.48 242.42 193.94 34 108.82 141.18 111.76 141.18 114.71 141.18 120.59 141.18 0 0 102.94 147.06 235.29 188.24 35 108.57 137.14 111.43 137.14 114.29 137.14 120.00 137.14 0 0 102.86 145.71 228.57 182.86 36 108.33 133.33 111.11 133.33 113.89 133.33 119.44 133.33 0 0 102.78 144.44 222.22 177.78 37 108.11 129.73 110.81 129.73 113.51 129.73 118.92 129.73 0 0 102.70 143.24 216.22 172.97 38 107.89 126.32 110.53 126.32 113.16 126.32 118.42 126.32 0 0 102.63 142.11 210.53 168.42 39 107.69 123.08 110.26 123.08 112.82 123.08 117.95 123.08 0 0 102.56 141.03 205.13 164.10 40 107.50 120.00 110.00 120.00 112.50 120.00 117.50 120.00 0 0 102.50 140.00 200.00 160.00 41 107.32 117.07 109.76 117.07 112.20 117.07 117.07 117.07 0 0 102.44 139.02 195.12 156.10 42 107.14 114.29 109.52 114.29 111.90 114.29 116.67 152.38 0 0 102.38 138.10 190.48 152.38 43 106.98 111.63 109.30 111.63 111.63 111.63 116.28 148.84 0 0 102.33 137.21 186.05 148.84 44 106.82 109.09 109.09 109.09 111.36 145.45 115.91 145.45 0 0 102.27 136.36 181.82 145.45 45 106.67 106.67 108.89 142.22 111.11 142.22 115.56 142.22 0 0 102.22 135.56 177.78 142.22 46 106.52 139.13 108.70 139.13 110.87 139.13 115.22 139.13 0 0 102.17 134.78 173.91 139.13 47 106.38 136.17 108.51 136.17 110.64 136.17 114.89 136.17 0 0 102.13 134.04 170.21 136.17 48 106.25 133.33 108.33 133.33 110.42 133.33 114.58 133.33 0 0 102.08 133.33 166.67 133.33 49 106.12 130.61 108.16 130.61 110.20 130.61 114.29 130.61 0 0 102.04 132.65 163.27 163.27 50 106.00 128.00 108.00 128.00 110.00 128.00 114.00 128.00 0 0 102.00 132.00 160.00 160.00 51 105.88 125.49 107.84 125.49 109.80 125.49 113.73 125.49 0 0 101.96 131.37 156.86 156.86 52 105.77 123.08 107.69 123.08 109.62 123.08 113.46 123.08 0 0 101.92 130.77 153.85 153.85 53 105.66 120.75 107.55 120.75 109.43 120.75 113.21 120.75 0 0 101.89 130.19 150.94 150.94 54 105.56 118.52 107.41 118.52 109.26 118.52 112.96 118.52 0 0 101.85 129.63 148.15 148.15 55 105.45 116.36 107.27 116.36 109.09 116.36 112.73 116.36 0 0 101.82 129.09 145.45 145.45 56 105.36 114.29 107.14 114.29 108.93 114.29 112.50 114.29 0 0 101.79 128.57 142.86 142.86 57 105.26 112.28 107.02 112.28 108.77 112.28 112.28 112.28 0 0 101.75 128.07 140.35 140.35 58 105.17 110.34 106.90 110.34 108.62 110.34 112.07 165.52 0 0 101.72 127.59 137.93 137.93 59 105.08 108.47 106.78 108.47 108.47 108.47 111.86 162.71 0 0 101.69 127.12 135.59 135.59 60 105.00 106.67 106.67 106.67 108.33 160.00 111.67 160.00 0 0 101.67 126.67 133.33 133.33 61 104.92 104.92 106.56 157.38 108.20 157.38 111.48 157.38 0 0 101.64 126.23 131.15 131.15 62 104.84 154.84 106.45 154.84 108.06 154.84 111.29 154.84 0 0 101.61 125.81 129.03 129.03 63 104.76 152.38 106.35 152.38 107.94 152.38 111.11 152.38 0 0 101.59 125.40 126.98 126.98 64 104.69 150.00 106.25 150.00 107.81 150.00 110.94 150.00 0 0 101.56 125.00 125.00 125.00 65 104.62 147.69 106.15 147.69 107.69 147.69 110.77 147.69 0 0 101.54 124.62 221.54 172.31 66 104.55 145.45 106.06 145.45 107.58 145.45 110.61 145.45 0 0 101.52 124.24 218.18 169.70 67 104.48 143.28 105.97 143.28 107.46 143.28 110.45 143.28 0 0 101.49 123.88 214.93 167.16 68 104.41 141.18 105.88 141.18 107.35 141.18 110.29 141.18 0 0 101.47 123.53 211.76 164.71 69 104.35 139.13 105.80 139.13 107.25 139.13 110.14 139.13 0 0 101.45 123.19 208.70 162.32 70 104.29 137.14 105.71 137.14 107.14 137.14 110.00 137.14 0 0 101.43 122.86 205.71 160.00 71 104.23 135.21 105.63 135.21 107.04 135.21 109.86 135.21 0 0 101.41 122.54 202.82 157.75 72 104.17 133.33 105.56 133.33 106.94 133.33 109.72 133.33 0 0 101.39 122.22 200.00 155.56 73 104.11 131.51 105.48 131.51 106.85 131.51 109.59 131.51 0 0 101.37 121.92 197.26 153.42 74 104.05 129.73 105.41 129.73 106.76 129.73 109.46 129.73 0 0 101.35 121.62 194.59 151.35 75 104.00 128.00 105.33 128.00 106.67 128.00 109.33 128.00 0 0 101.33 121.33 192.00 149.33 76 103.95 126.32 105.26 126.32 106.58 126.32 109.21 126.32 0 0 101.32 121.05 189.47 147.37 77 103.90 124.68 105.19 124.68 106.49 124.68 109.09 124.68 0 0 101.30 120.78 187.01 145.45 78 103.85 123.08 105.13 123.08 106.41 123.08 108.97 123.08 0 0 101.28 120.51 184.62 143.59 79 103.80 121.52 105.06 121.52 106.33 121.52 108.86 121.52 0 0 101.27 120.25 182.28 141.77 80 103.75 120.00 105.00 120.00 106.25 120.00 108.75 120.00 0 0 101.25 120.00 180.00 140.00 81 103.70 118.52 104.94 118.52 106.17 118.52 108.64 118.52 0 0 101.23 119.75 177.78 138.27 82 103.66 117.07 104.88 117.07 106.10 117.07 108.54 117.07 0 0 101.22 119.51 175.61 136.59 83 103.61 115.66 104.82 115.66 106.02 115.66 108.43 115.66 0 0 101.20 119.28 173.49 134.94 84 103.57 114.29 104.76 114.29 105.95 114.29 108.33 114.29 0 0 101.19 119.05 171.43 133.33 85 103.53 112.94 104.71 112.94 105.88 112.94 108.24 112.94 0 0 101.18 118.82 169.41 131.76 86 103.49 111.63 104.65 111.63 105.81 111.63 108.14 111.63 0 0 101.16 118.60 167.44 130.23 87 103.45 110.34 104.60 110.34 105.75 110.34 108.05 110.34 0 0 101.15 118.39 165.52 128.74 88 103.41 109.09 104.55 109.09 105.68 109.09 107.95 109.09 0 0 101.14 118.18 163.64 127.27 89 103.37 107.87 104.49 107.87 105.62 107.87 107.87 107.87 0 0 101.12 117.98 161.80 125.84 90 103.33 106.67 104.44 106.67 105.56 106.67 107.78 142.22 0 0 101.11 117.78 160.00 124.44 91 103.30 105.49 104.40 105.49 105.49 105.49 107.69 140.66 0 0 101.10 117.58 158.24 123.08 92 103.26 104.35 104.35 104.35 105.43 139.13 107.61 139.13 0 0 101.09 117.39 156.52 121.74 93 103.23 103.23 104.30 137.63 105.38 137.63 107.53 137.63 0 0 101.08 117.20 154.84 120.43 94 103.19 136.17 104.26 136.17 105.32 136.17 107.45 136.17 0 0 101.06 117.02 153.19 119.15 95 103.16 134.74 104.21 134.74 105.26 134.74 107.37 134.74 0 0 101.05 116.84 151.58 117.89 96 103.12 133.33 104.17 133.33 105.21 133.33 107.29 133.33 0 0 101.04 116.67 150.00 116.67 97 103.09 131.96 104.12 131.96 105.15 131.96 107.22 131.96 0 0 101.03 116.49 148.45 148.45 98 103.06 130.61 104.08 130.61 105.10 130.61 107.14 130.61 0 0 101.02 116.33 146.94 146.94 99 103.03 129.29 104.04 129.29 105.05 129.29 107.07 129.29 0 0 101.01 116.16 145.45 145.45 100 103.00 128.00 104.00 128.00 105.00 128.00 107.00 128.00 0 0 101.00 116.00 144.00 144.00 101 102.97 126.73 103.96 126.73 104.95 126.73 106.93 126.73 0 0 100.99 115.84 142.57 142.57 102 102.94 125.49 103.92 125.49 104.90 125.49 106.86 125.49 0 0 100.98 115.69 141.18 141.18 103 102.91 124.27 103.88 124.27 104.85 124.27 106.80 124.27 0 0 100.97 115.53 139.81 139.81 104 102.88 123.08 103.85 123.08 104.81 123.08 106.73 123.08 0 0 100.96 115.38 138.46 138.46 105 102.86 121.90 103.81 121.90 104.76 121.90 106.67 121.90 0 0 100.95 115.24 137.14 137.14 106 102.83 120.75 103.77 120.75 104.72 120.75 106.60 120.75 0 0 100.94 115.09 135.85 135.85 107 102.80 119.63 103.74 119.63 104.67 119.63 106.54 119.63 0 0 100.93 114.95 134.58 134.58 108 102.78 118.52 103.70 118.52 104.63 118.52 106.48 118.52 0 0 100.93 114.81 133.33 133.33 109 102.75 117.43 103.67 117.43 104.59 117.43 106.42 117.43 0 0 100.92 114.68 132.11 132.11 110 102.73 116.36 103.64 116.36 104.55 116.36 106.36 116.36 0 0 100.91 114.55 130.91 130.91 111 102.70 115.32 103.60 115.32 104.50 115.32 106.31 115.32 0 0 100.90 114.41 129.73 129.73 112 102.68 114.29 103.57 114.29 104.46 114.29 106.25 114.29 0 0 100.89 114.29 128.57 128.57 113 102.65 113.27 103.54 113.27 104.42 113.27 106.19 113.27 0 0 100.88 114.16 127.43 127.43 114 102.63 112.28 103.51 112.28 104.39 112.28 106.14 112.28 0 0 100.88 114.04 126.32 126.32 115 102.61 111.30 103.48 111.30 104.35 111.30 106.09 111.30 0 0 100.87 113.91 125.22 125.22 116 102.59 110.34 103.45 110.34 104.31 110.34 106.03 110.34 0 0 100.86 113.79 124.14 124.14 117 102.56 109.40 103.42 109.40 104.27 109.40 105.98 109.40 0 0 100.85 113.68 123.08 123.08 118 102.54 108.47 103.39 108.47 104.24 108.47 105.93 108.47 0 0 100.85 113.56 122.03 122.03 119 102.52 107.56 103.36 107.56 104.20 107.56 105.88 107.56 0 0 100.84 113.45 121.01 121.01 120 102.50 106.67 103.33 106.67 104.17 106.67 105.83 106.67 0 0 100.83 113.33 120.00 120.00 121 102.48 105.79 103.31 105.79 104.13 105.79 105.79 105.79 0 0 100.83 113.22 119.01 119.01 122 102.46 104.92 103.28 104.92 104.10 104.92 105.74 157.38 0 0 100.82 113.11 118.03 118.03 123 102.44 104.07 103.25 104.07 104.07 104.07 105.69 156.10 0 0 100.81 113.01 117.07 117.07 124 102.42 103.23 103.23 103.23 104.03 154.84 105.65 154.84 0 0 100.81 112.90 116.13 116.13 125 102.40 102.40 103.20 153.60 104.00 153.60 105.60 153.60 0 0 100.80 112.80 115.20 115.20 126 102.38 152.38 103.17 152.38 103.97 152.38 105.56 152.38 0 0 100.79 112.70 114.29 114.29 127 102.36 151.18 103.15 151.18 103.94 151.18 105.51 151.18 0 0 100.79 112.60 113.39 113.39 128 102.34 150.00 103.12 150.00 103.91 150.00 105.47 150.00 0 0 100.78 112.50 112.50 112.50 129 102.33 148.84 103.10 148.84 103.88 148.84 105.43 148.84 0 0 100.78 112.40 210.85 161.24 130 102.31 147.69 103.08 147.69 103.85 147.69 105.38 147.69 0 0 100.77 112.31 209.23 160.00 131 102.29 146.56 103.05 146.56 103.82 146.56 105.34 146.56 0 0 100.76 112.21 207.63 158.78 132 102.27 145.45 103.03 145.45 103.79 145.45 105.30 145.45 0 0 100.76 112.12 206.06 157.58 133 102.26 144.36 103.01 144.36 103.76 144.36 105.26 144.36 0 0 100.75 112.03 204.51 156.39 134 102.24 143.28 102.99 143.28 103.73 143.28 105.22 143.28 0 0 100.75 111.94 202.99 155.22 135 102.22 142.22 102.96 142.22 103.70 142.22 105.19 142.22 0 0 100.74 111.85 201.48 154.07 136 102.21 141.18 102.94 141.18 103.68 141.18 105.15 141.18 0 0 100.74 111.76 200.00 152.94 137 102.19 140.15 102.92 140.15 103.65 140.15 105.11 140.15 0 0 100.73 111.68 198.54 151.82 138 102.17 139.13 102.90 139.13 103.62 139.13 105.07 139.13 0 0 100.72 111.59 197.10 150.72 139 102.16 138.13 102.88 138.13 103.60 138.13 105.04 138.13 0 0 100.72 111.51 195.68 149.64 140 102.14 137.14 102.86 137.14 103.57 137.14 105.00 137.14 0 0 100.71 111.43 194.29 148.57 141 102.13 136.17 102.84 136.17 103.55 136.17 104.96 136.17 0 0 100.71 111.35 192.91 147.52 142 102.11 135.21 102.82 135.21 103.52 135.21 104.93 135.21 0 0 100.70 111.27 191.55 146.48 143 102.10 134.27 102.80 134.27 103.50 134.27 104.90 134.27 0 0 100.70 111.19 190.21 145.45 144 102.08 133.33 102.78 133.33 103.47 133.33 104.86 133.33 0 0 100.69 111.11 188.89 144.44 145 102.07 132.41 102.76 132.41 103.45 132.41 104.83 132.41 0 0 100.69 111.03 187.59 143.45 146 102.05 131.51 102.74 131.51 103.42 131.51 104.79 131.51 0 0 100.68 110.96 186.30 142.47 147 102.04 130.61 102.72 130.61 103.40 130.61 104.76 130.61 0 0 100.68 110.88 185.03 141.50 148 102.03 129.73 102.70 129.73 103.38 129.73 104.73 129.73 0 0 100.68 110.81 183.78 140.54 149 102.01 128.86 102.68 128.86 103.36 128.86 104.70 128.86 0 0 100.67 110.74 182.55 139.60 150 102.00 128.00 102.67 128.00 103.33 128.00 104.67 128.00 0 0 100.67 110.67 181.33 138.67 151 101.99 127.15 102.65 127.15 103.31 127.15 104.64 127.15 0 0 100.66 110.60 180.13 137.75 152 101.97 126.32 102.63 126.32 103.29 126.32 104.61 126.32 0 0 100.66 110.53 178.95 136.84 153 101.96 125.49 102.61 125.49 103.27 125.49 104.58 125.49 0 0 100.65 110.46 177.78 135.95 154 101.95 124.68 102.60 124.68 103.25 124.68 104.55 124.68 0 0 100.65 110.39 176.62 135.06 155 101.94 123.87 102.58 123.87 103.23 123.87 104.52 123.87 0 0 100.65 110.32 175.48 134.19 156 101.92 123.08 102.56 123.08 103.21 123.08 104.49 123.08 0 0 100.64 110.26 174.36 133.33 157 101.91 122.29 102.55 122.29 103.18 122.29 104.46 122.29 0 0 100.64 110.19 173.25 132.48 158 101.90 121.52 102.53 121.52 103.16 121.52 104.43 121.52 0 0 100.63 110.13 172.15 131.65 159 101.89 120.75 102.52 120.75 103.14 120.75 104.40 120.75 0 0 100.63 110.06 171.07 130.82 160 101.88 120.00 102.50 120.00 103.12 120.00 104.38 120.00 0 0 100.62 110.00 170.00 130.00 161 101.86 119.25 102.48 119.25 103.11 119.25 104.35 119.25 0 0 100.62 109.94 168.94 129.19 162 101.85 118.52 102.47 118.52 103.09 118.52 104.32 118.52 0 0 100.62 109.88 167.90 128.40 163 101.84 117.79 102.45 117.79 103.07 117.79 104.29 117.79 0 0 100.61 109.82 166.87 127.61 164 101.83 117.07 102.44 117.07 103.05 117.07 104.27 117.07 0 0 100.61 109.76 165.85 126.83 165 101.82 116.36 102.42 116.36 103.03 116.36 104.24 116.36 0 0 100.61 109.70 164.85 126.06 166 101.81 115.66 102.41 115.66 103.01 115.66 104.22 115.66 0 0 100.60 109.64 163.86 125.30 167 101.80 114.97 102.40 114.97 102.99 114.97 104.19 114.97 0 0 100.60 109.58 162.87 124.55 168 101.79 114.29 102.38 114.29 102.98 114.29 104.17 114.29 0 0 100.60 109.52 161.90 123.81 169 101.78 113.61 102.37 113.61 102.96 113.61 104.14 113.61 0 0 100.59 109.47 160.95 123.08 170 101.76 112.94 102.35 112.94 102.94 112.94 104.12 112.94 0 0 100.59 109.41 160.00 122.35 171 101.75 112.28 102.34 112.28 102.92 112.28 104.09 112.28 0 0 100.58 109.36 159.06 121.64 172 101.74 111.63 102.33 111.63 102.91 111.63 104.07 111.63 0 0 100.58 109.30 158.14 120.93 173 101.73 110.98 102.31 110.98 102.89 110.98 104.05 110.98 0 0 100.58 109.25 157.23 120.23 174 101.72 110.34 102.30 110.34 102.87 110.34 104.02 110.34 0 0 100.57 109.20 156.32 119.54 175 101.71 109.71 102.29 109.71 102.86 109.71 104.00 109.71 0 0 100.57 109.14 155.43 118.86 176 101.70 109.09 102.27 109.09 102.84 109.09 103.98 109.09 0 0 100.57 109.09 154.55 118.18 177 101.69 108.47 102.26 108.47 102.82 108.47 103.95 108.47 0 0 100.56 109.04 153.67 117.51 178 101.69 107.87 102.25 107.87 102.81 107.87 103.93 107.87 0 0 100.56 108.99 152.81 116.85 179 101.68 107.26 102.23 107.26 102.79 107.26 103.91 107.26 0 0 100.56 108.94 151.96 116.20 180 101.67 106.67 102.22 106.67 102.78 106.67 103.89 106.67 0 0 100.56 108.89 151.11 115.56 181 101.66 106.08 102.21 106.08 102.76 106.08 103.87 106.08 0 0 100.55 108.84 150.28 114.92 182 101.65 105.49 102.20 105.49 102.75 105.49 103.85 105.49 0 0 100.55 108.79 149.45 114.29 183 101.64 104.92 102.19 104.92 102.73 104.92 103.83 104.92 0 0 100.55 108.74 148.63 113.66 184 101.63 104.35 102.17 104.35 102.72 104.35 103.80 104.35 0 0 100.54 108.70 147.83 113.04 185 101.62 103.78 102.16 103.78 102.70 103.78 103.78 103.78 0 0 100.54 108.65 147.03 112.43 186 101.61 103.23 102.15 103.23 102.69 103.23 103.76 137.63 0 0 100.54 108.60 146.24 111.83 187 101.60 102.67 102.14 102.67 102.67 102.67 103.74 136.90 0 0 100.53 108.56 145.45 111.23 188 101.60 102.13 102.13 102.13 102.66 136.17 103.72 136.17 0 0 100.53 108.51 144.68 110.64 189 101.59 101.59 102.12 135.45 102.65 135.45 103.70 135.45 0 0 100.53 108.47 143.92 110.05 190 101.58 134.74 102.11 134.74 102.63 134.74 103.68 134.74 0 0 100.53 108.42 143.16 109.47 191 101.57 134.03 102.09 134.03 102.62 134.03 103.66 134.03 0 0 100.52 108.38 142.41 108.90 192 101.56 133.33 102.08 133.33 102.60 133.33 103.65 133.33 0 0 100.52 108.33 141.67 108.33 193 101.55 132.64 102.07 132.64 102.59 132.64 103.63 132.64 0 0 100.52 108.29 140.93 140.93 194 101.55 131.96 102.06 131.96 102.58 131.96 103.61 131.96 0 0 100.52 108.25 140.21 140.21 195 101.54 131.28 102.05 131.28 102.56 131.28 103.59 131.28 0 0 100.51 108.21 139.49 139.49 196 101.53 130.61 102.04 130.61 102.55 130.61 103.57 130.61 0 0 100.51 108.16 138.78 138.78 197 101.52 129.95 102.03 129.95 102.54 129.95 103.55 129.95 0 0 100.51 108.12 138.07 138.07 198 101.52 129.29 102.02 129.29 102.53 129.29 103.54 129.29 0 0 100.51 108.08 137.37 137.37 199 101.51 128.64 102.01 128.64 102.51 128.64 103.52 128.64 0 0 100.50 108.04 136.68 136.68 200 101.50 128.00 102.00 128.00 102.50 128.00 103.50 128.00 0 0 100.50 108.00 136.00 136.00 201 101.49 127.36 101.99 127.36 102.49 127.36 103.48 127.36 0 0 100.50 107.96 135.32 135.32 202 101.49 126.73 101.98 126.73 102.48 126.73 103.47 126.73 0 0 100.50 107.92 134.65 134.65 203 101.48 126.11 101.97 126.11 102.46 126.11 103.45 126.11 0 0 100.49 107.88 133.99 133.99 204 101.47 125.49 101.96 125.49 102.45 125.49 103.43 125.49 0 0 100.49 107.84 133.33 133.33 205 101.46 124.88 101.95 124.88 102.44 124.88 103.41 124.88 0 0 100.49 107.80 132.68 132.68 206 101.46 124.27 101.94 124.27 102.43 124.27 103.40 124.27 0 0 100.49 107.77 132.04 132.04 207 101.45 123.67 101.93 123.67 102.42 123.67 103.38 123.67 0 0 100.48 107.73 131.40 131.40 208 101.44 123.08 101.92 123.08 102.40 123.08 103.37 123.08 0 0 100.48 107.69 130.77 130.77 209 101.44 122.49 101.91 122.49 102.39 122.49 103.35 122.49 0 0 100.48 107.66 130.14 130.14 210 101.43 121.90 101.90 121.90 102.38 121.90 103.33 121.90 0 0 100.48 107.62 129.52 129.52 211 101.42 121.33 101.90 121.33 102.37 121.33 103.32 121.33 0 0 100.47 107.58 128.91 128.91 212 101.42 120.75 101.89 120.75 102.36 120.75 103.30 120.75 0 0 100.47 107.55 128.30 128.30 213 101.41 120.19 101.88 120.19 102.35 120.19 103.29 120.19 0 0 100.47 107.51 127.70 127.70 214 101.40 119.63 101.87 119.63 102.34 119.63 103.27 119.63 0 0 100.47 107.48 127.10 127.10 215 101.40 119.07 101.86 119.07 102.33 119.07 103.26 119.07 0 0 100.47 107.44 126.51 126.51 216 101.39 118.52 101.85 118.52 102.31 118.52 103.24 118.52 0 0 100.46 107.41 125.93 125.93 217 101.38 117.97 101.84 117.97 102.30 117.97 103.23 117.97 0 0 100.46 107.37 125.35 125.35 218 101.38 117.43 101.83 117.43 102.29 117.43 103.21 117.43 0 0 100.46 107.34 124.77 124.77 219 101.37 116.89 101.83 116.89 102.28 116.89 103.20 116.89 0 0 100.46 107.31 124.20 124.20 220 101.36 116.36 101.82 116.36 102.27 116.36 103.18 116.36 0 0 100.45 107.27 123.64 123.64 221 101.36 115.84 101.81 115.84 102.26 115.84 103.17 115.84 0 0 100.45 107.24 123.08 123.08 222 101.35 115.32 101.80 115.32 102.25 115.32 103.15 115.32 0 0 100.45 107.21 122.52 122.52 223 101.35 114.80 101.79 114.80 102.24 114.80 103.14 114.80 0 0 100.45 107.17 121.97 121.97 224 101.34 114.29 101.79 114.29 102.23 114.29 103.12 114.29 0 0 100.45 107.14 121.43 121.43 225 101.33 113.78 101.78 113.78 102.22 113.78 103.11 113.78 0 0 100.44 107.11 120.89 120.89 226 101.33 113.27 101.77 113.27 102.21 113.27 103.10 113.27 0 0 100.44 107.08 120.35 120.35 227 101.32 112.78 101.76 112.78 102.20 112.78 103.08 112.78 0 0 100.44 107.05 119.82 119.82 228 101.32 112.28 101.75 112.28 102.19 112.28 103.07 112.28 0 0 100.44 107.02 119.30 119.30 229 101.31 111.79 101.75 111.79 102.18 111.79 103.06 111.79 0 0 100.44 106.99 118.78 118.78 230 101.30 111.30 101.74 111.30 102.17 111.30 103.04 111.30 0 0 100.43 106.96 118.26 118.26 231 101.30 110.82 101.73 110.82 102.16 110.82 103.03 110.82 0 0 100.43 106.93 117.75 117.75 232 101.29 110.34 101.72 110.34 102.16 110.34 103.02 110.34 0 0 100.43 106.90 117.24 117.24 233 101.29 109.87 101.72 109.87 102.15 109.87 103.00 109.87 0 0 100.43 106.87 116.74 116.74 234 101.28 109.40 101.71 109.40 102.14 109.40 102.99 109.40 0 0 100.43 106.84 116.24 116.24 235 101.28 108.94 101.70 108.94 102.13 108.94 102.98 108.94 0 0 100.43 106.81 115.74 115.74 236 101.27 108.47 101.69 108.47 102.12 108.47 102.97 108.47 0 0 100.42 106.78 115.25 115.25 237 101.27 108.02 101.69 108.02 102.11 108.02 102.95 108.02 0 0 100.42 106.75 114.77 114.77 238 101.26 107.56 101.68 107.56 102.10 107.56 102.94 107.56 0 0 100.42 106.72 114.29 114.29 239 101.26 107.11 101.67 107.11 102.09 107.11 102.93 107.11 0 0 100.42 106.69 113.81 113.81 240 101.25 106.67 101.67 106.67 102.08 106.67 102.92 106.67 0 0 100.42 106.67 113.33 113.33 241 101.24 106.22 101.66 106.22 102.07 106.22 102.90 106.22 0 0 100.41 106.64 112.86 112.86 242 101.24 105.79 101.65 105.79 102.07 105.79 102.89 105.79 0 0 100.41 106.61 112.40 112.40 243 101.23 105.35 101.65 105.35 102.06 105.35 102.88 105.35 0 0 100.41 106.58 111.93 111.93 244 101.23 104.92 101.64 104.92 102.05 104.92 102.87 104.92 0 0 100.41 106.56 111.48 111.48 245 101.22 104.49 101.63 104.49 102.04 104.49 102.86 104.49 0 0 100.41 106.53 111.02 111.02 246 101.22 104.07 101.63 104.07 102.03 104.07 102.85 104.07 0 0 100.41 106.50 110.57 110.57 247 101.21 103.64 101.62 103.64 102.02 103.64 102.83 103.64 0 0 100.40 106.48 110.12 110.12 248 101.21 103.23 101.61 103.23 102.02 103.23 102.82 103.23 0 0 100.40 106.45 109.68 109.68 249 101.20 102.81 101.61 102.81 102.01 102.81 102.81 102.81 0 0 100.40 106.43 109.24 109.24 250 101.20 102.40 101.60 102.40 102.00 102.40 102.80 153.60 0 0 100.40 106.40 108.80 108.80 251 101.20 101.99 101.59 101.99 101.99 101.99 102.79 152.99 0 0 100.40 106.37 108.37 108.37 252 101.19 101.59 101.59 101.59 101.98 152.38 102.78 152.38 0 0 100.40 106.35 107.94 107.94 253 101.19 101.19 101.58 151.78 101.98 151.78 102.77 151.78 0 0 100.40 106.32 107.51 107.51 254 101.18 151.18 101.57 151.18 101.97 151.18 102.76 151.18 0 0 100.39 106.30 107.09 107.09 255 101.18 150.59 101.57 150.59 101.96 150.59 102.75 150.59 0 0 100.39 106.27 106.67 106.67 256 101.56 150.00 101.95 150.00 102.34 150.00 103.12 150.00 0 0 100.39 106.25 106.25 106.25 257 101.56 149.42 101.95 149.42 102.33 149.42 103.11 149.42 0 0 100.39 106.23 205.45 155.64 258 101.55 148.84 101.94 148.84 102.33 148.84 103.10 148.84 0 0 100.39 106.20 204.65 155.04 259 101.54 148.26 101.93 148.26 102.32 148.26 103.09 148.26 0 0 100.39 106.18 203.86 154.44 ustr-1.0.4/perf/sizes_out_64bit.tsv0000644000076400007640000006636710630111754016247 0ustar jamesjames# set style data lines # set xrange [0:259] # set yrange [100:500] # # set xlabel "Length" # set ylabel "Percent bigger" # # plot "sizes_out_64bit.tsv" using 1:2 title 'Ss0', # "sizes_out_64bit.tsv" using 1:3 title 'Ss1', # "sizes_out_64bit.tsv" using 1:4 title 'Ss2', # "sizes_out_64bit.tsv" using 1:5 title 'Ss3', # "sizes_out_64bit.tsv" using 1:6 title 'Ss4', # "sizes_out_64bit.tsv" using 1:7 title 'Ss5', # "sizes_out_64bit.tsv" using 1:8 title 'Ss6', # "sizes_out_64bit.tsv" using 1:9 title 'Ss7', # "sizes_out_64bit.tsv" using 1:10 title 'Ss8', # "sizes_out_64bit.tsv" using 1:11 title 'Ss9', # "sizes_out_64bit.tsv" using 1:12 title 'strdup', # "sizes_out_64bit.tsv" using 1:13 title 'NM_Ss', # "sizes_out_64bit.tsv" using 1:14 title 'NM_Ss x2', # "sizes_out_64bit.tsv" using 1:15 title 'NM_Ss xSs' # # plot "sizes_out_32bit.tsv" using 1:2 title 'Ss0', # "sizes_out_32bit.tsv" using 1:3 title 'Ss1', # "sizes_out_32bit.tsv" using 1:4 title 'Ss2', # "sizes_out_32bit.tsv" using 1:5 title 'Ss3', # "sizes_out_32bit.tsv" using 1:6 title 'Ss4', # "sizes_out_32bit.tsv" using 1:7 title 'Ss5', # "sizes_out_32bit.tsv" using 1:8 title 'Ss6', # "sizes_out_32bit.tsv" using 1:9 title 'Ss7', # "sizes_out_32bit.tsv" using 1:12 title 'strdup', # "sizes_out_32bit.tsv" using 1:13 title 'NM_Ss', # "sizes_out_32bit.tsv" using 1:14 title 'NM_Ss x2', # "sizes_out_32bit.tsv" using 1:15 title 'NM_Ss xSs' # # set xrange [1:59] # set yrange [100:800] # replot # 1 400.00 400.00 500.00 600.00 600.00 600.00 800.00 800.00 1200.00 1200.00 200.00 3400.00 3400.00 3400.00 2 250.00 300.00 300.00 300.00 350.00 400.00 450.00 600.00 650.00 800.00 100.00 1750.00 1800.00 1750.00 3 200.00 200.00 233.33 266.67 266.67 266.67 333.33 400.00 466.67 533.33 100.00 1200.00 1200.00 1200.00 4 175.00 200.00 200.00 200.00 225.00 300.00 275.00 300.00 375.00 400.00 100.00 925.00 1000.00 950.00 5 160.00 160.00 180.00 240.00 200.00 240.00 240.00 240.00 320.00 320.00 100.00 760.00 800.00 760.00 6 150.00 200.00 166.67 200.00 183.33 200.00 216.67 266.67 283.33 400.00 100.00 650.00 666.67 666.67 7 142.86 171.43 157.14 171.43 171.43 171.43 200.00 228.57 257.14 342.86 100.00 571.43 571.43 571.43 8 137.50 150.00 150.00 150.00 162.50 200.00 187.50 200.00 237.50 300.00 100.00 512.50 600.00 550.00 9 133.33 133.33 144.44 177.78 155.56 177.78 177.78 177.78 222.22 266.67 100.00 466.67 533.33 488.89 10 130.00 160.00 140.00 160.00 150.00 160.00 170.00 240.00 210.00 240.00 100.00 430.00 480.00 440.00 11 127.27 145.45 136.36 145.45 145.45 145.45 163.64 218.18 200.00 218.18 100.00 400.00 436.36 400.00 12 125.00 133.33 133.33 133.33 141.67 200.00 158.33 200.00 191.67 200.00 100.00 375.00 400.00 400.00 13 123.08 123.08 130.77 184.62 138.46 184.62 153.85 184.62 184.62 184.62 100.00 353.85 369.23 369.23 14 121.43 171.43 128.57 171.43 135.71 171.43 150.00 171.43 178.57 228.57 100.00 335.71 342.86 342.86 15 120.00 160.00 126.67 160.00 133.33 160.00 146.67 160.00 173.33 213.33 100.00 320.00 320.00 320.00 16 118.75 150.00 125.00 150.00 131.25 150.00 143.75 150.00 168.75 200.00 100.00 306.25 400.00 350.00 17 117.65 141.18 123.53 141.18 129.41 141.18 141.18 141.18 164.71 188.24 100.00 294.12 376.47 329.41 18 116.67 133.33 122.22 133.33 127.78 133.33 138.89 177.78 161.11 177.78 100.00 283.33 355.56 311.11 19 115.79 126.32 121.05 126.32 126.32 126.32 136.84 168.42 157.89 168.42 100.00 273.68 336.84 294.74 20 115.00 120.00 120.00 120.00 125.00 160.00 135.00 160.00 155.00 160.00 100.00 265.00 320.00 280.00 21 114.29 114.29 119.05 152.38 123.81 152.38 133.33 152.38 152.38 152.38 100.00 257.14 304.76 266.67 22 113.64 145.45 118.18 145.45 122.73 145.45 131.82 145.45 150.00 218.18 100.00 250.00 290.91 254.55 23 113.04 139.13 117.39 139.13 121.74 139.13 130.43 139.13 147.83 208.70 100.00 243.48 278.26 243.48 24 112.50 133.33 116.67 133.33 120.83 133.33 129.17 133.33 145.83 200.00 100.00 237.50 266.67 266.67 25 112.00 128.00 116.00 128.00 120.00 128.00 128.00 128.00 144.00 192.00 100.00 232.00 256.00 256.00 26 111.54 123.08 115.38 123.08 119.23 123.08 126.92 184.62 142.31 184.62 100.00 226.92 246.15 246.15 27 111.11 118.52 114.81 118.52 118.52 118.52 125.93 177.78 140.74 177.78 100.00 222.22 237.04 237.04 28 110.71 114.29 114.29 114.29 117.86 171.43 125.00 171.43 139.29 171.43 100.00 217.86 228.57 228.57 29 110.34 110.34 113.79 165.52 117.24 165.52 124.14 165.52 137.93 165.52 100.00 213.79 220.69 220.69 30 110.00 160.00 113.33 160.00 116.67 160.00 123.33 160.00 136.67 160.00 100.00 210.00 213.33 213.33 31 109.68 154.84 112.90 154.84 116.13 154.84 122.58 154.84 135.48 154.84 100.00 206.45 206.45 206.45 32 109.38 150.00 112.50 150.00 115.62 150.00 121.88 150.00 134.38 150.00 100.00 203.12 300.00 250.00 33 109.09 145.45 112.12 145.45 115.15 145.45 121.21 145.45 133.33 145.45 100.00 200.00 290.91 242.42 34 108.82 141.18 111.76 141.18 114.71 141.18 120.59 141.18 132.35 141.18 100.00 197.06 282.35 235.29 35 108.57 137.14 111.43 137.14 114.29 137.14 120.00 137.14 131.43 137.14 100.00 194.29 274.29 228.57 36 108.33 133.33 111.11 133.33 113.89 133.33 119.44 133.33 130.56 133.33 100.00 191.67 266.67 222.22 37 108.11 129.73 110.81 129.73 113.51 129.73 118.92 129.73 129.73 129.73 100.00 189.19 259.46 216.22 38 107.89 126.32 110.53 126.32 113.16 126.32 118.42 126.32 128.95 168.42 100.00 186.84 252.63 210.53 39 107.69 123.08 110.26 123.08 112.82 123.08 117.95 123.08 128.21 164.10 100.00 184.62 246.15 205.13 40 107.50 120.00 110.00 120.00 112.50 120.00 117.50 120.00 127.50 160.00 100.00 182.50 240.00 200.00 41 107.32 117.07 109.76 117.07 112.20 117.07 117.07 117.07 126.83 156.10 100.00 180.49 234.15 195.12 42 107.14 114.29 109.52 114.29 111.90 114.29 116.67 152.38 126.19 152.38 100.00 178.57 228.57 190.48 43 106.98 111.63 109.30 111.63 111.63 111.63 116.28 148.84 125.58 148.84 100.00 176.74 223.26 186.05 44 106.82 109.09 109.09 109.09 111.36 145.45 115.91 145.45 125.00 145.45 100.00 175.00 218.18 181.82 45 106.67 106.67 108.89 142.22 111.11 142.22 115.56 142.22 124.44 142.22 100.00 173.33 213.33 177.78 46 106.52 139.13 108.70 139.13 110.87 139.13 115.22 139.13 123.91 139.13 100.00 171.74 208.70 173.91 47 106.38 136.17 108.51 136.17 110.64 136.17 114.89 136.17 123.40 136.17 100.00 170.21 204.26 170.21 48 106.25 133.33 108.33 133.33 110.42 133.33 114.58 133.33 122.92 133.33 100.00 168.75 200.00 200.00 49 106.12 130.61 108.16 130.61 110.20 130.61 114.29 130.61 122.45 130.61 100.00 167.35 195.92 195.92 50 106.00 128.00 108.00 128.00 110.00 128.00 114.00 128.00 122.00 128.00 100.00 166.00 192.00 192.00 51 105.88 125.49 107.84 125.49 109.80 125.49 113.73 125.49 121.57 125.49 100.00 164.71 188.24 188.24 52 105.77 123.08 107.69 123.08 109.62 123.08 113.46 123.08 121.15 123.08 100.00 163.46 184.62 184.62 53 105.66 120.75 107.55 120.75 109.43 120.75 113.21 120.75 120.75 120.75 100.00 162.26 181.13 181.13 54 105.56 118.52 107.41 118.52 109.26 118.52 112.96 118.52 120.37 177.78 100.00 161.11 177.78 177.78 55 105.45 116.36 107.27 116.36 109.09 116.36 112.73 116.36 120.00 174.55 100.00 160.00 174.55 174.55 56 105.36 114.29 107.14 114.29 108.93 114.29 112.50 114.29 119.64 171.43 100.00 158.93 171.43 171.43 57 105.26 112.28 107.02 112.28 108.77 112.28 112.28 112.28 119.30 168.42 100.00 157.89 168.42 168.42 58 105.17 110.34 106.90 110.34 108.62 110.34 112.07 165.52 118.97 165.52 100.00 156.90 165.52 165.52 59 105.08 108.47 106.78 108.47 108.47 108.47 111.86 162.71 118.64 162.71 100.00 155.93 162.71 162.71 60 105.00 106.67 106.67 106.67 108.33 160.00 111.67 160.00 118.33 160.00 100.00 155.00 160.00 160.00 61 104.92 104.92 106.56 157.38 108.20 157.38 111.48 157.38 118.03 157.38 100.00 154.10 157.38 157.38 62 104.84 154.84 106.45 154.84 108.06 154.84 111.29 154.84 117.74 154.84 100.00 153.23 154.84 154.84 63 104.76 152.38 106.35 152.38 107.94 152.38 111.11 152.38 117.46 152.38 100.00 152.38 152.38 152.38 64 104.69 150.00 106.25 150.00 107.81 150.00 110.94 150.00 117.19 150.00 100.00 151.56 250.00 200.00 65 104.62 147.69 106.15 147.69 107.69 147.69 110.77 147.69 116.92 147.69 100.00 150.77 246.15 196.92 66 104.55 145.45 106.06 145.45 107.58 145.45 110.61 145.45 116.67 145.45 100.00 150.00 242.42 193.94 67 104.48 143.28 105.97 143.28 107.46 143.28 110.45 143.28 116.42 143.28 100.00 149.25 238.81 191.04 68 104.41 141.18 105.88 141.18 107.35 141.18 110.29 141.18 116.18 141.18 100.00 148.53 235.29 188.24 69 104.35 139.13 105.80 139.13 107.25 139.13 110.14 139.13 115.94 139.13 100.00 147.83 231.88 185.51 70 104.29 137.14 105.71 137.14 107.14 137.14 110.00 137.14 115.71 137.14 100.00 147.14 228.57 182.86 71 104.23 135.21 105.63 135.21 107.04 135.21 109.86 135.21 115.49 135.21 100.00 146.48 225.35 180.28 72 104.17 133.33 105.56 133.33 106.94 133.33 109.72 133.33 115.28 133.33 100.00 145.83 222.22 177.78 73 104.11 131.51 105.48 131.51 106.85 131.51 109.59 131.51 115.07 131.51 100.00 145.21 219.18 175.34 74 104.05 129.73 105.41 129.73 106.76 129.73 109.46 129.73 114.86 129.73 100.00 144.59 216.22 172.97 75 104.00 128.00 105.33 128.00 106.67 128.00 109.33 128.00 114.67 128.00 100.00 144.00 213.33 170.67 76 103.95 126.32 105.26 126.32 106.58 126.32 109.21 126.32 114.47 126.32 100.00 143.42 210.53 168.42 77 103.90 124.68 105.19 124.68 106.49 124.68 109.09 124.68 114.29 124.68 100.00 142.86 207.79 166.23 78 103.85 123.08 105.13 123.08 106.41 123.08 108.97 123.08 114.10 123.08 100.00 142.31 205.13 164.10 79 103.80 121.52 105.06 121.52 106.33 121.52 108.86 121.52 113.92 121.52 100.00 141.77 202.53 162.03 80 103.75 120.00 105.00 120.00 106.25 120.00 108.75 120.00 113.75 120.00 100.00 141.25 200.00 160.00 81 103.70 118.52 104.94 118.52 106.17 118.52 108.64 118.52 113.58 118.52 100.00 140.74 197.53 158.02 82 103.66 117.07 104.88 117.07 106.10 117.07 108.54 117.07 113.41 117.07 100.00 140.24 195.12 156.10 83 103.61 115.66 104.82 115.66 106.02 115.66 108.43 115.66 113.25 115.66 100.00 139.76 192.77 154.22 84 103.57 114.29 104.76 114.29 105.95 114.29 108.33 114.29 113.10 114.29 100.00 139.29 190.48 152.38 85 103.53 112.94 104.71 112.94 105.88 112.94 108.24 112.94 112.94 112.94 100.00 138.82 188.24 150.59 86 103.49 111.63 104.65 111.63 105.81 111.63 108.14 111.63 112.79 148.84 100.00 138.37 186.05 148.84 87 103.45 110.34 104.60 110.34 105.75 110.34 108.05 110.34 112.64 147.13 100.00 137.93 183.91 147.13 88 103.41 109.09 104.55 109.09 105.68 109.09 107.95 109.09 112.50 145.45 100.00 137.50 181.82 145.45 89 103.37 107.87 104.49 107.87 105.62 107.87 107.87 107.87 112.36 143.82 100.00 137.08 179.78 143.82 90 103.33 106.67 104.44 106.67 105.56 106.67 107.78 142.22 112.22 142.22 100.00 136.67 177.78 142.22 91 103.30 105.49 104.40 105.49 105.49 105.49 107.69 140.66 112.09 140.66 100.00 136.26 175.82 140.66 92 103.26 104.35 104.35 104.35 105.43 139.13 107.61 139.13 111.96 139.13 100.00 135.87 173.91 139.13 93 103.23 103.23 104.30 137.63 105.38 137.63 107.53 137.63 111.83 137.63 100.00 135.48 172.04 137.63 94 103.19 136.17 104.26 136.17 105.32 136.17 107.45 136.17 111.70 136.17 100.00 135.11 170.21 136.17 95 103.16 134.74 104.21 134.74 105.26 134.74 107.37 134.74 111.58 134.74 100.00 134.74 168.42 134.74 96 103.12 133.33 104.17 133.33 105.21 133.33 107.29 133.33 111.46 133.33 100.00 134.38 166.67 166.67 97 103.09 131.96 104.12 131.96 105.15 131.96 107.22 131.96 111.34 131.96 100.00 134.02 164.95 164.95 98 103.06 130.61 104.08 130.61 105.10 130.61 107.14 130.61 111.22 130.61 100.00 133.67 163.27 163.27 99 103.03 129.29 104.04 129.29 105.05 129.29 107.07 129.29 111.11 129.29 100.00 133.33 161.62 161.62 100 103.00 128.00 104.00 128.00 105.00 128.00 107.00 128.00 111.00 128.00 100.00 133.00 160.00 160.00 101 102.97 126.73 103.96 126.73 104.95 126.73 106.93 126.73 110.89 126.73 100.00 132.67 158.42 158.42 102 102.94 125.49 103.92 125.49 104.90 125.49 106.86 125.49 110.78 125.49 100.00 132.35 156.86 156.86 103 102.91 124.27 103.88 124.27 104.85 124.27 106.80 124.27 110.68 124.27 100.00 132.04 155.34 155.34 104 102.88 123.08 103.85 123.08 104.81 123.08 106.73 123.08 110.58 123.08 100.00 131.73 153.85 153.85 105 102.86 121.90 103.81 121.90 104.76 121.90 106.67 121.90 110.48 121.90 100.00 131.43 152.38 152.38 106 102.83 120.75 103.77 120.75 104.72 120.75 106.60 120.75 110.38 120.75 100.00 131.13 150.94 150.94 107 102.80 119.63 103.74 119.63 104.67 119.63 106.54 119.63 110.28 119.63 100.00 130.84 149.53 149.53 108 102.78 118.52 103.70 118.52 104.63 118.52 106.48 118.52 110.19 118.52 100.00 130.56 148.15 148.15 109 102.75 117.43 103.67 117.43 104.59 117.43 106.42 117.43 110.09 117.43 100.00 130.28 146.79 146.79 110 102.73 116.36 103.64 116.36 104.55 116.36 106.36 116.36 110.00 116.36 100.00 130.00 145.45 145.45 111 102.70 115.32 103.60 115.32 104.50 115.32 106.31 115.32 109.91 115.32 100.00 129.73 144.14 144.14 112 102.68 114.29 103.57 114.29 104.46 114.29 106.25 114.29 109.82 114.29 100.00 129.46 142.86 142.86 113 102.65 113.27 103.54 113.27 104.42 113.27 106.19 113.27 109.73 113.27 100.00 129.20 141.59 141.59 114 102.63 112.28 103.51 112.28 104.39 112.28 106.14 112.28 109.65 112.28 100.00 128.95 140.35 140.35 115 102.61 111.30 103.48 111.30 104.35 111.30 106.09 111.30 109.57 111.30 100.00 128.70 139.13 139.13 116 102.59 110.34 103.45 110.34 104.31 110.34 106.03 110.34 109.48 110.34 100.00 128.45 137.93 137.93 117 102.56 109.40 103.42 109.40 104.27 109.40 105.98 109.40 109.40 109.40 100.00 128.21 136.75 136.75 118 102.54 108.47 103.39 108.47 104.24 108.47 105.93 108.47 109.32 162.71 100.00 127.97 135.59 135.59 119 102.52 107.56 103.36 107.56 104.20 107.56 105.88 107.56 109.24 161.34 100.00 127.73 134.45 134.45 120 102.50 106.67 103.33 106.67 104.17 106.67 105.83 106.67 109.17 160.00 100.00 127.50 133.33 133.33 121 102.48 105.79 103.31 105.79 104.13 105.79 105.79 105.79 109.09 158.68 100.00 127.27 132.23 132.23 122 102.46 104.92 103.28 104.92 104.10 104.92 105.74 157.38 109.02 157.38 100.00 127.05 131.15 131.15 123 102.44 104.07 103.25 104.07 104.07 104.07 105.69 156.10 108.94 156.10 100.00 126.83 130.08 130.08 124 102.42 103.23 103.23 103.23 104.03 154.84 105.65 154.84 108.87 154.84 100.00 126.61 129.03 129.03 125 102.40 102.40 103.20 153.60 104.00 153.60 105.60 153.60 108.80 153.60 100.00 126.40 128.00 128.00 126 102.38 152.38 103.17 152.38 103.97 152.38 105.56 152.38 108.73 152.38 100.00 126.19 126.98 126.98 127 102.36 151.18 103.15 151.18 103.94 151.18 105.51 151.18 108.66 151.18 100.00 125.98 125.98 125.98 128 102.34 150.00 103.12 150.00 103.91 150.00 105.47 150.00 108.59 150.00 100.00 125.78 225.00 175.00 129 102.33 148.84 103.10 148.84 103.88 148.84 105.43 148.84 108.53 148.84 100.00 125.58 223.26 173.64 130 102.31 147.69 103.08 147.69 103.85 147.69 105.38 147.69 108.46 147.69 100.00 125.38 221.54 172.31 131 102.29 146.56 103.05 146.56 103.82 146.56 105.34 146.56 108.40 146.56 100.00 125.19 219.85 170.99 132 102.27 145.45 103.03 145.45 103.79 145.45 105.30 145.45 108.33 145.45 100.00 125.00 218.18 169.70 133 102.26 144.36 103.01 144.36 103.76 144.36 105.26 144.36 108.27 144.36 100.00 124.81 216.54 168.42 134 102.24 143.28 102.99 143.28 103.73 143.28 105.22 143.28 108.21 143.28 100.00 124.63 214.93 167.16 135 102.22 142.22 102.96 142.22 103.70 142.22 105.19 142.22 108.15 142.22 100.00 124.44 213.33 165.93 136 102.21 141.18 102.94 141.18 103.68 141.18 105.15 141.18 108.09 141.18 100.00 124.26 211.76 164.71 137 102.19 140.15 102.92 140.15 103.65 140.15 105.11 140.15 108.03 140.15 100.00 124.09 210.22 163.50 138 102.17 139.13 102.90 139.13 103.62 139.13 105.07 139.13 107.97 139.13 100.00 123.91 208.70 162.32 139 102.16 138.13 102.88 138.13 103.60 138.13 105.04 138.13 107.91 138.13 100.00 123.74 207.19 161.15 140 102.14 137.14 102.86 137.14 103.57 137.14 105.00 137.14 107.86 137.14 100.00 123.57 205.71 160.00 141 102.13 136.17 102.84 136.17 103.55 136.17 104.96 136.17 107.80 136.17 100.00 123.40 204.26 158.87 142 102.11 135.21 102.82 135.21 103.52 135.21 104.93 135.21 107.75 135.21 100.00 123.24 202.82 157.75 143 102.10 134.27 102.80 134.27 103.50 134.27 104.90 134.27 107.69 134.27 100.00 123.08 201.40 156.64 144 102.08 133.33 102.78 133.33 103.47 133.33 104.86 133.33 107.64 133.33 100.00 122.92 200.00 155.56 145 102.07 132.41 102.76 132.41 103.45 132.41 104.83 132.41 107.59 132.41 100.00 122.76 198.62 154.48 146 102.05 131.51 102.74 131.51 103.42 131.51 104.79 131.51 107.53 131.51 100.00 122.60 197.26 153.42 147 102.04 130.61 102.72 130.61 103.40 130.61 104.76 130.61 107.48 130.61 100.00 122.45 195.92 152.38 148 102.03 129.73 102.70 129.73 103.38 129.73 104.73 129.73 107.43 129.73 100.00 122.30 194.59 151.35 149 102.01 128.86 102.68 128.86 103.36 128.86 104.70 128.86 107.38 128.86 100.00 122.15 193.29 150.34 150 102.00 128.00 102.67 128.00 103.33 128.00 104.67 128.00 107.33 128.00 100.00 122.00 192.00 149.33 151 101.99 127.15 102.65 127.15 103.31 127.15 104.64 127.15 107.28 127.15 100.00 121.85 190.73 148.34 152 101.97 126.32 102.63 126.32 103.29 126.32 104.61 126.32 107.24 126.32 100.00 121.71 189.47 147.37 153 101.96 125.49 102.61 125.49 103.27 125.49 104.58 125.49 107.19 125.49 100.00 121.57 188.24 146.41 154 101.95 124.68 102.60 124.68 103.25 124.68 104.55 124.68 107.14 124.68 100.00 121.43 187.01 145.45 155 101.94 123.87 102.58 123.87 103.23 123.87 104.52 123.87 107.10 123.87 100.00 121.29 185.81 144.52 156 101.92 123.08 102.56 123.08 103.21 123.08 104.49 123.08 107.05 123.08 100.00 121.15 184.62 143.59 157 101.91 122.29 102.55 122.29 103.18 122.29 104.46 122.29 107.01 122.29 100.00 121.02 183.44 142.68 158 101.90 121.52 102.53 121.52 103.16 121.52 104.43 121.52 106.96 121.52 100.00 120.89 182.28 141.77 159 101.89 120.75 102.52 120.75 103.14 120.75 104.40 120.75 106.92 120.75 100.00 120.75 181.13 140.88 160 101.88 120.00 102.50 120.00 103.12 120.00 104.38 120.00 106.88 120.00 100.00 120.62 180.00 140.00 161 101.86 119.25 102.48 119.25 103.11 119.25 104.35 119.25 106.83 119.25 100.00 120.50 178.88 139.13 162 101.85 118.52 102.47 118.52 103.09 118.52 104.32 118.52 106.79 118.52 100.00 120.37 177.78 138.27 163 101.84 117.79 102.45 117.79 103.07 117.79 104.29 117.79 106.75 117.79 100.00 120.25 176.69 137.42 164 101.83 117.07 102.44 117.07 103.05 117.07 104.27 117.07 106.71 117.07 100.00 120.12 175.61 136.59 165 101.82 116.36 102.42 116.36 103.03 116.36 104.24 116.36 106.67 116.36 100.00 120.00 174.55 135.76 166 101.81 115.66 102.41 115.66 103.01 115.66 104.22 115.66 106.63 115.66 100.00 119.88 173.49 134.94 167 101.80 114.97 102.40 114.97 102.99 114.97 104.19 114.97 106.59 114.97 100.00 119.76 172.46 134.13 168 101.79 114.29 102.38 114.29 102.98 114.29 104.17 114.29 106.55 114.29 100.00 119.64 171.43 133.33 169 101.78 113.61 102.37 113.61 102.96 113.61 104.14 113.61 106.51 113.61 100.00 119.53 170.41 132.54 170 101.76 112.94 102.35 112.94 102.94 112.94 104.12 112.94 106.47 112.94 100.00 119.41 169.41 131.76 171 101.75 112.28 102.34 112.28 102.92 112.28 104.09 112.28 106.43 112.28 100.00 119.30 168.42 130.99 172 101.74 111.63 102.33 111.63 102.91 111.63 104.07 111.63 106.40 111.63 100.00 119.19 167.44 130.23 173 101.73 110.98 102.31 110.98 102.89 110.98 104.05 110.98 106.36 110.98 100.00 119.08 166.47 129.48 174 101.72 110.34 102.30 110.34 102.87 110.34 104.02 110.34 106.32 110.34 100.00 118.97 165.52 128.74 175 101.71 109.71 102.29 109.71 102.86 109.71 104.00 109.71 106.29 109.71 100.00 118.86 164.57 128.00 176 101.70 109.09 102.27 109.09 102.84 109.09 103.98 109.09 106.25 109.09 100.00 118.75 163.64 127.27 177 101.69 108.47 102.26 108.47 102.82 108.47 103.95 108.47 106.21 108.47 100.00 118.64 162.71 126.55 178 101.69 107.87 102.25 107.87 102.81 107.87 103.93 107.87 106.18 107.87 100.00 118.54 161.80 125.84 179 101.68 107.26 102.23 107.26 102.79 107.26 103.91 107.26 106.15 107.26 100.00 118.44 160.89 125.14 180 101.67 106.67 102.22 106.67 102.78 106.67 103.89 106.67 106.11 106.67 100.00 118.33 160.00 124.44 181 101.66 106.08 102.21 106.08 102.76 106.08 103.87 106.08 106.08 106.08 100.00 118.23 159.12 123.76 182 101.65 105.49 102.20 105.49 102.75 105.49 103.85 105.49 106.04 140.66 100.00 118.13 158.24 123.08 183 101.64 104.92 102.19 104.92 102.73 104.92 103.83 104.92 106.01 139.89 100.00 118.03 157.38 122.40 184 101.63 104.35 102.17 104.35 102.72 104.35 103.80 104.35 105.98 139.13 100.00 117.93 156.52 121.74 185 101.62 103.78 102.16 103.78 102.70 103.78 103.78 103.78 105.95 138.38 100.00 117.84 155.68 121.08 186 101.61 103.23 102.15 103.23 102.69 103.23 103.76 137.63 105.91 137.63 100.00 117.74 154.84 120.43 187 101.60 102.67 102.14 102.67 102.67 102.67 103.74 136.90 105.88 136.90 100.00 117.65 154.01 119.79 188 101.60 102.13 102.13 102.13 102.66 136.17 103.72 136.17 105.85 136.17 100.00 117.55 153.19 119.15 189 101.59 101.59 102.12 135.45 102.65 135.45 103.70 135.45 105.82 135.45 100.00 117.46 152.38 118.52 190 101.58 134.74 102.11 134.74 102.63 134.74 103.68 134.74 105.79 134.74 100.00 117.37 151.58 117.89 191 101.57 134.03 102.09 134.03 102.62 134.03 103.66 134.03 105.76 134.03 100.00 117.28 150.79 117.28 192 101.56 133.33 102.08 133.33 102.60 133.33 103.65 133.33 105.73 133.33 100.00 117.19 150.00 150.00 193 101.55 132.64 102.07 132.64 102.59 132.64 103.63 132.64 105.70 132.64 100.00 117.10 149.22 149.22 194 101.55 131.96 102.06 131.96 102.58 131.96 103.61 131.96 105.67 131.96 100.00 117.01 148.45 148.45 195 101.54 131.28 102.05 131.28 102.56 131.28 103.59 131.28 105.64 131.28 100.00 116.92 147.69 147.69 196 101.53 130.61 102.04 130.61 102.55 130.61 103.57 130.61 105.61 130.61 100.00 116.84 146.94 146.94 197 101.52 129.95 102.03 129.95 102.54 129.95 103.55 129.95 105.58 129.95 100.00 116.75 146.19 146.19 198 101.52 129.29 102.02 129.29 102.53 129.29 103.54 129.29 105.56 129.29 100.00 116.67 145.45 145.45 199 101.51 128.64 102.01 128.64 102.51 128.64 103.52 128.64 105.53 128.64 100.00 116.58 144.72 144.72 200 101.50 128.00 102.00 128.00 102.50 128.00 103.50 128.00 105.50 128.00 100.00 116.50 144.00 144.00 201 101.49 127.36 101.99 127.36 102.49 127.36 103.48 127.36 105.47 127.36 100.00 116.42 143.28 143.28 202 101.49 126.73 101.98 126.73 102.48 126.73 103.47 126.73 105.45 126.73 100.00 116.34 142.57 142.57 203 101.48 126.11 101.97 126.11 102.46 126.11 103.45 126.11 105.42 126.11 100.00 116.26 141.87 141.87 204 101.47 125.49 101.96 125.49 102.45 125.49 103.43 125.49 105.39 125.49 100.00 116.18 141.18 141.18 205 101.46 124.88 101.95 124.88 102.44 124.88 103.41 124.88 105.37 124.88 100.00 116.10 140.49 140.49 206 101.46 124.27 101.94 124.27 102.43 124.27 103.40 124.27 105.34 124.27 100.00 116.02 139.81 139.81 207 101.45 123.67 101.93 123.67 102.42 123.67 103.38 123.67 105.31 123.67 100.00 115.94 139.13 139.13 208 101.44 123.08 101.92 123.08 102.40 123.08 103.37 123.08 105.29 123.08 100.00 115.87 138.46 138.46 209 101.44 122.49 101.91 122.49 102.39 122.49 103.35 122.49 105.26 122.49 100.00 115.79 137.80 137.80 210 101.43 121.90 101.90 121.90 102.38 121.90 103.33 121.90 105.24 121.90 100.00 115.71 137.14 137.14 211 101.42 121.33 101.90 121.33 102.37 121.33 103.32 121.33 105.21 121.33 100.00 115.64 136.49 136.49 212 101.42 120.75 101.89 120.75 102.36 120.75 103.30 120.75 105.19 120.75 100.00 115.57 135.85 135.85 213 101.41 120.19 101.88 120.19 102.35 120.19 103.29 120.19 105.16 120.19 100.00 115.49 135.21 135.21 214 101.40 119.63 101.87 119.63 102.34 119.63 103.27 119.63 105.14 119.63 100.00 115.42 134.58 134.58 215 101.40 119.07 101.86 119.07 102.33 119.07 103.26 119.07 105.12 119.07 100.00 115.35 133.95 133.95 216 101.39 118.52 101.85 118.52 102.31 118.52 103.24 118.52 105.09 118.52 100.00 115.28 133.33 133.33 217 101.38 117.97 101.84 117.97 102.30 117.97 103.23 117.97 105.07 117.97 100.00 115.21 132.72 132.72 218 101.38 117.43 101.83 117.43 102.29 117.43 103.21 117.43 105.05 117.43 100.00 115.14 132.11 132.11 219 101.37 116.89 101.83 116.89 102.28 116.89 103.20 116.89 105.02 116.89 100.00 115.07 131.51 131.51 220 101.36 116.36 101.82 116.36 102.27 116.36 103.18 116.36 105.00 116.36 100.00 115.00 130.91 130.91 221 101.36 115.84 101.81 115.84 102.26 115.84 103.17 115.84 104.98 115.84 100.00 114.93 130.32 130.32 222 101.35 115.32 101.80 115.32 102.25 115.32 103.15 115.32 104.95 115.32 100.00 114.86 129.73 129.73 223 101.35 114.80 101.79 114.80 102.24 114.80 103.14 114.80 104.93 114.80 100.00 114.80 129.15 129.15 224 101.34 114.29 101.79 114.29 102.23 114.29 103.12 114.29 104.91 114.29 100.00 114.73 128.57 128.57 225 101.33 113.78 101.78 113.78 102.22 113.78 103.11 113.78 104.89 113.78 100.00 114.67 128.00 128.00 226 101.33 113.27 101.77 113.27 102.21 113.27 103.10 113.27 104.87 113.27 100.00 114.60 127.43 127.43 227 101.32 112.78 101.76 112.78 102.20 112.78 103.08 112.78 104.85 112.78 100.00 114.54 126.87 126.87 228 101.32 112.28 101.75 112.28 102.19 112.28 103.07 112.28 104.82 112.28 100.00 114.47 126.32 126.32 229 101.31 111.79 101.75 111.79 102.18 111.79 103.06 111.79 104.80 111.79 100.00 114.41 125.76 125.76 230 101.30 111.30 101.74 111.30 102.17 111.30 103.04 111.30 104.78 111.30 100.00 114.35 125.22 125.22 231 101.30 110.82 101.73 110.82 102.16 110.82 103.03 110.82 104.76 110.82 100.00 114.29 124.68 124.68 232 101.29 110.34 101.72 110.34 102.16 110.34 103.02 110.34 104.74 110.34 100.00 114.22 124.14 124.14 233 101.29 109.87 101.72 109.87 102.15 109.87 103.00 109.87 104.72 109.87 100.00 114.16 123.61 123.61 234 101.28 109.40 101.71 109.40 102.14 109.40 102.99 109.40 104.70 109.40 100.00 114.10 123.08 123.08 235 101.28 108.94 101.70 108.94 102.13 108.94 102.98 108.94 104.68 108.94 100.00 114.04 122.55 122.55 236 101.27 108.47 101.69 108.47 102.12 108.47 102.97 108.47 104.66 108.47 100.00 113.98 122.03 122.03 237 101.27 108.02 101.69 108.02 102.11 108.02 102.95 108.02 104.64 108.02 100.00 113.92 121.52 121.52 238 101.26 107.56 101.68 107.56 102.10 107.56 102.94 107.56 104.62 107.56 100.00 113.87 121.01 121.01 239 101.26 107.11 101.67 107.11 102.09 107.11 102.93 107.11 104.60 107.11 100.00 113.81 120.50 120.50 240 101.25 106.67 101.67 106.67 102.08 106.67 102.92 106.67 104.58 106.67 100.00 113.75 120.00 120.00 241 101.24 106.22 101.66 106.22 102.07 106.22 102.90 106.22 104.56 106.22 100.00 113.69 119.50 119.50 242 101.24 105.79 101.65 105.79 102.07 105.79 102.89 105.79 104.55 105.79 100.00 113.64 119.01 119.01 243 101.23 105.35 101.65 105.35 102.06 105.35 102.88 105.35 104.53 105.35 100.00 113.58 118.52 118.52 244 101.23 104.92 101.64 104.92 102.05 104.92 102.87 104.92 104.51 104.92 100.00 113.52 118.03 118.03 245 101.22 104.49 101.63 104.49 102.04 104.49 102.86 104.49 104.49 104.49 100.00 113.47 117.55 117.55 246 101.22 104.07 101.63 104.07 102.03 104.07 102.85 104.07 104.47 156.10 100.00 113.41 117.07 117.07 247 101.21 103.64 101.62 103.64 102.02 103.64 102.83 103.64 104.45 155.47 100.00 113.36 116.60 116.60 248 101.21 103.23 101.61 103.23 102.02 103.23 102.82 103.23 104.44 154.84 100.00 113.31 116.13 116.13 249 101.20 102.81 101.61 102.81 102.01 102.81 102.81 102.81 104.42 154.22 100.00 113.25 115.66 115.66 250 101.20 102.40 101.60 102.40 102.00 102.40 102.80 153.60 104.40 153.60 100.00 113.20 115.20 115.20 251 101.20 101.99 101.59 101.99 101.99 101.99 102.79 152.99 104.38 152.99 100.00 113.15 114.74 114.74 252 101.19 101.59 101.59 101.59 101.98 152.38 102.78 152.38 104.37 152.38 100.00 113.10 114.29 114.29 253 101.19 101.19 101.58 151.78 101.98 151.78 102.77 151.78 104.35 151.78 100.00 113.04 113.83 113.83 254 101.18 151.18 101.57 151.18 101.97 151.18 102.76 151.18 104.33 151.18 100.00 112.99 113.39 113.39 255 101.18 150.59 101.57 150.59 101.96 150.59 102.75 150.59 104.31 150.59 100.00 112.94 112.94 112.94 256 101.56 150.00 101.95 150.00 102.34 150.00 103.12 150.00 104.69 150.00 100.00 112.89 212.50 162.50 257 101.56 149.42 101.95 149.42 102.33 149.42 103.11 149.42 104.67 149.42 100.00 112.84 211.67 161.87 258 101.55 148.84 101.94 148.84 102.33 148.84 103.10 148.84 104.65 148.84 100.00 112.79 210.85 161.24 259 101.54 148.26 101.93 148.26 102.32 148.26 103.09 148.26 104.63 148.26 100.00 112.74 210.04 160.62 ustr-1.0.4/perf/perf-sizes-calc.pl0000755000076400007640000000507710630111754015773 0ustar jamesjames#! /usr/bin/perl -w use strict; open IN, '<', shift || die " Format: $0 "; my %vals = (); my $cur_len = 0; while () { if (/^String: (\d+)/) { $cur_len = $1; $vals{$cur_len}->[8] = 0; # 32bit doesn't have them $vals{$cur_len}->[9] = 0; next; } if (/^\s+ Ss(\d) .* = \s (\d+.\d\d)%/x) { $vals{$cur_len}->[$1] = $2; next; } if (/^\s+ strdup .* = \s (\d+.\d\d)%/x) { $vals{$cur_len}->[10] = $1; next; } if (/^\s+ NM_Ss \s+ = .* = \s (\d+.\d\d)%/x) { $vals{$cur_len}->[11] = $1; next; } if (/^\s+ NM_Ss \s x2 \s+ = .* = \s (\d+.\d\d)%/x) { $vals{$cur_len}->[12] = $1; next; } if (/^\s+ NM_Ss \s xSs \s+ = .* = \s (\d+.\d\d)%/x) { $vals{$cur_len}->[13] = $1; next; } } print < $b } keys %vals) { my $i = $vals{$num}; printf("%u" . "\t%s" x 14 . "\n", $num, $i->[0], $i->[1], $i->[2], $i->[3], $i->[4], $i->[5], $i->[6], $i->[7], $i->[8], $i->[9], $i->[10], $i->[11], $i->[12], $i->[13]); } ustr-1.0.4/ustr-srch-code.h0000644000076400007640000002715010675034427014531 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_SRCH_H #error " Include ustr-srch.h before this file." #endif #ifndef USTR_CONF_HAVE_MEMRCHR /* GNU extension */ #ifdef __GLIBC__ #define USTR_CONF_HAVE_MEMRCHR 1 #else #define USTR_CONF_HAVE_MEMRCHR 0 #endif #endif USTR_CONF_I_PROTO size_t ustr_srch_chr_fwd(const struct Ustr *s1, size_t off, char val) { const char *beg = ustr_cstr(s1); const char *ptr; size_t len = ustr_len(s1); const char *tmp; USTR_ASSERT(ustr_assert_valid(s1)); USTR_ASSERT_RET(off <= len, 0); ptr = beg + off; len -= off; if (!(tmp = memchr(ptr, val, len))) return (0); len = tmp - beg; return (len + 1); } #if USTR_CONF_HAVE_MEMRCHR /* GNU extension */ USTR_CONF_I_PROTO size_t ustr_srch_chr_rev(const struct Ustr *s1, size_t off, char val) { const char *ptr = ustr_cstr(s1); size_t len = ustr_len(s1); const char *tmp; USTR_ASSERT(ustr_assert_valid(s1)); USTR_ASSERT_RET(off <= len, 0); len -= off; if (!(tmp = memrchr(ptr, val, len))) return (0); len = tmp - ptr; return (len + 1); } #else USTR_CONF_I_PROTO size_t ustr_srch_chr_rev(const struct Ustr *s1, size_t off, char val) { /* slow... */ const char *ptr = ustr_cstr(s1); size_t len = ustr_len(s1); const char *tmp = ptr; const char *prev = 0; USTR_ASSERT(ustr_assert_valid(s1)); USTR_ASSERT_RET(off <= len, 0); len -= off; while ((tmp = memchr(tmp, val, len - (tmp - ptr)))) { prev = tmp; ++tmp; } if (!prev) return (0); len = prev - ptr; return (len + 1); } #endif #if ! USTR_CONF_HAVE_MEMMEM USTR_CONF_i_PROTO void *ustr__sys_memmem(const void *hs, size_t hslen, const void *nd, size_t ndlen) { const char *ptr = hs; if (ndlen == 0) return ((void *)hs); while (hslen >= ndlen) { if (!memcmp(ptr, nd, ndlen)) return ((void *)ptr); --hslen; ++ptr; } return (0); } #endif USTR_CONF_I_PROTO size_t ustr_srch_buf_fwd(const struct Ustr *s1, size_t off, const void *val, size_t vlen) { const char *beg = ustr_cstr(s1); const char *ptr; size_t len = ustr_len(s1); char *tmp = 0; USTR_ASSERT(ustr_assert_valid(s1)); if (vlen == 1) return (ustr_srch_chr_fwd(s1, off, ((const char *)val)[0])); USTR_ASSERT_RET(off <= len, 0); if (vlen == 0) return (len ? (off + 1) : 0); ptr = beg + off; len -= off; if (!(tmp = USTR__SYS_MEMMEM(ptr, len, val, vlen))) return (0); len = tmp - beg; return (len + 1); } USTR_CONF_I_PROTO size_t ustr_srch_buf_rev(const struct Ustr *s1, size_t off, const void *val, size_t vlen) { const char *ptr = ustr_cstr(s1); size_t len = ustr_len(s1); const char *prev = 0; const char *tmp = 0; USTR_ASSERT(ustr_assert_valid(s1)); if (vlen == 1) return (ustr_srch_chr_rev(s1, off, ((const char *)val)[0])); USTR_ASSERT_RET(off <= len, 0); len -= off; if (vlen == 0) return (len); tmp = ptr; while (((len - (tmp - ptr)) >= vlen) && (tmp = USTR__SYS_MEMMEM(tmp, len - (tmp - ptr), val, vlen))) { prev = tmp; ++tmp; } if (!prev) return (0); len = prev - ptr; return (len + 1); } USTR_CONF_I_PROTO size_t ustr_srch_subustr_fwd(const struct Ustr *s1, size_t off, const struct Ustr *s2, size_t pos, size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_srch_buf_fwd(s1, off, "", 0)); return (ustr_srch_buf_fwd(s1, off, ustr_cstr(s2) + --pos, len)); } USTR_CONF_I_PROTO size_t ustr_srch_subustr_rev(const struct Ustr *s1, size_t off, const struct Ustr *s2, size_t pos, size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_srch_buf_rev(s1, off, "", 0)); return (ustr_srch_buf_rev(s1, off, ustr_cstr(s2) + --pos, len)); } USTR_CONF_i_PROTO void *ustr__memrepchr(const void *hs, size_t hslen, char nd, size_t ndlen) { const char *ptr = hs; USTR_ASSERT(ndlen); /* dealt with by callers */ while (hslen >= ndlen) { const char *tmp = memchr(ptr, nd, hslen); size_t len = ndlen; if (!tmp) break; if (ndlen > (hslen - (tmp - ptr))) break; tmp += len; while (len > 0) { --tmp; if (*tmp != nd) break; --len; } if (!len) return ((void *)tmp); hslen -= (tmp - ptr); ptr = tmp; } return (0); } USTR_CONF_I_PROTO size_t ustr_srch_rep_chr_fwd(const struct Ustr *s1,size_t off, char val, size_t vlen) { const char *beg = ustr_cstr(s1); const char *ptr; size_t len = ustr_len(s1); char *tmp = 0; USTR_ASSERT(ustr_assert_valid(s1)); if (vlen == 1) return (ustr_srch_chr_fwd(s1, off, val)); USTR_ASSERT_RET(off <= len, 0); if (vlen == 0) return (len ? (off + 1) : 0); ptr = beg + off; len -= off; if (!(tmp = ustr__memrepchr(ptr, len, val, vlen))) return (0); len = tmp - beg; return (len + 1); } USTR_CONF_I_PROTO size_t ustr_srch_rep_chr_rev(const struct Ustr *s1,size_t off, char val, size_t vlen) { const char *ptr = ustr_cstr(s1); size_t len = ustr_len(s1); const char *prev = 0; const char *tmp = 0; USTR_ASSERT(ustr_assert_valid(s1)); if (vlen == 1) return (ustr_srch_chr_rev(s1, off, val)); USTR_ASSERT_RET(off <= len, 0); len -= off; if (vlen == 0) return (len); tmp = ptr; while (((len - (tmp - ptr)) >= vlen) && (tmp = ustr__memrepchr(tmp, len - (tmp - ptr), val, vlen))) { prev = tmp; ++tmp; } if (!prev) return (0); len = prev - ptr; return (len + 1); } /* ignore case */ USTR_CONF_i_PROTO void *ustr__memcasechr(const void *hs, const char nd, size_t len) { const unsigned char *s1 = hs; unsigned char c2 = nd; if ((c2 >= 0x61) && (c2 <= 0x7a)) c2 ^= 0x20; while (len) { unsigned char c1 = *s1; if ((c1 >= 0x61) && (c1 <= 0x7a)) c1 ^= 0x20; if (c1 == c2) return ((void *)s1); --len; ++s1; } return (0); } USTR_CONF_i_PROTO void *ustr__memcasemem(const void *hs,size_t hslen, const void *nd,size_t ndlen) { const char *ptr = hs; USTR_ASSERT(ndlen); /* dealt with by callers */ while (hslen >= ndlen) { if (!ustr__memcasecmp(ptr, nd, ndlen)) return ((void *)ptr); --hslen; ++ptr; } return (0); } USTR_CONF_i_PROTO void *ustr__memcaserepchr(const void *hs, size_t hslen, char nd, size_t ndlen) { const unsigned char *s1 = hs; unsigned char c2 = nd; USTR_ASSERT(ndlen); /* dealt with by callers */ if ((c2 >= 0x61) && (c2 <= 0x7a)) c2 ^= 0x20; while (hslen >= ndlen) { const unsigned char *tmp = ustr__memcasechr(s1, nd, hslen); size_t len = ndlen; if (!tmp) break; if (ndlen > (hslen - (tmp - s1))) break; tmp += len; while (len > 0) { unsigned char c1 = *--tmp; if ((c1 >= 0x61) && (c1 <= 0x7a)) c1 ^= 0x20; if (c1 != c2) break; --len; } if (!len) return ((void *)tmp); hslen -= (tmp - s1); s1 = tmp; } return (0); } USTR_CONF_I_PROTO size_t ustr_srch_case_chr_fwd(const struct Ustr *s1, size_t off, char val) { const char *beg = ustr_cstr(s1); const char *ptr; size_t len = ustr_len(s1); const char *tmp; USTR_ASSERT(ustr_assert_valid(s1)); USTR_ASSERT_RET(off <= len, 0); ptr = beg + off; len -= off; if (!(tmp = ustr__memcasechr(ptr, val, len))) return (0); len = tmp - beg; return (len + 1); } USTR_CONF_I_PROTO size_t ustr_srch_case_chr_rev(const struct Ustr *s1, size_t off, char val) { /* slow... */ const char *ptr = ustr_cstr(s1); size_t len = ustr_len(s1); const char *tmp = ptr; const char *prev = 0; USTR_ASSERT(ustr_assert_valid(s1)); USTR_ASSERT_RET(off <= len, 0); len -= off; while ((tmp = ustr__memcasechr(tmp, val, len - (tmp - ptr)))) { prev = tmp; ++tmp; } if (!prev) return (0); len = prev - ptr; return (len + 1); } USTR_CONF_I_PROTO size_t ustr_srch_case_buf_fwd(const struct Ustr *s1, size_t off, const void *val, size_t vlen) { const char *beg = ustr_cstr(s1); const char *ptr; size_t len = ustr_len(s1); char *tmp = 0; USTR_ASSERT(ustr_assert_valid(s1)); if (vlen == 1) return (ustr_srch_case_chr_fwd(s1, off, ((const char *)val)[0])); USTR_ASSERT_RET(off <= len, 0); if (vlen == 0) return (len ? (off + 1) : 0); ptr = beg + off; len -= off; if (!(tmp = ustr__memcasemem(ptr, len, val, vlen))) return (0); len = tmp - beg; return (len + 1); } USTR_CONF_I_PROTO size_t ustr_srch_case_buf_rev(const struct Ustr *s1, size_t off, const void *val, size_t vlen) { const char *ptr = ustr_cstr(s1); size_t len = ustr_len(s1); const char *prev = 0; const char *tmp = 0; USTR_ASSERT(ustr_assert_valid(s1)); if (vlen == 1) return (ustr_srch_case_chr_rev(s1, off, ((const char *)val)[0])); USTR_ASSERT_RET(off <= len, 0); len -= off; if (vlen == 0) return (len); tmp = ptr; while (((len - (tmp - ptr)) >= vlen) && (tmp = ustr__memcasemem(tmp, len - (tmp - ptr), val, vlen))) { prev = tmp; ++tmp; } if (!prev) return (0); len = prev - ptr; return (len + 1); } USTR_CONF_I_PROTO size_t ustr_srch_case_subustr_fwd(const struct Ustr *s1, size_t off, const struct Ustr *s2, size_t pos, size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_srch_case_buf_fwd(s1, off, "", 0)); return (ustr_srch_case_buf_fwd(s1, off, ustr_cstr(s2) + --pos, len)); } USTR_CONF_I_PROTO size_t ustr_srch_case_subustr_rev(const struct Ustr *s1, size_t off, const struct Ustr *s2, size_t pos, size_t len) { USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2)); if (!ustr_assert_valid_subustr(s2, pos, len)) return (ustr_srch_case_buf_rev(s1, off, "", 0)); return (ustr_srch_case_buf_rev(s1, off, ustr_cstr(s2) + --pos, len)); } USTR_CONF_I_PROTO size_t ustr_srch_case_rep_chr_fwd(const struct Ustr *s1, size_t off, char val, size_t vlen) { const char *beg = ustr_cstr(s1); const char *ptr; size_t len = ustr_len(s1); char *tmp = 0; USTR_ASSERT(ustr_assert_valid(s1)); if (vlen == 1) return (ustr_srch_case_chr_fwd(s1, off, val)); USTR_ASSERT_RET(off <= len, 0); if (vlen == 0) return (len ? (off + 1) : 0); ptr = beg + off; len -= off; if (!(tmp = ustr__memcaserepchr(ptr, len, val, vlen))) return (0); len = tmp - beg; return (len + 1); } USTR_CONF_I_PROTO size_t ustr_srch_case_rep_chr_rev(const struct Ustr *s1, size_t off, char val, size_t vlen) { const char *ptr = ustr_cstr(s1); size_t len = ustr_len(s1); const char *prev = 0; const char *tmp = 0; USTR_ASSERT(ustr_assert_valid(s1)); if (vlen == 1) return (ustr_srch_case_chr_rev(s1, off, val)); USTR_ASSERT_RET(off <= len, 0); len -= off; if (vlen == 0) return (len); tmp = ptr; while (((len - (tmp - ptr)) >= vlen) && (tmp = ustr__memcaserepchr(tmp, len - (tmp - ptr), val, vlen))) { prev = tmp; ++tmp; } if (!prev) return (0); len = prev - ptr; return (len + 1); } ustr-1.0.4/ustr-utf8-internal.h0000644000076400007640000000175510722117141015351 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_UTF8_INTERNAL_H #define USTR_UTF8_INTERNAL_H 1 #ifndef USTR_MAIN_H # error " You should have already included ustr-main.h, or just include ustr.h" #endif struct ustr__utf8_interval { unsigned int first; unsigned int last; }; #if ! USTR_CONF_HAVE_STDINT_H # define USTR__UTF8_WCHAR unsigned long #else # define USTR__UTF8_WCHAR uint_least32_t #endif USTR_CONF_e_PROTO int ustr__utf8_bisearch(USTR__UTF8_WCHAR,const struct ustr__utf8_interval*,int); USTR_CONF_e_PROTO USTR__SSIZE ustr__utf8_mk_wcwidth(USTR__UTF8_WCHAR) USTR__COMPILE_ATTR_WARN_UNUSED_RET(); USTR_CONF_e_PROTO USTR__UTF8_WCHAR ustr__utf8_check(const unsigned char **) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO const unsigned char *ustr__utf8_prev(const unsigned char *, size_t) USTR__COMPILE_ATTR_NONNULL_A(); USTR_CONF_e_PROTO const unsigned char *ustr__utf8_next(const unsigned char *) USTR__COMPILE_ATTR_NONNULL_A(); #endif ustr-1.0.4/ustr-cntl-code.h0000644000076400007640000003143310722060211014510 0ustar jamesjames/* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */ #ifndef USTR_MAIN_H #error " You should have already included ustr-main.h, or just include ustr.h." #endif /* not sure of the version */ #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && (__GNUC__ > 3) && \ USTR_CONF_COMPILE_USE_ATTRIBUTES # define USTR__COMPILE_ATTR_H() __attribute__((visibility("hidden"))) #else # define USTR__COMPILE_ATTR_H() #endif #include /* va_list for va_arg() functionality */ /* second set of defaults... *sigh* */ struct Ustr_opts USTR__COMPILE_ATTR_H() ustr__opts[1] = { {1, /* ref bytes */ {ustr__cntl_mc_setup_malloc, /* malloc be called first */ realloc, free}, /* Ustr_cntl_mem */ {vsnprintf, vsnprintf}, /* fmt */ USTR_FALSE, /* has_size */ USTR_FALSE, /* exact_bytes */ USTR_FALSE, /* scrub on malloc */ USTR_FALSE, /* scrub on free */ USTR_FALSE /* scrub on realloc */ }}; /* not namespaced because this must be in a C-file. */ #ifndef USE_MALLOC_CHECK #define USE_MALLOC_CHECK 1 #endif #define MALLOC_CHECK_API_M_SCRUB ustr__opts->mc_m_scrub #define MALLOC_CHECK_API_F_SCRUB ustr__opts->mc_f_scrub #define MALLOC_CHECK_API_R_SCRUB ustr__opts->mc_r_scrub #define MALLOC_CHECK_SCOPE_EXTERN 0 #include "malloc-check.h" MALLOC_CHECK_DECL(); typedef struct Ustr__cntl_mc_ptrs { const char *file; unsigned int line; const char *func; } Ustr__cntl_mc_ptrs; Ustr__cntl_mc_ptrs USTR__COMPILE_ATTR_H() *ustr__cntl_mc_ptr = 0; size_t USTR__COMPILE_ATTR_H() ustr__cntl_mc_num = 0; size_t USTR__COMPILE_ATTR_H() ustr__cntl_mc_sz = 0; #define USTR__STREQ(x, y) !strcmp(x, y) USTR_CONF_i_PROTO int ustr__cntl_mc_setup_env2bool(const char *key, int def) { const char *ptr = getenv(key); if (!ptr) return (!!def); if (USTR__STREQ(ptr, "1")) return (USTR_TRUE); if (USTR__STREQ(ptr, "on")) return (USTR_TRUE); if (USTR__STREQ(ptr, "yes")) return (USTR_TRUE); if (USTR__STREQ(ptr, "0")) return (USTR_FALSE); if (USTR__STREQ(ptr, "off")) return (USTR_FALSE); if (USTR__STREQ(ptr, "no")) return (USTR_FALSE); return (!!def); } USTR_CONF_i_PROTO void ustr__cntl_mc_setup_main(void) { int val = 0; if (!ustr__cntl_mc_setup_env2bool("USTR_CNTL_MC", USTR_CONF_USE_ASSERT)) { ustr__opts->umem.sys_malloc = malloc; ustr__opts->umem.sys_realloc = realloc; ustr__opts->umem.sys_free = free; return; } val = ustr__opts->mc_m_scrub; val = ustr__cntl_mc_setup_env2bool("USTR_CNTL_MC_M_SCRUB", val); ustr__opts->mc_m_scrub = val; val = ustr__opts->mc_f_scrub; val = ustr__cntl_mc_setup_env2bool("USTR_CNTL_MC_F_SCRUB", val); ustr__opts->mc_f_scrub = val; val = ustr__opts->mc_r_scrub; val = ustr__cntl_mc_setup_env2bool("USTR_CNTL_MC_R_SCRUB", val); ustr__opts->mc_r_scrub = val; USTR_CNTL_MALLOC_CHECK_BEG(USTR_TRUE); } USTR_CONF_i_PROTO void *ustr__cntl_mc_setup_malloc(size_t x) { /* again, it's not possible to call anything but malloc() or free(NULL). * So just doing setup here is fine. */ ustr__cntl_mc_setup_main(); return (ustr__opts->umem.sys_malloc(x)); } USTR_CONF_i_PROTO void *ustr__cntl_mc_malloc(size_t x) { struct Ustr__cntl_mc_ptrs *ptr = ustr__cntl_mc_ptr; size_t num = ustr__cntl_mc_num; return (malloc_check_malloc(x, ptr[num].file, ptr[num].line, ptr[num].func)); } USTR_CONF_i_PROTO void *ustr__cntl_mc_realloc(void *p, size_t x) { struct Ustr__cntl_mc_ptrs *ptr = ustr__cntl_mc_ptr; size_t num = ustr__cntl_mc_num; return (malloc_check_realloc(p,x, ptr[num].file,ptr[num].line,ptr[num].func)); } USTR_CONF_i_PROTO void ustr__cntl_mc_free(void *x) { struct Ustr__cntl_mc_ptrs *ptr = ustr__cntl_mc_ptr; size_t num = ustr__cntl_mc_num; malloc_check_free(x, ptr[num].file, ptr[num].line, ptr[num].func); } USTR_CONF_I_PROTO int ustr_cntl_opt(int option, ...) { int ret = USTR_FALSE; va_list ap; va_start(ap, option); switch (option) { case USTR_CNTL_OPT_GET_REF_BYTES: { size_t *val = va_arg(ap, size_t *); *val = ustr__opts->ref_bytes; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_SET_REF_BYTES: { size_t rbytes = va_arg(ap, size_t); USTR_ASSERT_RET((rbytes == 0) || (rbytes == 1) || (rbytes == 2) || (rbytes == 4) || (USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)), USTR_FALSE); ustr__opts->ref_bytes = rbytes; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_GET_HAS_SIZE: { int *val = va_arg(ap, int *); *val = ustr__opts->has_size; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_SET_HAS_SIZE: { int val = va_arg(ap, int); USTR_ASSERT_RET((val == !!val), USTR_FALSE); ustr__opts->has_size = val; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_GET_EXACT_BYTES: { int *val = va_arg(ap, int *); *val = ustr__opts->exact_bytes; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_SET_EXACT_BYTES: { int val = va_arg(ap, int); USTR_ASSERT_RET((val == !!val), USTR_FALSE); ustr__opts->exact_bytes = val; ret = USTR_TRUE; } break; /* call backs */ case USTR_CNTL_OPT_GET_MEM: { struct Ustr_cntl_mem *val = va_arg(ap, struct Ustr_cntl_mem *); val->sys_malloc = ustr__opts->umem.sys_malloc; val->sys_realloc = ustr__opts->umem.sys_realloc; val->sys_free = ustr__opts->umem.sys_free; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_SET_MEM: { const struct Ustr_cntl_mem *val = va_arg(ap, struct Ustr_cntl_mem *); ustr__opts->umem.sys_malloc = val->sys_malloc; ustr__opts->umem.sys_realloc = val->sys_realloc; ustr__opts->umem.sys_free = val->sys_free; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_GET_MC_M_SCRUB: { int *val = va_arg(ap, int *); *val = ustr__opts->mc_m_scrub; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_SET_MC_M_SCRUB: { int val = va_arg(ap, int); USTR_ASSERT_RET((val == !!val), USTR_FALSE); ustr__opts->mc_m_scrub = val; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_GET_MC_F_SCRUB: { int *val = va_arg(ap, int *); *val = ustr__opts->mc_f_scrub; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_SET_MC_F_SCRUB: { int val = va_arg(ap, int); USTR_ASSERT_RET((val == !!val), USTR_FALSE); ustr__opts->mc_f_scrub = val; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_GET_MC_R_SCRUB: { int *val = va_arg(ap, int *); *val = ustr__opts->mc_r_scrub; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_SET_MC_R_SCRUB: { int val = va_arg(ap, int); USTR_ASSERT_RET((val == !!val), USTR_FALSE); ustr__opts->mc_r_scrub = val; ret = USTR_TRUE; } break; case 666: { unsigned long valT = va_arg(ap, unsigned long); int enabled = !!ustr__cntl_mc_sz; USTR_ASSERT(ustr__cntl_mc_num <= ustr__cntl_mc_sz); if (valT == 0x0FFE) { ret = ustr__cntl_mc_num + enabled; break; } switch (valT) { case 0xF0F0: case 0xF0F1: case 0x0FF0: case 0x0FF1: case 0x0FF2: case 0x0FF3: case 0x0FF4: case 0x0FFF: ret = USTR_TRUE; } USTR_ASSERT(ret); if (!enabled && (valT == 0x0FFF)) { ret = USTR_FALSE; break; } if (!enabled && (valT != 0x0FF0)) break; /* pretend it worked */ switch (valT) { case 0xF0F0: { unsigned long valV = va_arg(ap, unsigned long); MALLOC_CHECK_FAIL_IN(valV); } break; case 0xF0F1: { unsigned long *valV = va_arg(ap, unsigned long *); *valV = MALLOC_CHECK_STORE.mem_fail_num; } break; case 0x0FF0: { const char *file = va_arg(ap, char *); unsigned int line = va_arg(ap, unsigned int); const char *func = va_arg(ap, char *); struct Ustr__cntl_mc_ptrs *tptr = ustr__cntl_mc_ptr; size_t tsz = 3; if (!enabled) tptr = MC_MALLOC(sizeof(Ustr__cntl_mc_ptrs) * tsz); else if (++ustr__cntl_mc_num >= ustr__cntl_mc_sz) { tsz = (ustr__cntl_mc_sz * 2) + 1; tptr = MC_REALLOC(tptr, sizeof(Ustr__cntl_mc_ptrs) * tsz); } if (!tptr) { if (enabled) --ustr__cntl_mc_num; ret = USTR_FALSE; break; } if (!enabled) { ustr__opts->umem.sys_malloc = ustr__cntl_mc_malloc; ustr__opts->umem.sys_realloc = ustr__cntl_mc_realloc; ustr__opts->umem.sys_free = ustr__cntl_mc_free; } ustr__cntl_mc_ptr = tptr; ustr__cntl_mc_sz = tsz; ustr__cntl_mc_ptr[ustr__cntl_mc_num].file = file; ustr__cntl_mc_ptr[ustr__cntl_mc_num].line = line; ustr__cntl_mc_ptr[ustr__cntl_mc_num].func = func; } break; case 0x0FF1: { struct Ustr__cntl_mc_ptrs *ptr = ustr__cntl_mc_ptr; size_t num = ustr__cntl_mc_num; void *valP = va_arg(ap, void *); malloc_check_mem(valP, ptr[num].file, ptr[num].line, ptr[num].func); } break; case 0x0FF2: { struct Ustr__cntl_mc_ptrs *ptr = ustr__cntl_mc_ptr; size_t num = ustr__cntl_mc_num; void *valP = va_arg(ap, void *); size_t valV = va_arg(ap, size_t); malloc_check_mem_sz(valP, valV, ptr[num].file, ptr[num].line, ptr[num].func); } break; case 0x0FF3: { struct Ustr__cntl_mc_ptrs *ptr = ustr__cntl_mc_ptr; size_t num = ustr__cntl_mc_num; void *valP = va_arg(ap, void *); size_t valV = va_arg(ap, size_t); malloc_check_mem_minsz(valP, valV, ptr[num].file, ptr[num].line, ptr[num].func); } break; case 0x0FF4: { /* needed for realloc() down doesn't fail */ struct Ustr__cntl_mc_ptrs *ptr_mc = ustr__cntl_mc_ptr; size_t num_mc = ustr__cntl_mc_num; void *ptr = va_arg(ap, void *); size_t nsz = va_arg(ap, size_t); unsigned int scan = malloc_check_mem(ptr, ptr_mc[num_mc].file, ptr_mc[num_mc].line, ptr_mc[num_mc].func); MALLOC_CHECK_STORE.mem_vals[scan].sz = nsz; } break; case 0x0FFF: { const char *file = va_arg(ap, char *); unsigned int line = va_arg(ap, unsigned int); const char *func = va_arg(ap, char *); if (ustr__cntl_mc_num) { USTR_ASSERT(!strcmp(file, ustr__cntl_mc_ptr[ustr__cntl_mc_num].file)); USTR_ASSERT(line); /* can't say much about this */ USTR_ASSERT(!strcmp(func, ustr__cntl_mc_ptr[ustr__cntl_mc_num].func)); --ustr__cntl_mc_num; break; } MC_FREE(ustr__cntl_mc_ptr); ustr__cntl_mc_num = 0; ustr__cntl_mc_sz = 0; ustr__cntl_mc_ptr = 0; /* it's bad otherwise */ malloc_check_empty(file, line, func); ustr__opts->umem.sys_malloc = malloc; ustr__opts->umem.sys_realloc = realloc; ustr__opts->umem.sys_free = free; MALLOC_CHECK_STORE.mem_num = 0; MALLOC_CHECK_STORE.mem_fail_num = 0; } break; } } break; case USTR_CNTL_OPT_GET_FMT: { struct Ustr_cntl_fmt *val = va_arg(ap, struct Ustr_cntl_fmt *); val->sys_vsnprintf_beg = ustr__opts->ufmt.sys_vsnprintf_beg; val->sys_vsnprintf_end = ustr__opts->ufmt.sys_vsnprintf_end; ret = USTR_TRUE; } break; case USTR_CNTL_OPT_SET_FMT: { const struct Ustr_cntl_fmt *val = va_arg(ap, struct Ustr_cntl_fmt *); ustr__opts->ufmt.sys_vsnprintf_beg = val->sys_vsnprintf_beg; ustr__opts->ufmt.sys_vsnprintf_end = val->sys_vsnprintf_end; ret = USTR_TRUE; } /* break; */ USTR_ASSERT_NO_SWITCH_DEF("Bad option passed to ustr_cntl_opt()"); } va_end(ap); return (ret); } ustr-1.0.4/ustr-io-dbg-code.c0000644000076400007640000000130210722116252014703 0ustar jamesjames#define USTR_CONF_INCLUDE_CODEONLY_HEADERS 0 #define USTR_CONF_INCLUDE_INTERNAL_HEADERS 1 #include "ustr-conf-debug.h" #define USTR_CONF_USE_DYNAMIC_CONF USTR_CONF_HAVE_DYNAMIC_CONF #define USTR_CONF_e_PROTO extern #define USTR_CONF_i_PROTO extern inline #define USTR_CONF_E_PROTO extern #define USTR_CONF_I_PROTO extern inline #define USTR_CONF_EI_PROTO extern #define USTR_CONF_II_PROTO extern inline #include "ustr-main.h" #undef USTR_CONF_INCLUDE_CODEONLY_HEADERS #define USTR_CONF_INCLUDE_CODEONLY_HEADERS 1 #undef USTR_CONF_i_PROTO #define USTR_CONF_i_PROTO #undef USTR_CONF_I_PROTO #define USTR_CONF_I_PROTO #undef USTR_CONF_II_PROTO #define USTR_CONF_II_PROTO inline #include "ustr-io.h"