From 6f7c1546d6f57160644745429c13c5c9e8ca5b2e Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Wed, 3 Mar 2021 12:05:11 -0500 Subject: finally figured out what wasn't working with buffer_set_line_len! hooray!!!!! --- buffer.c | 72 +++++++++++++++++++++++++++++++++++++++------------------------- main.c | 3 +-- util.c | 20 ++++++++++++------ 3 files changed, 59 insertions(+), 36 deletions(-) diff --git a/buffer.c b/buffer.c index d1ccb11..8106494 100644 --- a/buffer.c +++ b/buffer.c @@ -446,6 +446,39 @@ static void buffer_pos_print(BufferPos p) { printf("[" U32_FMT ":" U32_FMT "]", p.line, p.index); } +// for debugging +#if !NDEBUG +static void buffer_pos_check_valid(TextBuffer *buffer, BufferPos p) { + assert(p.line < buffer->nlines); + assert(p.index <= buffer->lines[p.line].len); +} + +static bool buffer_line_valid(Line *line) { + if (line->len && !line->str) + return false; + return true; +} + +// perform a series of checks to make sure the buffer doesn't have any invalid values +void buffer_check_valid(TextBuffer *buffer) { + assert(buffer->nlines); + buffer_pos_check_valid(buffer, buffer->cursor_pos); + if (buffer->selection) { + buffer_pos_check_valid(buffer, buffer->selection_pos); + // you shouldn't be able to select nothing + assert(!buffer_pos_eq(buffer->cursor_pos, buffer->selection_pos)); + } + for (u32 i = 0; i < buffer->nlines; ++i) { + Line *line = &buffer->lines[i]; + assert(buffer_line_valid(line)); + } +} +#else +void buffer_check_valid(TextBuffer *buffer) { + (void)buffer; +} +#endif + static Status buffer_edit_create(TextBuffer *buffer, BufferEdit *edit, BufferPos start, u32 prev_len, u32 new_len) { edit->time = time_get_seconds(); if (prev_len == 0) @@ -559,10 +592,11 @@ static void buffer_remove_last_edit_if_empty(TextBuffer *buffer) { // returns true if allocation was succesful static Status buffer_line_set_len(TextBuffer *buffer, Line *line, u32 new_len) { if (new_len >= 8) { - u32 curr_capacity = (u32)1 << (32 - util_count_leading_zeroes(line->len)); + u32 curr_capacity = (u32)1 << (32 - util_count_leading_zeroes32(line->len)); + assert(curr_capacity > line->len); if (new_len >= curr_capacity) { - u8 leading_zeroes = util_count_leading_zeroes(new_len); + u8 leading_zeroes = util_count_leading_zeroes32(new_len); if (leading_zeroes == 0) { // this line is too big return false; @@ -587,6 +621,7 @@ static Status buffer_line_set_len(TextBuffer *buffer, Line *line, u32 new_len) { } } line->len = new_len; + assert(line->str); return true; } @@ -1291,9 +1326,10 @@ BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32 Line *line = &buffer->lines[line_idx]; // `text` could consist of multiple lines, e.g. U"line 1\nline 2", - // so we need to go through them one by one + u32 n_added_lines = (u32)str32_count_char(str, '\n'); if (n_added_lines) { + // allocate space for the new lines if (buffer_insert_lines(buffer, line_idx + 1, n_added_lines)) { line = &buffer->lines[line_idx]; // fix pointer // move any text past the cursor on this line to the last added line. @@ -1302,14 +1338,15 @@ BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32 if (chars_moved) { if (buffer_line_set_len(buffer, last_line, chars_moved)) { memcpy(last_line->str, line->str + index, chars_moved * sizeof(char32_t)); - line->len -= chars_moved; + line->len -= chars_moved; } } } } - while (str.len) { + // insert the actual text from each line in str + while (1) { u32 text_line_len = (u32)str32chr(str, '\n'); u32 old_len = line->len; u32 new_len = old_len + text_line_len; @@ -1334,6 +1371,8 @@ BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32 ++line; ++str.str; --str.len; + } else { + break; } } @@ -2061,29 +2100,6 @@ bool buffer_save_as(TextBuffer *buffer, char const *new_filename) { } } -// for debugging -#if DEBUG -static void buffer_pos_check_valid(TextBuffer *buffer, BufferPos p) { - assert(p.line < buffer->nlines); - assert(p.index <= buffer->lines[p.line].len); -} - -// perform a series of checks to make sure the buffer doesn't have any invalid values -void buffer_check_valid(TextBuffer *buffer) { - assert(buffer->nlines); - buffer_pos_check_valid(buffer, buffer->cursor_pos); - if (buffer->selection) { - buffer_pos_check_valid(buffer, buffer->selection_pos); - // you shouldn't be able to select nothing - assert(!buffer_pos_eq(buffer->cursor_pos, buffer->selection_pos)); - } -} -#else -void buffer_check_valid(TextBuffer *buffer) { - (void)buffer; -} -#endif - u32 buffer_first_rendered_line(TextBuffer *buffer) { return (u32)buffer->scroll_y; } diff --git a/main.c b/main.c index dc30eeb..3ffd7c8 100644 --- a/main.c +++ b/main.c @@ -288,7 +288,6 @@ int main(int argc, char **argv) { setlocale(LC_ALL, ""); // allow unicode - printf("%p\n",ted); // @TODO: delete me // read command-line arguments char const *starting_filename = NULL; @@ -849,7 +848,7 @@ int main(int argc, char **argv) { } } - #if DEBUG + #if !NDEBUG for (u16 i = 0; i < TED_MAX_BUFFERS; ++i) if (ted->buffers_used[i]) buffer_check_valid(&ted->buffers[i]); diff --git a/util.c b/util.c index 632bd0e..f0daa09 100644 --- a/util.c +++ b/util.c @@ -20,16 +20,24 @@ static u8 util_popcount(u64 x) { #endif } -static u8 util_count_leading_zeroes(u64 x) { +static u8 util_count_leading_zeroes32(u32 x) { + if (x == 0) return 32; // GCC's __builtin_clz is undefined for x = 0 #if __GNUC__ - return (u8)__builtin_clzll(x); +#if UINT_MAX == 4294967295 + return (u8)__builtin_clz(x); +#else + #error "unsigned int isn't 32 bits. this function needs fixing to work on sytems like yours." +#endif #elif _WIN32 - return (u8)__lzcnt64(x); + return (u8)__lzcnt(x); #else u8 count = 0; - for (int i = 63; i >= 0; --i) - if (x & ((u64)1<= 0; --i) { + if (x & ((u32)1<