Line.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "Line.h"
  2. Chunk::Chunk(const std::string& str)
  3. : m_data(str)
  4. {
  5. }
  6. Chunk::~Chunk()
  7. {
  8. }
  9. Line::Line(const std::string& str)
  10. {
  11. m_chunks.push_back(Chunk(str));
  12. }
  13. Line::Line(Line&& other)
  14. : m_chunks(std::move(other.m_chunks))
  15. {
  16. }
  17. Line::~Line()
  18. {
  19. }
  20. std::string Line::data() const
  21. {
  22. std::string str;
  23. for (auto& chunk : m_chunks)
  24. str += chunk.data();
  25. return str;
  26. }
  27. void Line::append(const std::string& text)
  28. {
  29. m_chunks.push_back(Chunk(text));
  30. }
  31. void Line::prepend(const std::string& text)
  32. {
  33. m_chunks.push_front(Chunk(text));
  34. }
  35. std::string Line::truncate(size_t length)
  36. {
  37. coalesce();
  38. auto remainder = data().substr(0, length);
  39. auto chop = data().substr(length, data().length() - length);
  40. m_chunks.clear();
  41. m_chunks.push_back(Chunk{ remainder });
  42. return chop;
  43. }
  44. void Line::insert(size_t index, const std::string& text)
  45. {
  46. if (index == 0) {
  47. prepend(text);
  48. return;
  49. }
  50. if (index == length()) {
  51. append(text);
  52. return;
  53. }
  54. auto chunk_address = chunk_index_for_position(index);
  55. auto chunk_index = std::get<0>(chunk_address);
  56. auto& chunk = m_chunks[chunk_index];
  57. auto index_in_chunk = std::get<1>(chunk_address);
  58. static FILE* f = fopen("log", "a");
  59. fprintf(f, "#Column:%zu, Chunk:%zu, Index:%zu\n", index, chunk_index, index_in_chunk);
  60. auto left_string = chunk.data().substr(0, index_in_chunk);
  61. auto right_string = chunk.data().substr(index_in_chunk, chunk.length() - index_in_chunk);
  62. fprintf(f, "#{\"%s\", \"%s\", \"%s\"}\n", left_string.c_str(), text.c_str(), right_string.c_str());
  63. Chunk left_chunk { left_string };
  64. Chunk mid_chunk { text };
  65. Chunk right_chunk { right_string };
  66. auto iterator = m_chunks.begin() + chunk_index;
  67. m_chunks.erase(iterator);
  68. iterator = m_chunks.begin() + chunk_index;
  69. // Note reverse insertion order!
  70. iterator = m_chunks.insert(iterator, right_chunk);
  71. iterator = m_chunks.insert(iterator, mid_chunk);
  72. iterator = m_chunks.insert(iterator, left_chunk);
  73. fflush(f);
  74. }
  75. std::tuple<size_t, size_t> Line::chunk_index_for_position(size_t position)
  76. {
  77. ASSERT(position < length());
  78. size_t seen { 0 };
  79. for (size_t i = 0; i < m_chunks.size(); ++i) {
  80. if (position < seen + m_chunks[i].length())
  81. return std::make_tuple(i, position - seen);
  82. seen += m_chunks[i].length();
  83. }
  84. ASSERT(false);
  85. return std::make_tuple(0, 0);
  86. }
  87. void Line::coalesce()
  88. {
  89. if (m_chunks.size() <= 1)
  90. return;
  91. auto contents = data();
  92. m_chunks.clear();
  93. m_chunks.push_back(Chunk{ contents });
  94. }
  95. void Line::erase(size_t column, int count)
  96. {
  97. coalesce();
  98. auto str = data();
  99. if (count < 0)
  100. str.erase(str.begin() + column + count, str.begin() + column);
  101. else
  102. str.erase(str.begin() + column, str.begin() + column + count);
  103. m_chunks.clear();
  104. m_chunks.push_back(Chunk{ str });
  105. }