2011-10-18 00:05:06 +02:00
|
|
|
#ifndef buffer_iterator_inl_h_INCLUDED
|
|
|
|
#define buffer_iterator_inl_h_INCLUDED
|
|
|
|
|
|
|
|
#include "assert.hh"
|
|
|
|
|
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
2012-03-30 13:37:18 +02:00
|
|
|
inline BufferIterator::BufferIterator(const Buffer& buffer, BufferCoord coord)
|
|
|
|
: m_buffer(&buffer), m_coord(coord)
|
2011-10-18 00:05:06 +02:00
|
|
|
{
|
2012-03-30 13:37:18 +02:00
|
|
|
assert(is_valid());
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline const Buffer& BufferIterator::buffer() const
|
|
|
|
{
|
|
|
|
assert(m_buffer);
|
|
|
|
return *m_buffer;
|
|
|
|
}
|
|
|
|
|
2011-10-24 16:26:21 +02:00
|
|
|
inline bool BufferIterator::is_valid() const
|
|
|
|
{
|
2012-03-30 13:37:18 +02:00
|
|
|
return m_buffer and
|
|
|
|
((line() < m_buffer->line_count() and
|
2012-03-30 14:00:40 +02:00
|
|
|
column() < m_buffer->m_lines[line()].length()) or
|
2012-03-30 13:37:18 +02:00
|
|
|
((line() == m_buffer->line_count() and column() == 0)) or
|
|
|
|
(line() == m_buffer->line_count() - 1 and
|
2012-03-30 14:00:40 +02:00
|
|
|
column() == m_buffer->m_lines.back().length()));
|
2011-10-24 16:26:21 +02:00
|
|
|
}
|
|
|
|
|
2011-10-18 00:05:06 +02:00
|
|
|
inline BufferIterator& BufferIterator::operator=(const BufferIterator& iterator)
|
|
|
|
{
|
|
|
|
m_buffer = iterator.m_buffer;
|
2012-03-30 13:37:18 +02:00
|
|
|
m_coord = iterator.m_coord;
|
2011-10-18 00:05:06 +02:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool BufferIterator::operator==(const BufferIterator& iterator) const
|
|
|
|
{
|
|
|
|
assert(m_buffer == iterator.m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
return (m_coord == iterator.m_coord);
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool BufferIterator::operator!=(const BufferIterator& iterator) const
|
|
|
|
{
|
|
|
|
assert(m_buffer == iterator.m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
return (m_coord != iterator.m_coord);
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool BufferIterator::operator<(const BufferIterator& iterator) const
|
|
|
|
{
|
|
|
|
assert(m_buffer == iterator.m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
return (m_coord < iterator.m_coord);
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool BufferIterator::operator<=(const BufferIterator& iterator) const
|
|
|
|
{
|
|
|
|
assert(m_buffer == iterator.m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
return (m_coord <= iterator.m_coord);
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool BufferIterator::operator>(const BufferIterator& iterator) const
|
|
|
|
{
|
|
|
|
assert(m_buffer == iterator.m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
return (m_coord > iterator.m_coord);
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool BufferIterator::operator>=(const BufferIterator& iterator) const
|
|
|
|
{
|
|
|
|
assert(m_buffer == iterator.m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
return (m_coord >= iterator.m_coord);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferCoord measure_string(const String& string)
|
|
|
|
{
|
|
|
|
BufferCoord res;
|
|
|
|
for (auto c : string)
|
|
|
|
{
|
|
|
|
if (c == '\n')
|
|
|
|
{
|
|
|
|
++res.line;
|
|
|
|
res.column = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
++res.column;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferCoord advance(const BufferCoord& base, const BufferCoord& offset)
|
|
|
|
{
|
|
|
|
if (offset.line == 0)
|
|
|
|
return BufferCoord{base.line, base.column + offset.column};
|
|
|
|
else
|
|
|
|
return BufferCoord{base.line + offset.line, offset.column};
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void BufferIterator::update(const Modification& modification)
|
|
|
|
{
|
|
|
|
const BufferIterator& pos = modification.position;
|
|
|
|
if (*this < pos)
|
|
|
|
return;
|
|
|
|
|
|
|
|
BufferCoord measure = measure_string(modification.content);
|
|
|
|
if (modification.type == Modification::Erase)
|
|
|
|
{
|
|
|
|
BufferCoord end = advance(pos.m_coord, measure);
|
|
|
|
if (m_coord <= end)
|
|
|
|
m_coord = pos.m_coord;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_coord.line -= measure.line;
|
|
|
|
if (end.line == m_coord.line)
|
|
|
|
m_coord.column -= measure.column;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_end())
|
|
|
|
operator--();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(modification.type == Modification::Insert);
|
|
|
|
if (pos.line() == line())
|
|
|
|
{
|
|
|
|
BufferCoord end = advance(pos.m_coord, measure);
|
|
|
|
m_coord.column = end.column + column() - pos.column();
|
|
|
|
}
|
|
|
|
m_coord.line += measure.line;
|
|
|
|
}
|
|
|
|
assert(is_valid());
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferChar BufferIterator::operator*() const
|
|
|
|
{
|
|
|
|
assert(m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
return m_buffer->m_lines[line()].content[column()];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferSize BufferIterator::offset() const
|
|
|
|
{
|
|
|
|
assert(m_buffer);
|
|
|
|
return line() == 0 ? column() : m_buffer->m_lines[line()].start + column();
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferSize BufferIterator::operator-(const BufferIterator& iterator) const
|
|
|
|
{
|
|
|
|
assert(m_buffer == iterator.m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
return offset() - iterator.offset();
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferIterator BufferIterator::operator+(BufferSize size) const
|
|
|
|
{
|
|
|
|
assert(m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
if (size >= 0)
|
|
|
|
{
|
|
|
|
BufferSize o = std::min(m_buffer->length(), offset() + size);
|
|
|
|
for (int i = line() + 1; i < m_buffer->line_count(); ++i)
|
|
|
|
{
|
|
|
|
if (m_buffer->m_lines[i].start > o)
|
|
|
|
return BufferIterator(*m_buffer, { i-1, o - m_buffer->m_lines[i-1].start });
|
|
|
|
}
|
|
|
|
int last_line = m_buffer->line_count() - 1;
|
|
|
|
return BufferIterator(*m_buffer, { last_line, o - m_buffer->m_lines[last_line].start });
|
|
|
|
}
|
|
|
|
return operator-(-size);
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferIterator BufferIterator::operator-(BufferSize size) const
|
|
|
|
{
|
|
|
|
assert(m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
if (size >= 0)
|
|
|
|
{
|
|
|
|
BufferSize o = std::max(0, offset() - size);
|
|
|
|
for (int i = line(); i >= 0; --i)
|
|
|
|
{
|
|
|
|
if (m_buffer->m_lines[i].start <= o)
|
|
|
|
return BufferIterator(*m_buffer, { i, o - m_buffer->m_lines[i].start });
|
|
|
|
}
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
return operator+(-size);
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferIterator& BufferIterator::operator+=(BufferSize size)
|
|
|
|
{
|
2012-03-30 13:37:18 +02:00
|
|
|
return *this = (*this + size);
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferIterator& BufferIterator::operator-=(BufferSize size)
|
|
|
|
{
|
2012-03-30 13:37:18 +02:00
|
|
|
return *this = (*this - size);
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferIterator& BufferIterator::operator++()
|
|
|
|
{
|
|
|
|
return (*this += 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline BufferIterator& BufferIterator::operator--()
|
|
|
|
{
|
|
|
|
return (*this -= 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool BufferIterator::is_begin() const
|
|
|
|
{
|
|
|
|
assert(m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
return m_coord.line == 0 and m_coord.column == 0;
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool BufferIterator::is_end() const
|
|
|
|
{
|
|
|
|
assert(m_buffer);
|
2012-03-30 13:37:18 +02:00
|
|
|
return offset() == m_buffer->length();
|
2011-10-18 00:05:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif // buffer_iterator_inl_h_INCLUDED
|