1
1
mirror of https://github.com/mawww/kakoune.git synced 2024-12-25 04:24:48 +03:00

Remove use of 'offset' in buffer iterators, lines are just String

No need to maintain line offsets anymore.
This commit is contained in:
Maxime Coste 2014-05-24 17:08:01 +01:00
parent 95200d1de1
commit b6b646e9a2
6 changed files with 74 additions and 80 deletions

View File

@ -30,13 +30,11 @@ Buffer::Buffer(String name, Flags flags, std::vector<String> lines,
if (lines.empty())
lines.emplace_back("\n");
ByteCount pos = 0;
m_lines.reserve(lines.size());
for (auto& line : lines)
{
kak_assert(not line.empty() and line.back() == '\n');
m_lines.emplace_back(Line{ pos, std::move(line) });
pos += m_lines.back().length();
m_lines.emplace_back(std::move(line));
}
m_changes.push_back({ Change::Insert, {0,0}, line_count(), true });
@ -83,13 +81,11 @@ void Buffer::reload(std::vector<String> lines, time_t fs_timestamp)
if (lines.empty())
lines.emplace_back("\n");
ByteCount pos = 0;
m_lines.reserve(lines.size());
for (auto& line : lines)
{
kak_assert(not line.empty() and line.back() == '\n');
m_lines.emplace_back(Line{ pos, std::move(line) });
pos += m_lines.back().length();
m_lines.emplace_back(std::move(line));
}
m_fs_timestamp = fs_timestamp;
@ -135,7 +131,7 @@ ByteCoord Buffer::clamp(ByteCoord coord) const
ByteCoord Buffer::offset_coord(ByteCoord coord, CharCount offset)
{
auto& line = m_lines[coord.line].content;
auto& line = m_lines[coord.line];
auto character = std::max(0_char, std::min(line.char_count_to(coord.column) + offset,
line.char_length() - 1));
return {coord.line, line.byte_count_to(character)};
@ -143,9 +139,9 @@ ByteCoord Buffer::offset_coord(ByteCoord coord, CharCount offset)
ByteCoord Buffer::offset_coord(ByteCoord coord, LineCount offset)
{
auto character = m_lines[coord.line].content.char_count_to(coord.column);
auto character = m_lines[coord.line].char_count_to(coord.column);
auto line = Kakoune::clamp(coord.line + offset, 0_line, line_count()-1);
auto& content = m_lines[line].content;
auto& content = m_lines[line];
character = std::max(0_char, std::min(character, content.char_length() - 2));
return {line, content.byte_count_to(character)};
@ -162,7 +158,7 @@ String Buffer::string(ByteCoord begin, ByteCoord end) const
ByteCount count = -1;
if (line == end.line)
count = end.column - start;
res += m_lines[line].content.substr(start, count);
res += m_lines[line].substr(start, count);
}
return res;
}
@ -423,14 +419,11 @@ bool Buffer::redo()
void Buffer::check_invariant() const
{
#ifdef KAK_DEBUG
ByteCount start = 0;
kak_assert(not m_lines.empty());
for (auto& line : m_lines)
{
kak_assert(line.start == start);
kak_assert(line.length() > 0);
kak_assert(line.content.back() == '\n');
start += line.length();
kak_assert(line.back() == '\n');
}
#endif
}
@ -442,12 +435,6 @@ ByteCoord Buffer::do_insert(ByteCoord pos, const String& content)
if (content.empty())
return pos;
ByteCount offset = this->offset(pos);
// all following lines advanced by length
for (LineCount i = pos.line+1; i < line_count(); ++i)
m_lines[i].start += content.length();
ByteCoord begin;
ByteCoord end;
bool at_end = false;
@ -460,23 +447,23 @@ ByteCoord Buffer::do_insert(ByteCoord pos, const String& content)
{
if (content[i] == '\n')
{
m_lines.push_back({ offset + start, content.substr(start, i + 1 - start) });
m_lines.push_back(content.substr(start, i + 1 - start));
start = i + 1;
}
}
if (start != content.length())
m_lines.push_back({ offset + start, content.substr(start) });
m_lines.push_back(content.substr(start));
begin = pos.column == 0 ? pos : ByteCoord{ pos.line + 1, 0 };
end = ByteCoord{ line_count()-1, m_lines.back().length() };
end = ByteCoord{ line_count(), 0 };
at_end = true;
}
else
{
String prefix = m_lines[pos.line].content.substr(0, pos.column);
String suffix = m_lines[pos.line].content.substr(pos.column);
String prefix = m_lines[pos.line].substr(0, pos.column);
String suffix = m_lines[pos.line].substr(pos.column);
std::vector<Line> new_lines;
std::vector<String> new_lines;
ByteCount start = 0;
for (ByteCount i = 0; i < content.length(); ++i)
@ -487,18 +474,17 @@ ByteCoord Buffer::do_insert(ByteCoord pos, const String& content)
if (start == 0)
{
line_content = prefix + line_content;
new_lines.push_back({ offset + start - prefix.length(),
std::move(line_content) });
new_lines.push_back(std::move(line_content));
}
else
new_lines.push_back({ offset + start, std::move(line_content) });
new_lines.push_back(std::move(line_content));
start = i + 1;
}
}
if (start == 0)
new_lines.push_back({ offset + start - prefix.length(), prefix + content + suffix });
new_lines.push_back(prefix + content + suffix);
else if (start != content.length() or not suffix.empty())
new_lines.push_back({ offset + start, content.substr(start) + suffix });
new_lines.push_back(content.substr(start) + suffix);
LineCount last_line = pos.line + new_lines.size() - 1;
@ -520,10 +506,9 @@ ByteCoord Buffer::do_erase(ByteCoord begin, ByteCoord end)
{
kak_assert(is_valid(begin));
kak_assert(is_valid(end));
const ByteCount length = distance(begin, end);
String prefix = m_lines[begin.line].content.substr(0, begin.column);
String suffix = m_lines[end.line].content.substr(end.column);
Line new_line = { m_lines[begin.line].start, prefix + suffix };
String prefix = m_lines[begin.line].substr(0, begin.column);
String suffix = m_lines[end.line].substr(end.column);
String new_line = prefix + suffix;
ByteCoord next;
if (new_line.length() != 0)
@ -538,9 +523,6 @@ ByteCoord Buffer::do_erase(ByteCoord begin, ByteCoord end)
next = is_end(begin) ? end_coord() : ByteCoord{begin.line, 0};
}
for (LineCount i = begin.line+1; i < line_count(); ++i)
m_lines[i].start -= length;
m_changes.push_back({ Change::Erase, begin, end, is_end(begin) });
return next;
}
@ -626,17 +608,38 @@ void Buffer::notify_saved()
ByteCoord Buffer::advance(ByteCoord coord, ByteCount count) const
{
ByteCount off = Kakoune::clamp(offset(coord) + count, 0_byte, byte_count());
auto it = std::upper_bound(m_lines.begin(), m_lines.end(), off,
[](ByteCount s, const Line& l) { return s < l.start; }) - 1;
return { LineCount{ (int)(it - m_lines.begin()) }, off - it->start };
if (count > 0)
{
auto line = coord.line;
count += coord.column;
while (count >= m_lines[line].length())
{
count -= m_lines[line++].length();
if (line == line_count())
return end_coord();
}
return { line, count };
}
else if (count < 0)
{
auto line = coord.line;
count += coord.column;
while (count < 0)
{
count += m_lines[--line].length();
if (line < 0)
return {0, 0};
}
return { line, count };
}
return coord;
}
ByteCoord Buffer::char_next(ByteCoord coord) const
{
if (coord.column < m_lines[coord.line].length() - 1)
{
auto& line = m_lines[coord.line].content;
auto& line = m_lines[coord.line];
coord.column += utf8::codepoint_size(line.begin() + (int)coord.column);
// Handle invalid utf-8
if (coord.column >= line.length())
@ -667,7 +670,7 @@ ByteCoord Buffer::char_prev(ByteCoord coord) const
}
else
{
auto& line = m_lines[coord.line].content;
auto& line = m_lines[coord.line];
coord.column = (int)(utf8::character_start(line.begin() + (int)coord.column - 1) - line.begin());
}
return coord;

View File

@ -105,7 +105,6 @@ public:
String string(ByteCoord begin, ByteCoord end) const;
char byte_at(ByteCoord c) const;
ByteCount offset(ByteCoord c) const;
ByteCount distance(ByteCoord begin, ByteCoord end) const;
ByteCoord advance(ByteCoord coord, ByteCount count) const;
ByteCoord next(ByteCoord coord) const;
@ -124,11 +123,10 @@ public:
BufferIterator begin() const;
BufferIterator end() const;
ByteCount byte_count() const;
LineCount line_count() const;
const String& operator[](LineCount line) const
{ return m_lines[line].content; }
{ return m_lines[line]; }
// returns an iterator at given coordinates. clamp line_and_column
BufferIterator iterator_at(ByteCoord coord) const;
@ -177,20 +175,13 @@ private:
void on_option_changed(const Option& option) override;
struct Line
struct LineList : std::vector<String>
{
ByteCount start;
String content;
String& operator[](LineCount line)
{ return std::vector<String>::operator[]((int)line); }
ByteCount length() const { return content.length(); }
};
struct LineList : std::vector<Line>
{
Line& operator[](LineCount line)
{ return std::vector<Line>::operator[]((int)line); }
const Line& operator[](LineCount line) const
{ return std::vector<Line>::operator[]((int)line); }
const String& operator[](LineCount line) const
{ return std::vector<String>::operator[]((int)line); }
};
LineList m_lines;

View File

@ -9,7 +9,7 @@ namespace Kakoune
inline char Buffer::byte_at(ByteCoord c) const
{
kak_assert(c.line < line_count() and c.column < m_lines[c.line].length());
return m_lines[c.line].content[c.column];
return m_lines[c.line][c.column];
}
inline ByteCoord Buffer::next(ByteCoord coord) const
@ -40,14 +40,19 @@ inline ByteCoord Buffer::prev(ByteCoord coord) const
inline ByteCount Buffer::distance(ByteCoord begin, ByteCoord end) const
{
return offset(end) - offset(begin);
}
inline ByteCount Buffer::offset(ByteCoord c) const
{
if (c.line == line_count())
return m_lines.back().start + m_lines.back().length();
return m_lines[c.line].start + c.column;
if (begin > end)
return -distance(end, begin);
ByteCount res = 0;
for (LineCount l = begin.line; l <= end.line; ++l)
{
ByteCount len = m_lines[l].length();
res += len;
if (l == begin.line)
res -= begin.column;
if (l == end.line)
res -= len - end.column;
}
return res;
}
inline bool Buffer::is_valid(ByteCoord c) const
@ -77,13 +82,6 @@ inline BufferIterator Buffer::end() const
return BufferIterator(*this, { line_count() - 1, m_lines.back().length() });
}
inline ByteCount Buffer::byte_count() const
{
if (m_lines.empty())
return 0;
return m_lines.back().start + m_lines.back().length();
}
inline LineCount Buffer::line_count() const
{
return LineCount(m_lines.size());

View File

@ -189,14 +189,13 @@ void InsertCompleter::select(int offset)
const auto& cursor_pos = selections.main().cursor();
const auto prefix_len = buffer.distance(m_completions.begin, cursor_pos);
const auto suffix_len = std::max(0_byte, buffer.distance(cursor_pos, m_completions.end));
const auto buffer_len = buffer.byte_count();
auto ref = buffer.string(m_completions.begin, m_completions.end);
for (auto& sel : selections)
{
auto offset = buffer.offset(sel.cursor());
auto pos = buffer.iterator_at(sel.cursor());
if (offset >= prefix_len and offset + suffix_len < buffer_len and
const auto& cursor = sel.cursor();
auto pos = buffer.iterator_at(cursor);
if (cursor.column >= prefix_len and (pos + suffix_len) != buffer.end() and
std::equal(ref.begin(), ref.end(), pos - prefix_len))
{
pos = buffer.erase(pos - prefix_len, pos + suffix_len);

View File

@ -288,7 +288,7 @@ Selection select_whole_paragraph(const Buffer& buffer, const Selection& selectio
{
BufferIterator first = buffer.iterator_at(selection.cursor());
if (not (flags & ObjectFlags::ToEnd) and buffer.offset(first.coord()) > 1 and
if (not (flags & ObjectFlags::ToEnd) and first.coord() > ByteCoord{0,1} and
*(first-1) == '\n' and *(first-2) == '\n')
--first;
else if ((flags & ObjectFlags::ToEnd) and

View File

@ -27,6 +27,9 @@ void test_buffer()
kak_assert(pos.coord() == ByteCoord{1 COMMA 0});
buffer.insert(pos, "tchou kanaky\n");
kak_assert(buffer.line_count() == 5);
BufferIterator pos2 = buffer.end();
pos2 -= 9;
kak_assert(*pos2 == '?');
String str = buffer.string({ 4, 1 }, buffer.next({ 4, 5 }));
kak_assert(str == "youpi");