ss_t *ss_cpy_substr_u(ss_t **s, const ss_t *src, const size_t char_off, const size_t n) { ASSERT_RETURN_IF(!s, ss_void); ASSERT_RETURN_IF(!src || !n, ss_clear(s)); /* BEHAVIOR: empty */ if (*s == src) { /* aliasing */ char *ps = get_str(*s); size_t actual_unicode_count = 0; const size_t ss = sd_get_size(*s); const size_t off = sc_unicode_count_to_utf8_size(ps, 0, ss, char_off, &actual_unicode_count); const size_t n_size = sc_unicode_count_to_utf8_size(ps, off, ss, n, &actual_unicode_count); ASSERT_RETURN_IF(off >= ss, ss_clear(s)); /* BEHAVIOR: empty */ const size_t copy_size = S_MIN(ss - off, n_size); memmove(ps, ps + off, copy_size); set_size(*s, copy_size); if (n == actual_unicode_count) { set_unicode_size_cached(*s, S_TRUE); set_unicode_size(*s, n); } else { /* BEHAVIOR: cache lost */ set_unicode_size_cached(*s, S_FALSE); } } else { if (*s) ss_clear(s); ss_cat_substr_u(s, src, char_off, n); } return ss_check(s); }
sdm_t *sdm_alloc(const enum eSM_Type t, const size_t nsubmaps, const size_t initial_reserve) { ASSERT_RETURN_IF(nsubmaps < 1, NULL); size_t alloc_size = sizeof(sdm_t) + sizeof(sm_t *) * (nsubmaps - 1); sdm_t *dm = (sdm_t *)__sd_malloc(alloc_size); ASSERT_RETURN_IF(!dm, NULL); memset(dm, 0, alloc_size); size_t i = 0, nelems = (initial_reserve / nsubmaps) + 1; for (; i < nsubmaps; i++) { if (!(dm->maps[i] = sm_alloc(t, nelems))) break; /* Allocation error */ } if (i != nsubmaps) { /* Handle allocation error */ for (i = 0; i < nsubmaps; i++) { if (dm->maps[i]) free(dm->maps[i]); else break; } free(dm); dm = NULL; } else { /* Set routing defaults */ sdm_set_routing(dm, NULL, NULL); dm->nmaps = nsubmaps; } return dm; }
ss_t *ss_cpy_cn(ss_t **s, const char *src, const size_t src_size) { ASSERT_RETURN_IF(!s, ss_void); ASSERT_RETURN_IF(!src || !src_size, ss_clear(s)); /* BEHAVIOR: empty */ if (*s) ss_clear(s); ss_cat_cn(s, src, src_size); return ss_check(s); }
ss_t *ss_cpy_sub(ss_t **s, const ss_t *src, const sv_t *offs, const size_t nth) { ASSERT_RETURN_IF(!s, ss_void); ASSERT_RETURN_IF((!src || !offs), ss_clear(s)); /* BEHAVIOR: empty */ const size_t elems = sv_size(offs) / 2; ASSERT_RETURN_IF(nth >= elems, ss_clear(s)); /* BEHAVIOR: empty */ const size_t off = (size_t)sv_u_at(offs, nth * 2); const size_t size = (size_t)sv_u_at(offs, nth * 2 + 1); return ss_cpy_substr(s, src, off, size); }
ss_t *ss_cpy_printf_va(ss_t **s, const size_t size, const char *fmt, va_list ap) { ASSERT_RETURN_IF(!s, ss_void); ASSERT_RETURN_IF((!size || !fmt) && ss_clear(s), *s); if (*s) { ss_reserve(s, size); ss_clear(s); } return ss_cat_printf_va(s, size, fmt, ap); }
ss_t *ss_cpy_printf(ss_t **s, const size_t size, const char *fmt, ...) { ASSERT_RETURN_IF(!s, ss_void); ASSERT_RETURN_IF((!size || !fmt) && ss_clear(s), *s); if (*s) { ss_reserve(s, size); ss_clear(s); } va_list ap; va_start(ap, fmt); ss_cat_printf_va(s, size, fmt, ap); va_end(ap); return *s; }
static ss_t *aux_rtrim(ss_t **s, const sbool_t cat, const ss_t *src) { ASSERT_RETURN_IF(!s, ss_void); if (!src) src = ss_void; const size_t ss = sd_get_size(src), at = (cat && *s) ? sd_get_size(*s) : 0; if (ss > 0) { const sbool_t aliasing = *s == src; const char *ps = get_str_r(src); size_t i = ss - 1; for (; i > 0 && isspace(ps[i]); i--); if (isspace(ps[i])) i--; const size_t nspaces = ss - i - 1, copy_size = ss - nspaces, out_size = at + copy_size, cat_usize = cat ? get_unicode_size(*s) : 0, src_usize = *s ? get_unicode_size(*s) : 0; if (ss_reserve(s, out_size) >= out_size) { char *pt = get_str(*s); if (!aliasing) memcpy(pt + at, ps, copy_size); set_size(*s, out_size); set_unicode_size(*s, cat_usize + src_usize - nspaces); } } else { if (cat) ss_check(s); else ss_clear(s); } return *s; }
static ss_t *aux_resize(ss_t **s, const sbool_t cat, const ss_t *src, const size_t n, char fill_byte) { ASSERT_RETURN_IF(!s, ss_void); if (!src) src = ss_void; const size_t src_size = sd_get_size(src), at = (cat && *s) ? sd_get_size(*s) : 0, out_size = at + n; /* BEHAVIOR: n overflow TODO */ const sbool_t aliasing = *s == src; if (src_size < n) { /* fill */ if (ss_reserve(s, out_size) >= out_size) { char *o = get_str(*s); if (!aliasing) { const char *p = get_str_r(src); memcpy(o + at, p, src_size); } memset(o + at + src_size, fill_byte, n - src_size); set_size(*s, out_size); } } else { /* else: cut (implicit) */ if (ss_reserve(s, out_size) >= out_size) { if (!aliasing) memcpy(get_str(*s) + at, get_str_r(src), n); set_size(*s, out_size); } } return *s; }
static ss_t *aux_erase(ss_t **s, const sbool_t cat, const ss_t *src, const size_t off, const size_t n) { ASSERT_RETURN_IF(!s, ss_void); if (!src) src = ss_void; const size_t ss0 = sd_get_size(src), at = (cat && *s) ? sd_get_size(*s) : 0; const sbool_t overflow = off + n > ss0; const size_t src_size = overflow ? ss0 - off : n, copy_size = ss0 - off - src_size; if (*s == src) { /* BEHAVIOR: aliasing: copy-only */ if (off + n >= ss0) { /* tail clean cut */ set_size(*s, off); } else { char *ps = get_str(*s); memmove(ps + off, ps + off + n, copy_size); set_size(*s, ss0 - n); } set_unicode_size_cached(*s, S_FALSE); } else { /* copy or cat */ const size_t out_size = at + off + copy_size; if (ss_reserve(s, out_size) >= out_size) { char *po = get_str(*s); memcpy(po + at, get_str_r(src), off); memcpy(po + at + off, get_str_r(src) + off + n, copy_size); set_size(*s, out_size); set_unicode_size_cached(*s, S_FALSE); } } return ss_check(s); }
static ss_t *aux_toenc(ss_t **s, const sbool_t cat, const ss_t *src, senc_f_t f) { ASSERT_RETURN_IF(!s, ss_void); if (!src) src = ss_void; const int aliasing = *s == src; const size_t in_size = sd_get_size(src), at = (cat && *s) ? sd_get_size(*s) : 0, out_size = at + f(NULL, in_size, NULL); if (ss_reserve(s, out_size) >= out_size) { const ss_t *src1 = aliasing ? *s : src; f((const unsigned char *)get_str_r(src1), in_size, (unsigned char *)get_str(*s) + at); if (at == 0) { set_unicode_size_cached(*s, S_TRUE); set_unicode_size(*s, in_size * 2); } else { /* cat */ if (is_unicode_size_cached(*s) && at == sd_get_size(*s)) set_unicode_size(*s, get_unicode_size(*s) + in_size * 2); else set_unicode_size_cached(*s, S_FALSE); } set_size(*s, out_size); } return ss_check(s); }
ss_t *ss_cat_aux(ss_t **s, const size_t nargs, const ss_t *s1, ...) { ASSERT_RETURN_IF(!s, ss_void); if (s1 && sd_get_size(s1) > 0) { va_list ap; size_t extra_size = sd_get_size(s1); const ss_t *s_next, *s0 = *s; const size_t ss0 = *s ? sd_get_size(s0) : 0, uss0 = s0 ? get_unicode_size(s0) : 0; va_start(ap, s1); size_t i = 1; for (; i < nargs; i++) { s_next = va_arg(ap, const ss_t *); if (s_next) extra_size += sd_get_size(s_next); } va_end(ap); if (ss_grow(s, extra_size)) { ss_cat_aliasing(s, s0, ss0, uss0, s1); if (nargs == 1) return *s; va_start(ap, s1); for (i = 1; i < nargs; i++) { s_next = va_arg(ap, const ss_t *); if (s_next) ss_cat_aliasing(s, s0, ss0, uss0, s_next); } va_end(ap); } }
sbool_t sm_s_count(const sm_t *m, const ss_t *k) { ASSERT_RETURN_IF(!m, S_FALSE); struct SMapSX n; n.k = k; return st_locate(m, (const stn_t *)&n) ? S_TRUE : S_FALSE; }
ss_t *ss_cpy_wn(ss_t **s, const wchar_t *src, const size_t src_size) { ASSERT_RETURN_IF(!s, ss_void); if (*s) ss_clear(s); return ss_cat_wn(s, src, src_size); }
sbool_t sm_u_count(const sm_t *m, const suint32_t k) { ASSERT_RETURN_IF(!m, S_FALSE); struct SMapuu n; n.k = k; return st_locate(m, (const stn_t *)&n) ? S_TRUE : S_FALSE; }
sbool_t sm_ip_insert(sm_t **m, const sint_t k, const void *v) { ASSERT_RETURN_IF(!m, S_FALSE); struct SMapIP n; n.x.k = k; n.v = v; return st_insert((st_t **)m, (const stn_t *)&n); }
size_t ss_len_left(const ss_t *s) { ASSERT_RETURN_IF(!s, 0); const size_t size = sd_get_size(s), max_size = ss_get_max_size(s); S_ASSERT(s && max_size > size); return (s && max_size > size) ? max_size - size : 0; }
sbool_t sm_is_insert(sm_t **m, const sint_t k, const ss_t *v) { ASSERT_RETURN_IF(!m, S_FALSE); struct SMapIS n; n.x.k = k; n.v = ss_dup(v); return st_insert((st_t **)m, (const stn_t *)&n); }
sint32_t sm_ii32_at(const sm_t *m, const sint32_t k) { ASSERT_RETURN_IF(!m, SINT32_MIN); struct SMapii n; n.k = k; const struct SMapii *nr = (const struct SMapii *)st_locate(m, (const stn_t *)&n); return nr ? nr->v : (sint32_t)m->f.iaux1; }
ss_t *ss_cpy_char(ss_t **s, const int c) { ASSERT_RETURN_IF(!s, ss_void); if (ss_reserve(s, SSU8_MAX_SIZE) >= SSU8_MAX_SIZE) { ss_clear(s); return ss_cat_char(s, c); } return *s; }
S_INLINE sbool_t sm_ii_insert_aux(sm_t **m, const sint_t k, const sint_t v, const st_rewrite_t rw_f) { ASSERT_RETURN_IF(!m, S_FALSE); struct SMapII n; n.x.k = k; n.v = v; return st_insert_rw((st_t **)m, (const stn_t *)&n, rw_f); }
const void *sm_sp_at(const sm_t *m, const ss_t *k) { ASSERT_RETURN_IF(!m, NULL); struct SMapSP n; n.x.k = (ss_t *)k; /* not going to be overwritten */ const struct SMapSP *nr = (const struct SMapSP *)st_locate(m, (const stn_t *)&n); return nr ? nr->v : NULL; }
suint32_t sm_uu32_at(const sm_t *m, const suint32_t k) { ASSERT_RETURN_IF(!m, 0); struct SMapuu n; n.k = k; const struct SMapuu *nr = (const struct SMapuu *)st_locate(m, (const stn_t *)&n); return nr ? nr->v : (suint32_t)m->f.iaux1; }
const ss_t *sm_ss_at(const sm_t *m, const ss_t *k) { ASSERT_RETURN_IF(!m, ss_empty()); struct SMapSS n; n.x.k = (ss_t *)k; /* not going to be overwritten */ const struct SMapSS *nr = (const struct SMapSS *)st_locate(m, (const stn_t *)&n); return nr ? nr->v : (ss_t *)m->f.paux1; }
sint_t sm_si_at(const sm_t *m, const ss_t *k) { ASSERT_RETURN_IF(!m, SINT_MIN); struct SMapSI n; n.x.k = (ss_t *)k; /* not going to be overwritten */ const struct SMapSI *nr = (const struct SMapSI *)st_locate(m, (const stn_t *)&n); return nr ? nr->v : m->f.iaux1; }
const void *sm_ip_at(const sm_t *m, const sint_t k) { ASSERT_RETURN_IF(!m, NULL); struct SMapIP n; n.x.k = k; const struct SMapIP *nr = (const struct SMapIP *)st_locate(m, (const stn_t *)&n); return nr ? nr->v : NULL; }
const ss_t *sm_is_at(const sm_t *m, const sint_t k) { ASSERT_RETURN_IF(!m, ss_empty()); struct SMapIS n; n.x.k = k; const struct SMapIS *nr = (const struct SMapIS *)st_locate(m, (const stn_t *)&n); return nr ? nr->v : (const ss_t *)m->f.paux1; }
sint_t sm_ii_at(const sm_t *m, const sint_t k) { ASSERT_RETURN_IF(!m, SINT_MIN); struct SMapII n; n.x.k = k; const struct SMapII *nr = (const struct SMapII *)st_locate(m, (const stn_t *)&n); return nr ? nr->v : m->f.iaux1; }
sbool_t sm_sp_insert(sm_t **m, const ss_t *k, const void *v) { ASSERT_RETURN_IF(!m, S_FALSE); struct SMapSP n; n.x.k = NULL; ss_cpy(&n.x.k, k); n.v = v; return st_insert((st_t **)m, (const stn_t *)&n); }
ss_t *ss_cpy(ss_t **s, const ss_t *src) { ASSERT_RETURN_IF(!s, ss_void); RETURN_IF(*s == src && ss_check(s), *s); /* aliasing, same string */ RETURN_IF(!src, ss_clear(s)); /* BEHAVIOR: empty */ if (*s) ss_clear(s); return ss_cat(s, src); }
S_INLINE sbool_t sm_si_insert_aux(sm_t **m, const ss_t *k, const sint_t v, const st_rewrite_t rw_f) { ASSERT_RETURN_IF(!m, S_FALSE); struct SMapSI n; n.x.k = NULL; ss_cpy(&n.x.k, k); n.v = v; return st_insert_rw((st_t **)m, (const stn_t *)&n, rw_f); }