From 02b33c7d8fd0167a4cbca78be26ed32e042c7370 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 3 Jun 2013 18:56:48 +0200 Subject: [PATCH] Buffer: add methods for char access instead of byte access --- src/buffer.cc | 55 ++++++++++++++++++++++++++++++++++++-- src/buffer.hh | 10 ++++++- src/buffer_iterator.inl.hh | 4 +-- 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/buffer.cc b/src/buffer.cc index a06d9783..4738cc47 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -88,7 +88,7 @@ bool Buffer::set_name(String name) BufferIterator Buffer::iterator_at(const BufferCoord& coord) const { - return BufferIterator(*this, clamp(coord)); + return is_end(coord) ? end() : BufferIterator(*this, clamp(coord)); } ByteCount Buffer::line_length(LineCount line) const @@ -634,6 +634,11 @@ BufferCoord Buffer::advance(BufferCoord coord, ByteCount count) const return { LineCount{ (int)(it - m_lines.begin()) }, off - it->start }; } +BufferCoord Buffer::char_advance(BufferCoord coord, CharCount count) const +{ + return utf8::advance(iterator_at(coord), end(), count); +} + BufferCoord Buffer::next(BufferCoord coord) const { if (coord.column < m_lines[coord.line].length() - 1) @@ -648,6 +653,23 @@ BufferCoord Buffer::next(BufferCoord coord) const return coord; } +BufferCoord Buffer::char_next(BufferCoord coord) const +{ + if (coord.column < m_lines[coord.line].length() - 1) + { + auto& line = m_lines[coord.line].content; + coord.column += utf8::codepoint_size(line.begin() + (int)coord.column); + } + else if (coord.line == m_lines.size() - 1) + coord.column = m_lines.back().length(); + else + { + ++coord.line; + coord.column = 0; + } + return coord; +} + BufferCoord Buffer::prev(BufferCoord coord) const { if (coord.column == 0) @@ -663,11 +685,34 @@ BufferCoord Buffer::prev(BufferCoord coord) const return coord; } +BufferCoord Buffer::char_prev(BufferCoord coord) const +{ + kak_assert(is_valid(coord)); + if (is_end(coord)) + return coord = {(int)m_lines.size()-1, m_lines.back().length() - 1}; + else if (coord.column == 0) + { + if (coord.line > 0) + coord = { coord.line-1, m_lines[coord.line-1].length() - 1 }; + } + else + { + auto& line = m_lines[coord.line].content; + coord.column = (int)(utf8::character_start(line.begin() + (int)coord.column - 1) - line.begin()); + } + return coord; +} + ByteCount Buffer::distance(const BufferCoord& begin, const BufferCoord& end) const { return offset(end) - offset(begin); } +CharCount Buffer::char_distance(const BufferCoord& begin, const BufferCoord& end) const +{ + return utf8::distance(iterator_at(begin), iterator_at(end)); +} + ByteCount Buffer::offset(const BufferCoord& c) const { if (c.line == line_count()) @@ -688,10 +733,16 @@ bool Buffer::is_end(const BufferCoord& c) const (c.line == line_count() - 1 and c.column == m_lines.back().length()); } -char Buffer::at(const BufferCoord& c) const +char Buffer::byte_at(const BufferCoord& c) const { kak_assert(c.line < line_count() and c.column < m_lines[c.line].length()); return m_lines[c.line].content[c.column]; } +Codepoint Buffer::char_at(const BufferCoord& c) const +{ + kak_assert(c.line < line_count() and c.column < m_lines[c.line].length()); + return utf8::codepoint(m_lines[c.line].content.begin() + (int)c.column); +} + } diff --git a/src/buffer.hh b/src/buffer.hh index 08a29aee..a1ea0dbe 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -120,12 +120,20 @@ public: bool redo(); String string(const BufferCoord& begin, const BufferCoord& end) const; - char at(const BufferCoord& c) const; + + char byte_at(const BufferCoord& c) const; ByteCount offset(const BufferCoord& c) const; ByteCount distance(const BufferCoord& begin, const BufferCoord& end) const; BufferCoord advance(BufferCoord coord, ByteCount count) const; BufferCoord next(BufferCoord coord) const; BufferCoord prev(BufferCoord coord) const; + + Codepoint char_at(const BufferCoord& c) const; + CharCount char_distance(const BufferCoord& begin, const BufferCoord& end) const; + BufferCoord char_advance(BufferCoord coord, CharCount count) const; + BufferCoord char_next(BufferCoord coord) const; + BufferCoord char_prev(BufferCoord coord) const; + bool is_valid(const BufferCoord& c) const; bool is_end(const BufferCoord& c) const; diff --git a/src/buffer_iterator.inl.hh b/src/buffer_iterator.inl.hh index 1d3953ba..6afc4342 100644 --- a/src/buffer_iterator.inl.hh +++ b/src/buffer_iterator.inl.hh @@ -59,12 +59,12 @@ inline bool BufferIterator::operator>=(const BufferIterator& iterator) const inline char BufferIterator::operator*() const { - return m_buffer->at(m_coord); + return m_buffer->byte_at(m_coord); } inline char BufferIterator::operator[](size_t n) const { - return m_buffer->at(m_buffer->advance(m_coord, n)); + return m_buffer->byte_at(m_buffer->advance(m_coord, n)); } inline size_t BufferIterator::operator-(const BufferIterator& iterator) const