diff options
Diffstat (limited to 'src/hist.c')
| -rw-r--r-- | src/hist.c | 133 |
1 files changed, 92 insertions, 41 deletions
@@ -123,9 +123,18 @@ static bool cont_push(struct hist *h, uint64_t seq) uint64_t *cont = malloc((size_t)cap * sizeof(*cont)); if (!cont) return false; - for (uint32_t i = 0; i < h->cont_count; i++) - cont[i] = cont_at(h, i); - free(h->cont); + if (h->cont) { + uint32_t count = h->cont_count; + uint32_t first = h->cont_first; + uint32_t old_cap = h->cont_mask + 1; + uint32_t chunk = old_cap - first; + if (chunk > count) + chunk = count; + memcpy(cont, h->cont + first, (size_t)chunk * sizeof(*cont)); + if (count > chunk) + memcpy(cont + chunk, h->cont, (size_t)(count - chunk) * sizeof(*cont)); + free(h->cont); + } h->cont = cont; h->cont_mask = cap - 1; h->cont_first = 0; @@ -165,6 +174,8 @@ static uint64_t line_first(const struct hist *h, uint64_t id) static inline uint64_t line_end(const struct hist *h, uint64_t first) { + if (!h->cont_count) + return first + 1; uint64_t s = first + 1; while (s < h->head && (part(h, s)->flags & HLINE_CONT)) s++; @@ -463,12 +474,12 @@ static uint64_t evict_simple_run(struct hist *h, uint64_t k) (t8 >> 24) != 255 && (t9 >> 24) != 255 && (t10 >> 24) != 255 && (t11 >> 24) != 255 && (t12 >> 24) != 255 && (t13 >> 24) != 255 && (t14 >> 24) != 255 && (t15 >> 24) != 255, 1)) { - uint32_t o0 = f[0].off, o15 = f[15].off; - if (have_page && (o0 >> 16) == page && (o15 >> 16) == page && - o0 != NO_TEXT && f[1].off != NO_TEXT && f[2].off != NO_TEXT && f[3].off != NO_TEXT && - f[4].off != NO_TEXT && f[5].off != NO_TEXT && f[6].off != NO_TEXT && f[7].off != NO_TEXT && - f[8].off != NO_TEXT && f[9].off != NO_TEXT && f[10].off != NO_TEXT && f[11].off != NO_TEXT && - f[12].off != NO_TEXT && f[13].off != NO_TEXT && f[14].off != NO_TEXT && o15 != NO_TEXT) { + uint32_t target = page << 16; + uint32_t off_diff = (f[0].off ^ target) | (f[1].off ^ target) | (f[2].off ^ target) | (f[3].off ^ target) | + (f[4].off ^ target) | (f[5].off ^ target) | (f[6].off ^ target) | (f[7].off ^ target) | + (f[8].off ^ target) | (f[9].off ^ target) | (f[10].off ^ target) | (f[11].off ^ target) | + (f[12].off ^ target) | (f[13].off ^ target) | (f[14].off ^ target) | (f[15].off ^ target); + if (have_page && (off_diff & 0xffff0000u) == 0) { run += 16; } else { for (int j = 0; j < 16; j++) { @@ -548,9 +559,17 @@ static inline void evict_for(struct hist *h, uint64_t n) if (have + n <= (uint64_t)h->line_limit) return; uint64_t need = have + n - h->line_limit; - uint64_t done = evict_simple_run(h, need); - for (uint64_t i = done; i < need; i++) + while (need > 0) { + uint64_t done = evict_simple_run(h, need); + if (done >= need) + break; + need -= done; + uint64_t old_lines = h->lines; evict_line(h); + if (h->lines == old_lines) + break; + need--; + } } /* Drop the oldest line with all its parts. It is never the open line. */ @@ -615,27 +634,57 @@ static inline int page_for(struct hist *h, size_t need) static inline int put_varint(uint8_t *p, uint32_t v) { - int n = 0; - while (v >= 0x80) { - p[n++] = (uint8_t)(v | 0x80); - v >>= 7; + if (TERM_EXPECT(v < 0x80, 1)) { + p[0] = (uint8_t)v; + return 1; } - p[n++] = (uint8_t)v; - return n; + p[0] = (uint8_t)(v | 0x80); + if (TERM_EXPECT(v < 0x4000, 1)) { + p[1] = (uint8_t)(v >> 7); + return 2; + } + p[1] = (uint8_t)((v >> 7) | 0x80); + if (v < 0x200000) { + p[2] = (uint8_t)(v >> 14); + return 3; + } + p[2] = (uint8_t)((v >> 14) | 0x80); + if (v < 0x10000000) { + p[3] = (uint8_t)(v >> 21); + return 4; + } + p[3] = (uint8_t)((v >> 21) | 0x80); + p[4] = (uint8_t)(v >> 28); + return 5; } static inline int get_varint(const uint8_t *p, uint32_t *v) { - uint32_t r = 0; - int shift = 0, n = 0; - uint8_t b; - do { - b = p[n++]; - r |= (uint32_t)(b & 0x7f) << shift; - shift += 7; - } while ((b & 0x80) && shift < 35); - *v = r; - return n; + uint8_t b0 = p[0]; + if (TERM_EXPECT((b0 & 0x80) == 0, 1)) { + *v = b0; + return 1; + } + uint8_t b1 = p[1]; + if (TERM_EXPECT((b1 & 0x80) == 0, 1)) { + *v = (uint32_t)(b0 & 0x7f) | ((uint32_t)b1 << 7); + return 2; + } + uint8_t b2 = p[2]; + if ((b2 & 0x80) == 0) { + *v = (uint32_t)(b0 & 0x7f) | ((uint32_t)(b1 & 0x7f) << 7) | ((uint32_t)b2 << 14); + return 3; + } + uint8_t b3 = p[3]; + if ((b3 & 0x80) == 0) { + *v = (uint32_t)(b0 & 0x7f) | ((uint32_t)(b1 & 0x7f) << 7) | + ((uint32_t)(b2 & 0x7f) << 14) | ((uint32_t)b3 << 21); + return 4; + } + *v = (uint32_t)(b0 & 0x7f) | ((uint32_t)(b1 & 0x7f) << 7) | + ((uint32_t)(b2 & 0x7f) << 14) | ((uint32_t)(b3 & 0x7f) << 21) | + ((uint32_t)(p[4] & 0x7f) << 28); + return 5; } static inline void put_u32(uint8_t *p, uint32_t v) { memcpy(p, &v, 4); } @@ -649,7 +698,7 @@ static inline uint8_t *emit_run(uint8_t *p, const struct pen_attr *base, const s /* Most runs change only colors and cover fewer than 128 cells. */ if (TERM_EXPECT(count < 0x80 && pen_sl(pen) == pen_sl(base), 1)) { uint32_t dfg = pen->fg != base->fg, dbg = pen->bg != base->bg; - p[0] = (uint8_t)(dfg * RUN_FG | dbg * RUN_BG); + p[0] = (uint8_t)(dfg | (dbg << 1)); p[1] = (uint8_t)count; p += 2; put_u32(p, pen->fg); @@ -685,9 +734,7 @@ static bool runs_reserve(struct hist_runs *r, size_t extra) { if (TERM_EXPECT(r->len + extra <= r->cap, 1)) return true; - size_t cap = r->cap ? r->cap : 256; - while (cap < r->len + extra) - cap *= 2; + size_t cap = term_grow_cap(r->cap ? r->cap : 256, (size_t)r->len + extra); uint8_t *data = realloc(r->data, cap); if (!data) return false; @@ -2381,7 +2428,7 @@ static void runs_iter_init(struct runs_iter *it, const struct hist *h, const str /* Take up to n cells of the current run. it->pen is their pen. */ static inline uint32_t runs_take(struct runs_iter *it, uint32_t n) { - while (it->left == 0) { + while (TERM_EXPECT(it->left == 0, 0)) { if (it->p < it->end) { it->p = read_run(it->p, &it->pen, &it->left); } else if (it->pending) { @@ -2488,7 +2535,10 @@ uint64_t term_hist_line_cells(const struct hist *h, uint64_t id) return 0; if (id == h->last_id && h->last_cells) return h->last_cells; - uint64_t first = line_first(h, id), end = line_end(h, first), cells = 0; + uint64_t first = line_first(h, id), end = line_end(h, first); + if (first + 1 == end) + return part(h, first)->cells; + uint64_t cells = 0; for (uint64_t s = first; s < end; s++) cells += part(h, s)->cells; return cells; @@ -2500,7 +2550,10 @@ uint64_t term_hist_line_wide(const struct hist *h, uint64_t id) return 0; if (id == h->last_id && h->last_cells) return h->last_wide; - uint64_t first = line_first(h, id), end = line_end(h, first), wide = 0; + uint64_t first = line_first(h, id), end = line_end(h, first); + if (first + 1 == end) + return part(h, first)->wide; + uint64_t wide = 0; for (uint64_t seq = first; seq < end; seq++) wide += part(h, seq)->wide; return wide; @@ -2512,6 +2565,8 @@ uint8_t term_hist_line_flags(const struct hist *h, uint64_t id) return 0; uint64_t first = line_first(h, id), end = line_end(h, first); uint8_t flags = part(h, first)->flags; + if (first + 1 == end) + return flags; for (uint64_t s = first + 1; s < end; s++) { uint8_t f = part(h, s)->flags; flags = (uint8_t)((flags | f) & ~HLINE_NARROW) | (flags & f & HLINE_NARROW); @@ -2639,7 +2694,7 @@ int term_hist_decode_segments(const struct hist *h, uint64_t id, int start_seg, struct runs_iter it; runs_iter_init(&it, h, p); for (uint64_t k = skip; k > 0;) - k -= runs_take(&it, k > UINT32_MAX ? UINT32_MAX : (uint32_t)k); + k -= runs_take(&it, (uint32_t)k); const char *src = (const char *)part_text(h, p) + skip; while (avail > 0 && seg_idx < count) { int need = cols - n; @@ -2722,7 +2777,7 @@ int term_hist_decode_segments(const struct hist *h, uint64_t id, int start_seg, runs_iter_init(&it, h, p); for (uint32_t k = skipped_cells; k > 0;) - k -= runs_take(&it, k > UINT32_MAX ? UINT32_MAX : k); + k -= runs_take(&it, k); } while (t < tend && row < end_seg) { @@ -3201,10 +3256,8 @@ bool term_hist_init(struct hist *h, int line_limit, size_t byte_cap) h->pages = calloc(h->max_pages, sizeof(*h->pages)); h->page_used = calloc(h->max_pages, sizeof(*h->page_used)); h->page_parts = calloc(h->max_pages, sizeof(*h->page_parts)); - h->page_rows = calloc(h->max_pages, sizeof(*h->page_rows)); - h->page_simple = calloc(h->max_pages, sizeof(*h->page_simple)); h->free_pages = malloc(h->max_pages * sizeof(*h->free_pages)); - if (!h->pages || !h->page_used || !h->page_parts || !h->page_rows || !h->page_simple || !h->free_pages || !ring_reserve(h)) { + if (!h->pages || !h->page_used || !h->page_parts || !h->free_pages || !ring_reserve(h)) { term_hist_free(h); return false; } @@ -3219,8 +3272,6 @@ void term_hist_free(struct hist *h) free(h->pages); free(h->page_used); free(h->page_parts); - free(h->page_rows); - free(h->page_simple); free(h->free_pages); term_aligned_free(h->ring); free(h->blocks); |
