Split some PieceTable::Cursor functionality into PieceTable::Iterator

This commit is contained in:
Josh Holtrop 2016-08-27 15:20:08 -04:00
parent f659c14242
commit d6b3810a3c
2 changed files with 159 additions and 71 deletions

View File

@ -31,16 +31,89 @@ std::shared_ptr<PieceTable::Cursor> PieceTable::add_cursor()
{
auto cursor = std::make_shared<Cursor>();
cursor->piece_table = this;
cursor->piece = start_piece->next;
cursor->line_number = 0u;
cursor->offset = 0u;
cursor->iterator.piece_table = this;
cursor->iterator.piece = start_piece->next;
cursor->iterator.offset = 0u;
m_cursors.push_back(cursor);
return cursor;
}
uint8_t PieceTable::Iterator::num_bytes_in_code_point() const
{
if (offset >= piece->length)
{
return 0u;
}
else
{
return Encoding::num_bytes_in_code_point(piece_table->encoding, &piece->start[offset]);
}
}
void PieceTable::Iterator::go_next_position()
{
uint8_t code_point_size = num_bytes_in_code_point();
if ((offset + code_point_size) >= piece->length)
{
go_next_piece();
return;
}
offset += code_point_size;
}
void PieceTable::Iterator::go_prev_position()
{
if (offset > 0)
{
offset = Encoding::beginning_of_code_point(piece_table->encoding, &piece->start[offset - 1u]) - piece->start;
}
else if (piece != piece_table->start_piece)
{
piece = piece->prev;
if (piece->length > 0u)
{
offset = Encoding::beginning_of_code_point(piece_table->encoding, &piece->start[piece->length - 1u]) - piece->start;
}
else
{
offset = 0u;
}
}
}
void PieceTable::Iterator::go_end_of_piece()
{
if (piece->length > 0u)
{
offset = Encoding::beginning_of_code_point(piece_table->encoding, &piece->start[piece->length - 1u]) - piece->start;
}
else
{
offset = 0u;
}
}
void PieceTable::Iterator::go_next_piece()
{
if (piece != piece_table->end_piece)
{
piece = piece->next;
offset = 0u;
}
}
void PieceTable::Iterator::go_prev_piece()
{
if (piece != piece_table->start_piece)
{
piece = piece->prev;
offset = 0u;
}
}
#if 0
uint32_t PieceTable::Cursor::column() const
{
/* TODO: support tabs */
@ -58,119 +131,104 @@ uint32_t PieceTable::Cursor::column() const
}
return c;
}
#endif
void PieceTable::Cursor::go_start_of_line()
{
while ((!piece->prev->eol()) && (piece->prev != piece_table->start_piece))
while (iterator.valid() && (!iterator.piece->prev->eol()))
{
piece = piece->prev;
iterator.go_prev_piece();
}
offset = 0u;
}
void PieceTable::Cursor::go_end_of_line()
{
/* TODO: Use Encoding */
while ((!piece->eol()) && (piece->next != piece_table->end_piece))
while (iterator.valid() && (!iterator.piece->eol()))
{
piece = piece->next;
iterator.go_next_piece();
}
offset = (piece->length > 0u) ? piece->length - 1u : 0u;
iterator.go_end_of_piece();
}
bool PieceTable::Cursor::go_up(int n)
{
/* TODO: Use Encoding */
/* TODO: support tabs */
/* TODO: support n */
Piece * p = prev_line();
if (p == nullptr)
{
return false;
}
iterator.piece = p;
iterator.offset = 0u;
#if 0
uint32_t current_column = column();
piece = p;
offset = 0u;
line_number--;
forward_to_column(current_column);
#endif
return true;
}
bool PieceTable::Cursor::go_down(int n)
{
/* TODO: Use Encoding */
/* TODO: support tabs */
/* TODO: support n */
Piece * p = next_line();
if (p == nullptr)
{
return false;
}
iterator.piece = p;
iterator.offset = 0u;
#if 0
uint32_t current_column = column();
piece = p;
offset = 0u;
line_number++;
forward_to_column(current_column);
#endif
return true;
}
bool PieceTable::Cursor::go_left(int n)
{
/* TODO: Use Encoding */
/* TODO: support tabs */
/* TODO: support n */
if (offset > 0)
{
offset--;
}
else if ((piece->prev != piece_table->start_piece) &&
(!piece->prev->eol()))
{
piece = piece->prev;
offset = piece->length - 1u;
}
else
if (is_start_of_line())
{
return false;
}
iterator.go_prev_position();
return true;
}
bool PieceTable::Cursor::go_right(int n)
{
/* TODO: Use Encoding */
/* TODO: support tabs */
/* TODO: support n */
if (offset < piece->length - 1u)
{
offset++;
}
else if ((piece->next != piece_table->end_piece) &&
(!piece->eol()))
{
piece = piece->next;
offset = 0u;
}
else
if (is_end_of_line())
{
return false;
}
iterator.go_next_position();
return true;
}
bool PieceTable::Cursor::is_start_of_line()
{
return iterator.valid() &&
(iterator.offset == 0u) &&
(iterator.piece->prev->eol());
}
bool PieceTable::Cursor::is_end_of_line()
{
return iterator.valid() &&
((iterator.offset + iterator.num_bytes_in_code_point()) >= iterator.piece->length) &&
iterator.piece->eol();
}
PieceTable::Piece * PieceTable::Cursor::prev_line() const
{
Piece * p = piece;
while ((!p->prev->eol()) && (p->prev != piece_table->start_piece))
Piece * p = iterator.piece;
while ((!p->prev->eol()) && (p->prev != iterator.piece_table->start_piece))
{
p = p->prev;
}
if (p->prev == piece_table->start_piece)
if (p->prev == iterator.piece_table->start_piece)
{
return nullptr;
}
p = p->prev;
while ((!p->prev->eol()) && (p->prev != piece_table->start_piece))
while ((!p->prev->eol()) && (p->prev != iterator.piece_table->start_piece))
{
p = p->prev;
}
@ -179,23 +237,24 @@ PieceTable::Piece * PieceTable::Cursor::prev_line() const
PieceTable::Piece * PieceTable::Cursor::next_line() const
{
Piece * p = piece;
while ((!p->eol()) && (p->next != piece_table->end_piece))
Piece * p = iterator.piece;
while ((!p->eol()) && (p->next != iterator.piece_table->end_piece))
{
p = p->next;
}
if (p->next == piece_table->end_piece)
if (p->next == iterator.piece_table->end_piece)
{
return nullptr;
}
p = p->next;
while ((!p->eol()) && (p->next != piece_table->end_piece))
while ((!p->eol()) && (p->next != iterator.piece_table->end_piece))
{
p = p->next;
}
return p;
}
#if 0
void PieceTable::Cursor::forward_to_column(uint32_t c)
{
uint32_t current_column = column();
@ -214,3 +273,4 @@ void PieceTable::Cursor::forward_to_column(uint32_t c)
diff = new_diff;
}
}
#endif

View File

@ -48,7 +48,7 @@ public:
void toggle_eol() { flags ^= EOL_FLAG; }
};
struct Cursor
struct Iterator
{
/** The piece table the cursor belongs to. */
PieceTable * piece_table;
@ -59,23 +59,49 @@ public:
/** Byte offset within the piece. */
uint32_t offset;
/** Line number the cursor is on (0 based). */
uint32_t line_number;
/** Get the character pointed to by the cursor. */
uint32_t operator*() const
{
if (has_char())
{
return Encoding::decode(piece_table->encoding, &piece->start[offset]);
}
else
{
return 0xFFFFFFFFu;
}
}
uint8_t num_bytes_in_code_point() const;
void go_next_position();
void go_prev_position();
void go_end_of_piece();
void go_next_piece();
void go_prev_piece();
bool valid() const
{
return (piece != piece_table->start_piece) &&
(piece != piece_table->end_piece);
}
bool has_char() const
{
return valid() && (offset < piece->length);
}
};
struct Cursor
{
Iterator iterator;
/** Get the character pointed to by the cursor. */
uint32_t operator*() const
{
return Encoding::decode(piece_table->encoding, &piece->start[offset]);
return *iterator;
}
/**
* Get the screen column of the cursor (taking into account tabs).
*
* This function will return 0 only if the cursor is on an empty line.
* The first column of a line with at least one character is column 1.
*/
uint32_t column() const;
void go_start_of_line();
void go_end_of_line();
bool go_up(int n = 1);
@ -84,6 +110,8 @@ public:
bool go_right(int n = 1);
protected:
bool is_start_of_line();
bool is_end_of_line();
Piece * prev_line() const;
Piece * next_line() const;
void forward_to_column(uint32_t c);