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 size_t get_cmp_size(const ss_t *s1, const ss_t *s2) { if (!s1 || !s2) return 0; size_t s1_size = sd_get_size(s1), s2_size = sd_get_size(s2); return S_MAX(s1_size, s2_size); }
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); } }
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_resize_u(ss_t **s, const sbool_t cat, ss_t *src, const size_t u_chars, int fill_char) { ASSERT_RETURN_IF(!s, ss_void); if (!src) src = ss_void; const size_t at = (cat && *s) ? sd_get_size(*s) : 0, char_size = sc_wc_to_utf8_size(fill_char), current_u_chars = ss_len_u(src); RETURN_IF(u_chars == current_u_chars, ss_check(s)); /* same */ const sbool_t aliasing = *s == src; const size_t srcs = sd_get_size(src); if (current_u_chars < u_chars) { /* fill */ const size_t new_elems = u_chars - current_u_chars, at_inc = srcs + new_elems * char_size; SS_OVERFLOW_CHECK(s, at, at_inc); const size_t out_size = at + at_inc; if (ss_reserve(s, out_size) >= out_size) { if (!cat && !aliasing) /* copy */ ss_clear(s); if (!aliasing) { memcpy(get_str(*s) + at, get_str_r(src), srcs); inc_unicode_size(*s, current_u_chars); inc_size(*s, srcs); } size_t i = 0; for (; i < new_elems; i++) ss_cat_char(s, fill_char); } } else { /* cut */ const char *ps = get_str_r(src); size_t actual_unicode_count = 0; const size_t head_size = sc_unicode_count_to_utf8_size( ps, 0, srcs, u_chars, &actual_unicode_count); SS_OVERFLOW_CHECK(s, at, head_size); const size_t out_size = at + head_size; S_ASSERT(u_chars == actual_unicode_count); if (!aliasing) { /* copy or cat */ if (ss_reserve(s, out_size) >= out_size) { if (!cat && !aliasing) /* copy */ ss_clear(s); memcpy(get_str(*s) + at, ps, head_size); inc_unicode_size(*s, actual_unicode_count); inc_size(*s, head_size); } } else { /* cut */ set_size(*s, head_size); set_unicode_size(*s, actual_unicode_count); } } return *s; }
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); }
void scsi_sd_read_capacity(uint8_t lun, uint32_t *bcount, uint16_t *bsize) { const sdio_t *sdio = (const sdio_t*)scsi_lun[lun].info; *bcount = sd_get_size(*sdio); *bsize = 512u; }
static ss_t *aux_erase_u(ss_t **s, const sbool_t cat, const ss_t *src, const size_t char_off, const size_t n) { ASSERT_RETURN_IF(!s, ss_void); if (!src) src = ss_void; const char *ps = get_str_r(src); const size_t sso0 = *s ? sd_get_size(*s) : 0, ss0 = sd_get_size(src), head_size = sc_unicode_count_to_utf8_size(ps, 0, ss0, char_off, NULL); RETURN_IF(head_size >= ss0, ss_check(s)); /* BEHAVIOR */ size_t actual_n = 0; const size_t cus = *s ? get_unicode_size(*s) : 0, cut_size = sc_unicode_count_to_utf8_size(ps, head_size, ss0, n, &actual_n), tail_size = ss0 - cut_size - head_size; size_t out_size = ss0 - cut_size, prefix_usize = 0; if (*s == src) { /* aliasing: copy-only */ char *po = get_str(*s); memmove(po + head_size, ps + head_size + cut_size, tail_size); } else { /* copy/cat */ const size_t at = (cat && *s) ? sd_get_size(*s) : 0; out_size += at; if (ss_reserve(s, out_size) >= out_size) { char *po = get_str(*s); memcpy(po + at, get_str_r(src), head_size); memcpy(po + at + head_size, get_str_r(src) + head_size + cut_size, tail_size); set_size(*s, out_size); if (is_unicode_size_cached(*s) && (at == 0 || at == sso0)) { prefix_usize = get_unicode_size(*s); } else { set_unicode_size_cached(*s, S_FALSE); } } } if (cus > actual_n) set_unicode_size(*s, prefix_usize + cus - actual_n); else /* BEHAVIOR: unicode char count invalidation */ set_unicode_size_cached(*s, S_FALSE); set_size(*s, out_size); return ss_check(s); }
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; }
static ss_t *ss_cat_aliasing(ss_t **s, const ss_t *s0, const size_t s0_size, const size_t s0_unicode_size, const ss_t *src) { return src == s0 ? ss_cat_cn_raw(s, get_str(*s), 0, s0_size, s0_unicode_size) : ss_cat_cn_raw(s, get_str_r(src), 0, sd_get_size(src), get_unicode_size(src)); }
static ss_t *aux_ltrim(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); if (ss > 0) { const sbool_t aliasing = *s == src; const char *ps = get_str_r(src); size_t i = 0; for (; i < ss && isspace(ps[i]); i++); size_t at, cat_usize; if (cat) { if (*s) { at = sd_get_size(*s); cat_usize = get_unicode_size(*s); } else { at = cat_usize = 0; } } else { at = cat_usize = 0; } const size_t out_size = at + ss - i, src_usize = get_unicode_size(src); if (ss_reserve(s, out_size) >= out_size) { char *pt = get_str(*s); if (!aliasing) /* copy or cat: shift data */ memcpy(pt + at, ps + i, ss - i); else if (i > 0) /* copy: shift data */ memmove(pt, ps + i, ss - i); set_size(*s, at + ss - i); set_unicode_size(*s, cat_usize + src_usize - i); } } else { if (cat) ss_check(s); else ss_clear(s); } return *s; }
size_t ss_len_u(ss_t *s) { S_ASSERT(s); if (!s) return 0; if (is_unicode_size_cached(s)) return get_unicode_size(s); /* Not cached, so cache it: */ const char *p = get_str_r(s); const size_t ss = sd_get_size(s), cached_uc_size = sc_utf8_count_chars(p, ss); set_unicode_size_cached(s, S_TRUE); set_unicode_size(s, cached_uc_size); return cached_uc_size; }
static void ss_reconfig(ss_t *s, size_t new_alloc_size, const size_t new_mt_sz) { size_t size = sd_get_size(s), unicode_size = get_unicode_size(s); char *s_str = get_str(s); /* Compute offset on target location: */ struct SSTR_Small sm; struct SSTR_Full sf; const size_t s2_off = new_mt_sz == SS_METAINFO_SMALL? sm.str -(char *)&sm : sf.str - (char *)&sf; /* Convert string: */ memmove((char *)s + s2_off, s_str, size); s->is_full = sd_alloc_size_to_is_big(new_alloc_size, &ssf); set_size(s, size); set_alloc_size(s, new_alloc_size); set_unicode_size(s, unicode_size); }
/* BEHAVIOR: aliasing is supported, e.g. append(&a, a) */ static ss_t *ss_cat_cn_raw(ss_t **s, const char *src, const size_t src_off, const size_t src_size, const size_t src_usize) { ASSERT_RETURN_IF(!s, ss_void); if (src && src_size > 0) { const size_t off = *s ? sd_get_size(*s) : 0; if (ss_grow(s, src_size)) { memmove(get_str(*s) + off, src + src_off, src_size); inc_size(*s, src_size); if (is_unicode_size_cached(*s)) { if (src_usize > 0) inc_unicode_size(*s, src_usize); else set_unicode_size_cached(*s, S_FALSE); } } } return ss_check(s); }
ss_t *ss_cpy_substr(ss_t **s, const ss_t *src, const size_t 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); const size_t ss = sd_get_size(*s); ASSERT_RETURN_IF(off >= ss, ss_clear(s)); /* BEHAVIOR: empty */ const size_t copy_size = S_MIN(ss - off, n); memmove(ps, ps + off, copy_size); set_size(*s, copy_size); set_unicode_size_cached(*s, S_FALSE); /* BEHAVIOR: cache lost */ } else { if (*s) ss_clear(s); ss_cat_substr(s, src, off, n); } return ss_check(s); }
static ss_t *aux_toint(ss_t **s, const sbool_t cat, const sint_t num) { ASSERT_RETURN_IF(!s, ss_void); char btmp[128], *p = btmp + sizeof(btmp) - 1; sint_t n = num < 0 ? -num : num; do { *p-- = '0' + n % 10; n /= 10; } while (n); if (num < 0) *p-- = '-'; const size_t off = (size_t)((p - (char *)btmp) + 1), digits = sizeof(btmp) - off, at = (cat && *s) ? sd_get_size(*s) : 0; SS_OVERFLOW_CHECK(s, at, digits); const size_t out_size = at + digits; if (ss_reserve(s, out_size) >= out_size) { memcpy(get_str(*s) + at, btmp + off, digits); set_size(*s, out_size); inc_unicode_size(*s, digits); } return *s; }
scsi_cmdret_t scsi_sd_read10( SCSI_PARAMS ) { const sdio_t *sdio = (const sdio_t*)scsi_lun[lun].info; scsi_cdb10_t *cdb10 = (scsi_cdb10_t *)cmd; //uint8_t DPO = (cdb10->cdb_info >> 4) & 0x1; //uint8_t FUA = (cdb10->cdb_info >> 3) & 0x1; uint32_t lba = msbtohost32(cdb10->lba); uint32_t nblocks = msbtohost16(cdb10->length); uint32_t sdsize = sd_get_size(*sdio); sd_card_type_t sdtype = sd_get_type(*sdio); sd_error_t sdret; scsi_cmdret_t ret; uint32_t la = (sdtype != SDHC) ? lba * BLOCKSIZE : lba; sdret = SD_NO_ERROR; sd_transfer_ended = false; sd_set_transfer_handler(*sdio, sd_transfer_handler); if ((lba + nblocks - 1) >= sdsize) { log_error("SCSI Read(10), read beyond limit (limit 0x%08x, request 0x%08x / +%d)",sdsize,lba,nblocks); *status = SCSI_CHECK_CONDITION; return SCSI_CMD_DONE; } if (datamax < BLOCKSIZE) { log_error("SCSI Read(10), read buffer is smaller than a single sector (%d/%d bytes)",datalen,BLOCKSIZE); *status = SCSI_CHECK_CONDITION; return SCSI_CMD_ERROR; } sdret = sd_read_single_block(*sdio, la, data); if (cont == 0) { log_info("SCSI Read(10) type %d, lba 0x%08x, length %d",sdtype,lba,nblocks); } else { DBG("-%d-\n",cont); } if (sdret != SD_NO_ERROR) { log_error("SCSI Read Command Error on SD %d",sdret); *status = SCSI_CHECK_CONDITION; return SCSI_CMD_DONE; } while (!sd_transfer_ended) { ; } sdret = sd_get_status(*sdio); if (sdret != SD_NO_ERROR) { log_error("SCSI Read Error on SD (lba 0x%08x) ret %d",lba,sdret); *status = SCSI_CHECK_CONDITION; return SCSI_CMD_DONE; } switch (nblocks) { case 0: *status = SCSI_CHECK_CONDITION; ret = SCSI_CMD_ERROR; break; case 1: *datalen = BLOCKSIZE; *status = SCSI_GOOD; ret = SCSI_CMD_DONE; break; default: cdb10->lba = msbtohost32( lba + 1 ); cdb10->length = msbtohost16( nblocks - 1 ); *datalen = BLOCKSIZE; *status = SCSI_GOOD; ret = SCSI_CMD_PARTIAL; break; } return ret; }
static void inc_size(ss_t *s, const size_t inc_size) { set_size(s, sd_get_size(s) + inc_size); }
static ss_t *aux_toXcase(ss_t **s, const sbool_t cat, const ss_t *src, sint32_t (*towX)(sint32_t)) { ASSERT_RETURN_IF(!s, ss_void); if (!src) src = ss_void; const size_t ss = sd_get_size(src), sso_max = *s ? ss_get_max_size(*s) : 0; const char *ps = get_str_r(src); ss_t *out = NULL; const sbool_t aliasing = *s == src; unsigned char is_cached_usize = 0; ssize_t extra = sc_utf8_calc_case_extra_size(ps, 0, ss, towX); size_t cached_usize = 0, at; /* If possible, keep Unicode size cached: */ if (*s) { if (is_unicode_size_cached(*s) && is_unicode_size_cached(src)) { is_cached_usize = 1; cached_usize = get_unicode_size(src) + get_unicode_size(*s); } at = cat ? sd_get_size(*s) : 0; } else { /* copy */ if (is_unicode_size_cached(src)) { is_cached_usize = 1; cached_usize = get_unicode_size(src); } at = 0; } /* Check if it is necessary to allocate more memory: */ size_t sso_req = extra < 0 ? (at + ss - (size_t)(-extra)) : (at + ss + (size_t)extra); char *po0; if (!*s || sso_req > sso_max || (aliasing && extra > 0)) { if (*s && (*s)->ext_buffer) { /* BEHAVIOR */ S_ERROR("not enough memory: strings stored in the " "stored in fixed-length buffer can not be " "resized."); sd_set_alloc_errors(*s); return ss_check(s); } out = ss_alloc(sso_req); if (!out) { /* BEHAVIOR */ S_ERROR("not enough memory: can not " "change character case"); if (*s) sd_set_alloc_errors(*s); return ss_check(s); } char *pout = get_str(out); if (at > 0) /* cat */ memcpy(pout, get_str(*s), at); po0 = pout + at; } else { po0 = get_str(*s) + at; } /* Case conversion loop: */ size_t i = 0; int c = 0; char *po = po0, u8[SSU8_MAX_SIZE]; for (; i < ss;) { #ifdef S_ENABLE_UTF8_7BIT_PARALLEL_CASE_OPTIMIZATIONS unsigned *pou = (unsigned *)po; const size_t i2 = sc_parallel_toX(ps, i, ss, pou, towX); if (i != i2) { po += (i2 - i); i = i2; if (i >= ss) break; } #endif const size_t csize = ss_utf8_to_wc(ps, i, ss, &c, *s); const int c2 = towX(c); size_t csize2; if (c2 == c) { csize2 = csize; if (!aliasing) memcpy(po, ps + i, csize2); } else { csize2 = sc_wc_to_utf8(c2, u8, 0, SSU8_MAX_SIZE); memcpy(po, u8, csize2); } i += csize; po += csize2; } if (out) { /* Case of using a secondary string was required */ ss_t *s_bck = *s; *s = out; ss_free(&s_bck); } if (*s) { set_size(*s, sso_req); set_unicode_size_cached(*s, is_cached_usize); set_unicode_size(*s, cached_usize); } return ss_check(s); }
static ss_t *aux_replace(ss_t **s, const sbool_t cat, const ss_t *src, const size_t off, const ss_t *s1, const ss_t *s2) { ASSERT_RETURN_IF(!s, ss_void); if (!s1) s1 = ss_void; if (!s2) s2 = ss_void; if (!src) src = ss_void; const size_t at = (cat && *s) ? sd_get_size(*s) : 0; const char *p0 = get_str_r(src), *p2 = get_str_r(s2); const size_t l1 = sd_get_size(s1), l2 = sd_get_size(s2); size_t i = off, l = sd_get_size(src); ss_t *out = NULL; ssize_t size_delta = l2 > l1 ? (ssize_t)(l2 - l1) : -(ssize_t)(l1 - l2); sbool_t aliasing = S_FALSE; size_t out_size = at + l; char *o, *o0; if (l2 >= l1) { /* resize required */ size_t nfound = 0; /* scan required size */ for (;; i+= l1, nfound++) if ((i = ss_find(src, i, s1)) == S_NPOS) break; if (nfound == 0) /* 0 occurrences: return */ return ss_check(s); if (size_delta >= 0) out_size += (size_t)size_delta * nfound; else out_size -= (size_t)(-size_delta) * nfound; /* allocate output string */ out = ss_alloc(out_size); if (!out) { S_ERROR("not enough memory"); sd_set_alloc_errors(*s); return ss_check(s); } o0 = o = get_str(out); /* copy prefix data (cat) */ if (at > 0) memcpy(o, get_str_r(*s), at); } else { if (s && *s && *s == src) { aliasing = S_TRUE; } else { if (ss_reserve(s, out_size) < out_size) /* BEHAVIOR */ return ss_check(s); } o0 = o = get_str(*s); } typedef void (*memcpy_t)(void *, const void *, size_t); memcpy_t f_cpy; if (aliasing) { f_cpy = (memcpy_t)memmove; } else { f_cpy = (memcpy_t)memcpy; o += at; if (off > 0) /* copy not affected data */ memcpy(o, p0, off); } o += off; size_t i_next = s1 == s2? S_NPOS : /* no replace */ ss_find(src, i + off, s1); for (i = off;;) { /* before match copy: */ if (i_next == S_NPOS) { f_cpy(o, p0 + i, l - i); o += (l - i); break; } f_cpy(o, p0 + i, i_next - i); o += (i_next - i); /* replace: */ f_cpy(o, p2, l2); o += l2; i = i_next + l1; /* prepare next search: */ i_next = ss_find(src, i, s1); } if (out) { ss_t *s_bck = *s; *s = out; ss_free(&s_bck); } set_size(*s, (size_t)(o - o0)); return *s; }