diff --git a/src/core/BufferLineWalker.cc b/src/core/BufferLineWalker.cc index 77e6305..c6d7e55 100644 --- a/src/core/BufferLineWalker.cc +++ b/src/core/BufferLineWalker.cc @@ -2,100 +2,100 @@ /** * Construct a BufferLineWalker. + * + * @param buffer The Buffer we're iterating. + * @param start_of_line Buffer iterator pointing to the beginning of the buffer line. + * @param view_width View width, beyond which characters will wrap to the next line. + * @param character_width_determiner Functor to return the width (in columns) of a character. */ BufferLineWalker::BufferLineWalker( std::shared_ptr buffer, + std::shared_ptr start_of_line, + int view_width, CharacterWidthDeterminer & character_width_determiner) : m_buffer(buffer), m_character_width_determiner(character_width_determiner) { - m_width = 1; + m_view_width = view_width; + m_row_offset = 0; + m_screen_column = 0; + m_virtual_column = 0; + m_iterator = std::make_shared(*start_of_line); + process_new_character(); } -/** - * Set the view width. - * - * @param width View width. - */ -void BufferLineWalker::set_width(int width) +void BufferLineWalker::process_new_character() { - m_width = std::max(1, width); -} - -/** - * Invoke the callback for each character in the buffer line, wrapping to the - * next screen line and taking into account multi-column characters. - * - * Callback parameters: - * - row_offset - * - screen column - * - virtual column - * - character width - * - buffer iterator - * If the callback function returns true, iteration continues. Otherwise - * iteration is terminated. - * - * @param start_of_line Buffer iterator pointing to the beginning of the buffer line. - * @param callback Function to call for each character in the line. - */ -void BufferLineWalker::walk_line( - const Buffer::Iterator & start_of_line, - std::function callback) -{ - int row_offset = 0; - int screen_column = 0; - int virtual_column = 0; - Buffer::Iterator i = start_of_line; - for (;;) + if ((!m_iterator) || (!m_iterator->valid())) { - uint32_t code_point = *i; - if ((code_point == '\n') || (!i.valid())) - { - callback(row_offset, screen_column, virtual_column, 0, i); - break; - } - int c_width; - if (code_point == '\t') - { - uint8_t tabstop = m_buffer->tabstop(); - c_width = tabstop - virtual_column % tabstop; - } - else - { - c_width = m_character_width_determiner(code_point); - if (((screen_column + c_width) > m_width) && - (screen_column > 0)) - { - row_offset++; - screen_column = 0; - } - } - if (!callback(row_offset, screen_column, virtual_column, c_width, i)) - { - break; - } - virtual_column += c_width; - if (code_point == '\t') - { - screen_column += c_width; - while (screen_column >= m_width) - { - screen_column -= m_width; - row_offset++; - } - } - else - { - if ((screen_column + c_width) >= m_width) - { - row_offset++; - screen_column = 0; - } - else - { - screen_column += c_width; - } - } - i.go_forward(); + m_code_point = '\n'; + m_character_width = 0; + return; + } + + m_code_point = **m_iterator; + + if (m_code_point == '\n') + { + m_character_width = 0; + return; + } + + if (m_code_point == '\t') + { + uint8_t tabstop = m_buffer->tabstop(); + m_character_width = tabstop - m_virtual_column % tabstop; + return; + } + + m_character_width = m_character_width_determiner(m_code_point); + + if (((m_screen_column + m_character_width) > m_view_width) && + (m_screen_column > 0)) + { + m_row_offset++; + m_screen_column = 0; } } + +void BufferLineWalker::operator++(int unused) +{ + if (!m_iterator) + return; + + if ((m_code_point == '\n') || (!m_iterator->valid())) + { + m_code_point = '\n'; + m_iterator.reset(); + return; + } + + /* Adjust virtual column. */ + m_virtual_column += m_character_width; + + /* Adjust screen position. */ + if (m_code_point == '\t') + { + m_screen_column += m_character_width; + while (m_screen_column >= m_view_width) + { + m_screen_column -= m_view_width; + m_row_offset++; + } + } + else + { + if ((m_screen_column + m_character_width) >= m_view_width) + { + m_row_offset++; + m_screen_column = 0; + } + else + { + m_screen_column += m_character_width; + } + } + + m_iterator->go_forward(); + process_new_character(); +} diff --git a/src/core/BufferLineWalker.h b/src/core/BufferLineWalker.h index 56f51b8..3e4fb28 100644 --- a/src/core/BufferLineWalker.h +++ b/src/core/BufferLineWalker.h @@ -14,16 +14,42 @@ class BufferLineWalker public: BufferLineWalker( std::shared_ptr buffer, + std::shared_ptr start_of_line, + int view_width, CharacterWidthDeterminer & character_width_determiner); - void set_width(int width); - void walk_line( - const Buffer::Iterator & start_of_line, - std::function callback); + void operator++() { return (*this)++; } + void operator++(int unused); + bool is_eol() const + { + if (is_valid()) + { + return (m_code_point == '\n'); + } + return false; + } + bool is_valid() const + { + return (bool)m_iterator; + } + int row_offset() const { return m_row_offset; } + int screen_column() const { return m_screen_column; } + int virtual_column() const { return m_virtual_column; } + int character_width() const { return m_character_width; } + uint32_t code_point() const { return m_code_point; } + std::shared_ptr iterator() const { return m_iterator; } protected: std::shared_ptr m_buffer; + std::shared_ptr m_iterator; CharacterWidthDeterminer & m_character_width_determiner; - int m_width; + int m_view_width; + int m_row_offset; + int m_screen_column; + int m_virtual_column; + int m_character_width; + uint32_t m_code_point; + + void process_new_character(); }; #endif diff --git a/src/core/BufferView.cc b/src/core/BufferView.cc index 8464d01..eae9a8f 100644 --- a/src/core/BufferView.cc +++ b/src/core/BufferView.cc @@ -5,20 +5,22 @@ BufferView::BufferView(std::shared_ptr buffer, std::shared_ptr iterator, CharacterWidthDeterminer & character_width_determiner) - : m_iterator(iterator) + : m_buffer(buffer), + m_iterator(iterator), + m_character_width_determiner(character_width_determiner) { + m_width = 1; m_height = 1; m_scroll_offset = 0; m_cursor_screen_row = 0; m_cursor_screen_column = 0; m_cursor_virtual_column = 0; m_cursor_row_offset = 0; - m_buffer_line_walker = std::make_shared(buffer, character_width_determiner); } void BufferView::resize(int width, int height) { - m_buffer_line_walker->set_width(width); + m_width = std::max(1, width); m_height = std::max(1, height); } @@ -27,21 +29,12 @@ void BufferView::set_scroll_offset(int scroll_offset) m_scroll_offset = std::max(0, scroll_offset); } -void BufferView::iter_lines( - std::function callback) +BufferView::Iterator BufferView::vert_iter() { if (m_iterator->valid()) { + /* TODO: user calls update() before vert_iter(). */ update(); - Buffer::Iterator i = *m_first_line; - int row_offset = m_first_line_row_offset; - while (row_offset < m_height) - { - callback(row_offset, i); - row_offset += calculate_rows_in_line(i); - if (!i.go_next_line()) - break; - } } else { @@ -49,6 +42,7 @@ void BufferView::iter_lines( m_cursor_screen_column = 0; m_cursor_virtual_column = 0; } + return Iterator(*this); } /************************************************************************** @@ -58,12 +52,12 @@ void BufferView::iter_lines( void BufferView::update() { std::list>> backward_lines; - Buffer::Iterator start_of_line = *m_iterator; - start_of_line.go_start_of_line(); + auto start_of_line = std::make_shared(*m_iterator); + start_of_line->go_start_of_line(); int rows_in_cursor_line = calculate_rows_in_cursor_line(start_of_line); int so = effective_scroll_offset(); - int rows_above = screen_rows_above_line(*m_iterator, backward_lines) + m_cursor_row_offset; - int rows_below = screen_rows_below_line(*m_iterator) + std::max(0, rows_in_cursor_line - m_cursor_row_offset - 1); + int rows_above = screen_rows_above_line(start_of_line, backward_lines) + m_cursor_row_offset; + int rows_below = screen_rows_below_line(start_of_line) + std::max(0, rows_in_cursor_line - m_cursor_row_offset - 1); int min_rows_to_leave_above = std::min(rows_above, so); int min_rows_to_leave_below = std::min(rows_below, so); m_cursor_screen_row = std::min(m_height - min_rows_to_leave_below - 1, m_cursor_screen_row); @@ -89,49 +83,51 @@ void BufferView::update() } } -int BufferView::calculate_rows_in_line(const Buffer::Iterator & start_of_line) +int BufferView::calculate_rows_in_line(std::shared_ptr start_of_line) { int saved_row_offset = 0; - walk_line(start_of_line, [&saved_row_offset](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & i) -> bool { - uint32_t code_point = *i; - if ((code_point != '\n') && - (code_point != Buffer::Iterator::INVALID_CODE_POINT)) + for (auto it = horiz_iter(start_of_line); it.is_valid(); it++) + { + if (!it.is_eol()) { - saved_row_offset = row_offset; - return true; + saved_row_offset = it.row_offset(); } - return false; - }); + else + { + break; + } + } return saved_row_offset + 1; } -int BufferView::calculate_rows_in_cursor_line(const Buffer::Iterator & start_of_line) +int BufferView::calculate_rows_in_cursor_line(std::shared_ptr start_of_line) { int saved_row_offset = 0; - walk_line(start_of_line, [this, &saved_row_offset](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & i) -> bool { - uint32_t code_point = *i; - if (i == *m_iterator) + for (auto it = horiz_iter(start_of_line); it.is_valid(); it++) + { + if (*it.iterator() == *m_iterator) { - m_cursor_virtual_column = virtual_column; - m_cursor_screen_column = screen_column; - m_cursor_row_offset = row_offset; + m_cursor_virtual_column = it.virtual_column(); + m_cursor_screen_column = it.screen_column(); + m_cursor_row_offset = it.row_offset(); } - if ((code_point != '\n') && - (code_point != Buffer::Iterator::INVALID_CODE_POINT)) + if (!it.is_eol()) { - saved_row_offset = row_offset; - return true; + saved_row_offset = it.row_offset(); } - return false; - }); + else + { + break; + } + } return saved_row_offset + 1; } -int BufferView::screen_rows_below_line(const Buffer::Iterator & line) +int BufferView::screen_rows_below_line(std::shared_ptr line) { - Buffer::Iterator i = line; + auto i = std::make_shared(*line); int rows = 0; - while ((rows < m_height) && i.go_next_line()) + while ((rows < m_height) && i->go_next_line()) { rows += calculate_rows_in_line(i); } @@ -139,16 +135,16 @@ int BufferView::screen_rows_below_line(const Buffer::Iterator & line) } int BufferView::screen_rows_above_line( - const Buffer::Iterator & line, + std::shared_ptr line, std::list>> & backward_lines) { - Buffer::Iterator i = line; + auto i = std::make_shared(*line); int rows = 0; - while ((rows < m_height) && i.go_previous_line()) + while ((rows < m_height) && i->go_previous_line()) { int rows_in_this_line = calculate_rows_in_line(i); rows += rows_in_this_line; - backward_lines.push_back(std::pair>(rows_in_this_line, std::make_shared(i))); + backward_lines.push_back(std::pair>(rows_in_this_line, std::make_shared(*i))); } return rows; } diff --git a/src/core/BufferView.h b/src/core/BufferView.h index 441c99f..3476690 100644 --- a/src/core/BufferView.h +++ b/src/core/BufferView.h @@ -13,45 +13,89 @@ class BufferView { public: + class Iterator + { + public: + Iterator(BufferView & bv) : m_buffer_view(bv) + { + if (bv.m_iterator->valid()) + { + m_iterator = std::make_shared(*m_buffer_view.m_first_line); + m_row_offset = m_buffer_view.m_first_line_row_offset; + } + } + void operator++() + { + (*this)++; + } + void operator++(int unused) + { + if (is_valid()) + { + m_row_offset += m_buffer_view.calculate_rows_in_line(m_iterator); + if ((m_row_offset >= m_buffer_view.m_height) || (!m_iterator->go_next_line())) + { + m_iterator.reset(); + } + } + } + bool is_valid() + { + return (bool)m_iterator; + } + int row_offset() const + { + return m_row_offset; + } + std::shared_ptr iterator() const + { + return m_iterator; + } + + protected: + BufferView & m_buffer_view; + std::shared_ptr m_iterator; + int m_row_offset; + }; + BufferView(std::shared_ptr buffer, std::shared_ptr iterator, CharacterWidthDeterminer & character_width_determiner); void resize(int width, int height); void set_scroll_offset(int scroll_offset); - void iter_lines( - std::function callback); - void walk_line( - const Buffer::Iterator & start_of_line, - std::function callback) + Iterator vert_iter(); + BufferLineWalker horiz_iter(std::shared_ptr start_of_line) { - m_buffer_line_walker->walk_line(start_of_line, callback); + return BufferLineWalker(m_buffer, start_of_line, m_width, m_character_width_determiner); } int cursor_screen_row() const { return m_cursor_screen_row; } int cursor_screen_column() const { return m_cursor_screen_column; } int cursor_virtual_column() const { return m_cursor_virtual_column; } protected: + std::shared_ptr m_buffer; std::shared_ptr m_iterator; std::shared_ptr m_first_line; int m_first_line_row_offset; + int m_width; int m_height; int m_scroll_offset; int m_cursor_screen_row; int m_cursor_screen_column; int m_cursor_virtual_column; int m_cursor_row_offset; - std::shared_ptr m_buffer_line_walker; + CharacterWidthDeterminer & m_character_width_determiner; int effective_scroll_offset() { return std::min(m_scroll_offset, (m_height - 1) / 2); } void update(); - int calculate_rows_in_line(const Buffer::Iterator & start_of_line); - int calculate_rows_in_cursor_line(const Buffer::Iterator & start_of_line); - int screen_rows_below_line(const Buffer::Iterator & line); + int calculate_rows_in_line(std::shared_ptr start_of_line); + int calculate_rows_in_cursor_line(std::shared_ptr start_of_line); + int screen_rows_below_line(std::shared_ptr line); int screen_rows_above_line( - const Buffer::Iterator & line, + std::shared_ptr line, std::list>> & backward_lines); }; diff --git a/test/src/test_BufferLineWalker.cc b/test/src/test_BufferLineWalker.cc index 6491ede..c14248a 100644 --- a/test/src/test_BufferLineWalker.cc +++ b/test/src/test_BufferLineWalker.cc @@ -16,165 +16,143 @@ class MyCharacterWidthDeterminer : public CharacterWidthDeterminer } } cld; -TEST(BufferLineWalkerTest, calls_callback_once_for_empty_line) +TEST(BufferLineWalkerTest, iterats_once_for_empty_line) { static const uint8_t data[] = "\n"; std::shared_ptr b = std::make_shared(data, 1u); - BufferLineWalker blw(b, cld); - blw.set_width(20); std::shared_ptr start_of_line = b->add_iterator(); - int times_called = 0; - blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { - times_called++; - EXPECT_EQ(0, row_offset); - EXPECT_EQ(0, screen_column); - EXPECT_EQ(0, virtual_column); - EXPECT_EQ(0, character_width); - return true; - }); - EXPECT_EQ(1, times_called); + BufferLineWalker blw(b, start_of_line, 20, cld); + int iter_count = 0; + for (; blw.is_valid(); blw++) + { + EXPECT_EQ(0, blw.row_offset()); + EXPECT_EQ(0, blw.screen_column()); + EXPECT_EQ(0, blw.virtual_column()); + EXPECT_EQ(0, blw.character_width()); + EXPECT_TRUE(blw.is_eol()); + iter_count++; + } + EXPECT_EQ(1, iter_count); } TEST(BufferLineWalkerTest, walks_correctly_with_tabs_and_no_line_wrapping) { static const char data[] = "\t1\t12\t123\t1234\t!"; std::shared_ptr b = std::make_shared((const uint8_t *)data, strlen(data)); - BufferLineWalker blw(b, cld); - blw.set_width(100); std::shared_ptr start_of_line = b->add_iterator(); - int times_called = 0; - blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { - EXPECT_EQ(0, row_offset); - static int expected_screen_columns[] = { - 0, 4, 5, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 24, 25 - }; - static int expected_character_widths[] = { - 4, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 0 - }; - EXPECT_LT(times_called, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); - EXPECT_EQ(expected_screen_columns[times_called], screen_column); - EXPECT_EQ(expected_screen_columns[times_called], virtual_column); - EXPECT_EQ(expected_character_widths[times_called], character_width); - times_called++; - return true; - }); - EXPECT_EQ((int)strlen(data) + 1, times_called); + BufferLineWalker blw(b, start_of_line, 100, cld); + + static int expected_screen_columns[] = { + 0, 4, 5, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 24, 25 + }; + static int expected_character_widths[] = { + 4, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 0 + }; + int iter_count = 0; + for (; blw.is_valid(); blw++) + { + EXPECT_EQ(0, blw.row_offset()); + EXPECT_LT(iter_count, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); + EXPECT_EQ(expected_screen_columns[iter_count], blw.screen_column()); + EXPECT_EQ(expected_screen_columns[iter_count], blw.virtual_column()); + EXPECT_EQ(expected_character_widths[iter_count], blw.character_width()); + iter_count++; + } + EXPECT_EQ((int)strlen(data) + 1, iter_count); } TEST(BufferLineWalkerTest, walks_correctly_with_tabs_and_line_wrapping) { static const char data[] = "\t1\t12\t123\t1234\t!"; std::shared_ptr b = std::make_shared((const uint8_t *)data, strlen(data)); - BufferLineWalker blw(b, cld); - blw.set_width(5); std::shared_ptr start_of_line = b->add_iterator(); - int times_called = 0; - blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { - static int expected_screen_columns[] = { - 0, 4, 0, 3, 4, 0, 2, 3, 4, 0, 1, 2, 3, 4, 0, 4, 0 - }; - static int expected_row_offsets[] = { - 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5 - }; - static int expected_virtual_columns[] = { - 0, 4, 5, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 24, 25 - }; - static int expected_character_widths[] = { - 4, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 0 - }; - EXPECT_LT(times_called, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); - EXPECT_EQ(expected_row_offsets[times_called], row_offset); - EXPECT_EQ(expected_screen_columns[times_called], screen_column); - EXPECT_EQ(expected_virtual_columns[times_called], virtual_column); - EXPECT_EQ(expected_character_widths[times_called], character_width); - times_called++; - return true; - }); - EXPECT_EQ((int)strlen(data) + 1, times_called); + BufferLineWalker blw(b, start_of_line, 5, cld); + + static int expected_screen_columns[] = { + 0, 4, 0, 3, 4, 0, 2, 3, 4, 0, 1, 2, 3, 4, 0, 4, 0 + }; + static int expected_row_offsets[] = { + 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5 + }; + static int expected_virtual_columns[] = { + 0, 4, 5, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 24, 25 + }; + static int expected_character_widths[] = { + 4, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 0 + }; + int iter_count = 0; + for (; blw.is_valid(); blw++) + { + EXPECT_LT(iter_count, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); + EXPECT_EQ(expected_row_offsets[iter_count], blw.row_offset()); + EXPECT_EQ(expected_screen_columns[iter_count], blw.screen_column()); + EXPECT_EQ(expected_virtual_columns[iter_count], blw.virtual_column()); + EXPECT_EQ(expected_character_widths[iter_count], blw.character_width()); + iter_count++; + } + EXPECT_EQ((int)strlen(data) + 1, iter_count); } TEST(BufferLineWalkerTest, walks_correctly_with_multi_column_characters_and_line_wrapping) { static const char data[] = "ab\002xyz\003."; std::shared_ptr b = std::make_shared((const uint8_t *)data, strlen(data)); - BufferLineWalker blw(b, cld); - blw.set_width(4); std::shared_ptr start_of_line = b->add_iterator(); - int times_called = 0; - blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { - static int expected_screen_columns[] = { - 0, 1, 2, 0, 1, 2, 0, 2, 3 - }; - static int expected_row_offsets[] = { - 0, 0, 0, 1, 1, 1, 2, 2, 2 - }; - static int expected_virtual_columns[] = { - 0, 1, 2, 4, 5, 6, 7, 9, 10 - }; - static int expected_character_widths[] = { - 1, 1, 2, 1, 1, 1, 2, 1, 0 - }; - EXPECT_LT(times_called, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); - EXPECT_EQ(expected_row_offsets[times_called], row_offset); - EXPECT_EQ(expected_screen_columns[times_called], screen_column); - EXPECT_EQ(expected_virtual_columns[times_called], virtual_column); - EXPECT_EQ(expected_character_widths[times_called], character_width); - times_called++; - return true; - }); - EXPECT_EQ((int)strlen(data) + 1, times_called); + BufferLineWalker blw(b, start_of_line, 4, cld); + + static int expected_screen_columns[] = { + 0, 1, 2, 0, 1, 2, 0, 2, 3 + }; + static int expected_row_offsets[] = { + 0, 0, 0, 1, 1, 1, 2, 2, 2 + }; + static int expected_virtual_columns[] = { + 0, 1, 2, 4, 5, 6, 7, 9, 10 + }; + static int expected_character_widths[] = { + 1, 1, 2, 1, 1, 1, 2, 1, 0 + }; + int iter_count = 0; + for (; blw.is_valid(); blw++) + { + EXPECT_LT(iter_count, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); + EXPECT_EQ(expected_row_offsets[iter_count], blw.row_offset()); + EXPECT_EQ(expected_screen_columns[iter_count], blw.screen_column()); + EXPECT_EQ(expected_virtual_columns[iter_count], blw.virtual_column()); + EXPECT_EQ(expected_character_widths[iter_count], blw.character_width()); + iter_count++; + } + EXPECT_EQ((int)strlen(data) + 1, iter_count); } TEST(BufferLineWalkerTest, does_not_push_down_a_row_when_a_multi_column_character_is_wider_than_view_width) { static const char data[] = "\002\003"; std::shared_ptr b = std::make_shared((const uint8_t *)data, strlen(data)); - BufferLineWalker blw(b, cld); - blw.set_width(1); std::shared_ptr start_of_line = b->add_iterator(); - int times_called = 0; - blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { - static int expected_screen_columns[] = { - 0, 0, 0 - }; - static int expected_row_offsets[] = { - 0, 1, 2 - }; - static int expected_virtual_columns[] = { - 0, 2, 4 - }; - static int expected_character_widths[] = { - 2, 2, 0 - }; - EXPECT_LT(times_called, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); - EXPECT_EQ(expected_row_offsets[times_called], row_offset); - EXPECT_EQ(expected_screen_columns[times_called], screen_column); - EXPECT_EQ(expected_virtual_columns[times_called], virtual_column); - EXPECT_EQ(expected_character_widths[times_called], character_width); - times_called++; - return true; - }); - EXPECT_EQ((int)strlen(data) + 1, times_called); -} + BufferLineWalker blw(b, start_of_line, 1, cld); -TEST(BufferLineWalkerTest, stops_iterating_when_callback_returns_false) -{ - static const char data[] = "abcdef"; - std::shared_ptr b = std::make_shared((const uint8_t *)data, strlen(data)); - BufferLineWalker blw(b, cld); - blw.set_width(6); - std::shared_ptr start_of_line = b->add_iterator(); - int times_called = 0; - blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { - times_called++; - if (times_called >= 3) - { - return false; - } - else - { - return true; - } - }); - EXPECT_EQ(3, times_called); + static int expected_screen_columns[] = { + 0, 0, 0 + }; + static int expected_row_offsets[] = { + 0, 1, 2 + }; + static int expected_virtual_columns[] = { + 0, 2, 4 + }; + static int expected_character_widths[] = { + 2, 2, 0 + }; + int iter_count = 0; + for (; blw.is_valid(); blw++) + { + EXPECT_LT(iter_count, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); + EXPECT_EQ(expected_row_offsets[iter_count], blw.row_offset()); + EXPECT_EQ(expected_screen_columns[iter_count], blw.screen_column()); + EXPECT_EQ(expected_virtual_columns[iter_count], blw.virtual_column()); + EXPECT_EQ(expected_character_widths[iter_count], blw.character_width()); + iter_count++; + } + EXPECT_EQ((int)strlen(data) + 1, iter_count); } diff --git a/test/src/test_BufferView.cc b/test/src/test_BufferView.cc index d43dd72..c89421a 100644 --- a/test/src/test_BufferView.cc +++ b/test/src/test_BufferView.cc @@ -40,34 +40,34 @@ class MyCharacterWidthDeterminer : public CharacterWidthDeterminer } } Cwd; -static int LineNumber(const Buffer::Iterator & iterator) +static int LineNumber(std::shared_ptr iterator) { int line_number = 0; - Buffer::Iterator i = iterator; + auto i = std::make_shared(*iterator); for (;;) { - uint32_t c = *i; + uint32_t c = **i; if ((c < '0') || (c > '9')) break; line_number *= 10; line_number += ((int)c - '0'); - i.go_forward(); + i->go_forward(); } return line_number; } -TEST(BufferViewTest, iter_lines_does_not_call_callback_for_empty_buffer) +TEST(BufferViewTest, does_not_iterate_for_empty_buffer) { std::shared_ptr b = buffer_empty(); std::shared_ptr iterator = b->add_iterator(); BufferView bv(b, iterator, Cwd); bv.resize(40, 8); - int times_called = 0; - bv.iter_lines([×_called](int row_offset, const Buffer::Iterator & iterator) -> bool { - times_called++; - return true; - }); - EXPECT_EQ(0, times_called); + int iter_count = 0; + for (auto it = bv.vert_iter(); it.is_valid(); it++) + { + iter_count++; + } + EXPECT_EQ(0, iter_count); EXPECT_EQ(0, bv.cursor_screen_row()); EXPECT_EQ(0, bv.cursor_screen_column()); EXPECT_EQ(0, bv.cursor_virtual_column()); @@ -79,13 +79,13 @@ TEST(BufferViewTest, iterates_through_screen_lines_with_no_wrapping) std::shared_ptr iterator = b->add_iterator(); BufferView bv(b, iterator, Cwd); bv.resize(40, 8); - int times_called = 0; - bv.iter_lines([×_called](int row_offset, const Buffer::Iterator & iterator) -> bool { - EXPECT_EQ(times_called, LineNumber(iterator)); - times_called++; - return true; - }); - EXPECT_EQ(8, times_called); + int iter_count = 0; + for (auto it = bv.vert_iter(); it.is_valid(); it++) + { + EXPECT_EQ(iter_count, LineNumber(it.iterator())); + iter_count++; + } + EXPECT_EQ(8, iter_count); EXPECT_EQ(0, bv.cursor_screen_row()); EXPECT_EQ(0, bv.cursor_screen_column()); EXPECT_EQ(0, bv.cursor_virtual_column()); @@ -97,15 +97,15 @@ TEST(BufferViewTest, iterates_through_screen_lines_with_wrapping) std::shared_ptr iterator = b->add_iterator(); BufferView bv(b, iterator, Cwd); bv.resize(3, 10); - int times_called = 0; + int iter_count = 0; int expected_row_offsets[] = {0, 1, 2, 4, 5, 6, 7}; - bv.iter_lines([×_called, &expected_row_offsets](int row_offset, const Buffer::Iterator & iterator) -> bool { - EXPECT_EQ(times_called, LineNumber(iterator)); - EXPECT_EQ(expected_row_offsets[times_called], row_offset); - times_called++; - return true; - }); - EXPECT_EQ(7, times_called); + for (auto it = bv.vert_iter(); it.is_valid(); it++) + { + EXPECT_EQ(iter_count, LineNumber(it.iterator())); + EXPECT_EQ(expected_row_offsets[iter_count], it.row_offset()); + iter_count++; + } + EXPECT_EQ(7, iter_count); EXPECT_EQ(0, bv.cursor_screen_row()); EXPECT_EQ(0, bv.cursor_screen_column()); EXPECT_EQ(0, bv.cursor_virtual_column()); @@ -120,15 +120,15 @@ TEST(BufferViewTest, fills_view_with_last_lines_of_buffer_when_cursor_warps_to_l { } bv.resize(40, 3); - int times_called = 0; + int iter_count = 0; int expected_row_offsets[] = {0, 1, 2}; - bv.iter_lines([×_called, &expected_row_offsets](int row_offset, const Buffer::Iterator & iterator) -> bool { - EXPECT_EQ(10 + times_called, LineNumber(iterator)); - EXPECT_EQ(expected_row_offsets[times_called], row_offset); - times_called++; - return true; - }); - EXPECT_EQ(3, times_called); + for (auto it = bv.vert_iter(); it.is_valid(); it++) + { + EXPECT_EQ(10 + iter_count, LineNumber(it.iterator())); + EXPECT_EQ(expected_row_offsets[iter_count], it.row_offset()); + iter_count++; + } + EXPECT_EQ(3, iter_count); EXPECT_EQ(2, bv.cursor_screen_row()); EXPECT_EQ(0, bv.cursor_screen_column()); EXPECT_EQ(0, bv.cursor_virtual_column());