123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- #include "Line.h"
- Chunk::Chunk(const std::string& str)
- : m_data(str)
- {
- }
- Chunk::~Chunk()
- {
- }
- Line::Line(const std::string& str)
- {
- m_chunks.push_back(Chunk(str));
- }
- Line::Line(Line&& other)
- : m_chunks(std::move(other.m_chunks))
- {
- }
- Line::~Line()
- {
- }
- std::string Line::data() const
- {
- std::string str;
- for (auto& chunk : m_chunks)
- str += chunk.data();
- return str;
- }
- void Line::append(const std::string& text)
- {
- m_chunks.push_back(Chunk(text));
- }
- void Line::prepend(const std::string& text)
- {
- m_chunks.push_front(Chunk(text));
- }
- std::string Line::truncate(size_t length)
- {
- coalesce();
- auto remainder = data().substr(0, length);
- auto chop = data().substr(length, data().length() - length);
- m_chunks.clear();
- m_chunks.push_back(Chunk{ remainder });
- return chop;
- }
- void Line::insert(size_t index, const std::string& text)
- {
- if (index == 0) {
- prepend(text);
- return;
- }
- if (index == length()) {
- append(text);
- return;
- }
- auto chunk_address = chunk_index_for_position(index);
- auto chunk_index = std::get<0>(chunk_address);
- auto& chunk = m_chunks[chunk_index];
- auto index_in_chunk = std::get<1>(chunk_address);
- static FILE* f = fopen("log", "a");
- fprintf(f, "#Column:%zu, Chunk:%zu, Index:%zu\n", index, chunk_index, index_in_chunk);
- auto left_string = chunk.data().substr(0, index_in_chunk);
- auto right_string = chunk.data().substr(index_in_chunk, chunk.length() - index_in_chunk);
- fprintf(f, "#{\"%s\", \"%s\", \"%s\"}\n", left_string.c_str(), text.c_str(), right_string.c_str());
- Chunk left_chunk { left_string };
- Chunk mid_chunk { text };
- Chunk right_chunk { right_string };
- auto iterator = m_chunks.begin() + chunk_index;
- m_chunks.erase(iterator);
- iterator = m_chunks.begin() + chunk_index;
- // Note reverse insertion order!
- iterator = m_chunks.insert(iterator, right_chunk);
- iterator = m_chunks.insert(iterator, mid_chunk);
- iterator = m_chunks.insert(iterator, left_chunk);
- fflush(f);
- }
- std::tuple<size_t, size_t> Line::chunk_index_for_position(size_t position)
- {
- ASSERT(position < length());
- size_t seen { 0 };
- for (size_t i = 0; i < m_chunks.size(); ++i) {
- if (position < seen + m_chunks[i].length())
- return std::make_tuple(i, position - seen);
- seen += m_chunks[i].length();
- }
- ASSERT(false);
- return std::make_tuple(0, 0);
- }
- void Line::coalesce()
- {
- if (m_chunks.size() <= 1)
- return;
- auto contents = data();
- m_chunks.clear();
- m_chunks.push_back(Chunk{ contents });
- }
- void Line::erase(size_t column, int count)
- {
- coalesce();
- auto str = data();
- if (count < 0)
- str.erase(str.begin() + column + count, str.begin() + column);
- else
- str.erase(str.begin() + column, str.begin() + column + count);
- m_chunks.clear();
- m_chunks.push_back(Chunk{ str });
- }
|