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 ss_set_len(ss_t *s, const size_t new_len) { if (s) { const size_t max_size = ss_get_max_size(s); set_size(s, S_MIN(new_len, max_size)); set_unicode_size_cached(s, S_FALSE); /* BEHAVIOR: cache lost */ } }
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); }
int main(int argc, const char **argv) { if (argc < 3) return syntax_error(argv, 5); int csize = atoi(argv[1]), climit0 = atoi(argv[2]); if (csize < 1 || csize > 4) return syntax_error(argv, 6); if (climit0 < 0) return syntax_error(argv, 7); int exit_code = 0; size_t count = 0; size_t cmax = csize == 4 ? 0xffffffff : 0xffffffff & ((1 << (csize * 8)) - 1); size_t climit = climit0 ? S_MIN((size_t)climit0, cmax) : cmax; #ifdef COUNTER_USE_BITSET #define COUNTER_SET(val) sb_set(&bs, val) #define COUNTER_POPCOUNT sb_popcount(bs) sb_t *bs = sb_alloc(0); sb_eval(&bs, cmax); #else #define COUNTER_SET(val) sm_uu32_insert(&m, val, 1) #define COUNTER_POPCOUNT sm_size(m) sm_t *m = sm_alloc(SM_U32U32, 0); #endif unsigned char buf[3 * 4 * 128]; int i; ssize_t l; for (;;) { l = read(0, buf, sizeof(buf)); l = (l / csize) * csize; if (l <= 0) break; #define CNTLOOP(inc, val) \ for (i = 0; i < l; i += inc) { \ COUNTER_SET(val); \ count++; \ if (COUNTER_POPCOUNT >= climit) \ goto done; \ } switch (csize) { case 1: CNTLOOP(1, buf[i]); break; case 2: CNTLOOP(2, (size_t)(buf[i] << 8 | buf[i + 1])); break; case 3: CNTLOOP(3, (size_t)(buf[i] << 16 | buf[i + 1] << 8 | buf[i + 2])); break; case 4: CNTLOOP(4, (size_t)buf[i] << 24 | (size_t)buf[i + 1] << 16 | (size_t)buf[i + 2] << 8 | (size_t)buf[i + 3]); break; default: goto done; } #undef CNTLOOP } done: printf(FMT_ZU ", " FMT_ZU, count, COUNTER_POPCOUNT); #ifdef COUNTER_USE_BITSET sb_free(&bs); #else sm_free(&m); #endif return exit_code; }