#include "everything.hpp" // Treap representation of a file line* root; // Get size uf a subtreap count_type Treap::get_size(line* l) { if(l == nullptr) return 0; return l->size; } // Split treap by k-th element two_lines Treap::split(line *l, count_type k) { if(l == nullptr) return {nullptr, nullptr}; if(get_size(l->left) >= k) { // In the left subtree auto two = split(l->left, k); l->left = two.second; l->size -= get_size(two.first); return {two.first, l}; } else { // In the right subtree auto two = split(l->right, k - (1+get_size(l->left))); l->right = two.first; l->size -= get_size(two.second); return {l, two.second}; } } // Join two treaps line* Treap::join(line *a, line *b) { if(a == nullptr) return b; if(b == nullptr) return a; if(a->priority < b->priority) { a->size += get_size(b); a->right = join(a->right, b); return a; } else { b->size += get_size(a); b->left = join(a, b->left); return b; } } // Find k-th line of file line* Treap::find(line* l, count_type k) { if(l == nullptr) return nullptr; if(k <= get_size(l->left)) return find(l->left, k); else if(k == get_size(l->left)+1) return l; else return find(l->right, k - (1+get_size(l->left)) ); } // File access line* Treap::find(count_type k) { if(k >= root->size) return nullptr; // Don't find index k, but k-th line -> +1 return find(root, k+1); } void Treap::clear() { while(size() > 0) { auto two = split(root, 1); root = two.second; delete two.first; } } // Line insert void Treap::insert(count_type k, string s) { line *l = new line(rand(), s); if(root == nullptr) { root = l; return; } auto two = split(root, k); two.first = join(two.first, l); root = join(two); } // Line removal void Treap::remove(count_type k) { auto two = split(root, k+1); auto first_split = split(two.first, k); delete first_split.second; two.first = first_split.first; root = join(two); } // Accessing the file string Treap::get_line(count_type r, bool substitute_tab) { string line = get(r); if(!substitute_tab) return line; string ret = ""; for(count_type i = 0; i < line.size(); ++i) { if(line[i] == '\t') for(int j = 0; j < TAB_SIZE; j++) ret += ' '; else ret += line[i]; } return ret; } // TODO tabs are a grid, not just N tabs count_type Treap::get_tab_offset(position p) { count_type tab_offset = 0; string line = get_line(p.r, false); for(count_type i = 0; i + tab_offset < p.c; ++i) { if(line[i] == '\t') tab_offset += TAB_SIZE - 1; if(i + tab_offset > p.c) tab_offset -= i + tab_offset - p.c; } return tab_offset; } void Treap::set(position p, char ch) { find(p.r)->text[p.c-get_tab_offset(p)] = ch; } void Treap::insert(position p, string t) { find(p.r)->text.insert(p.c-get_tab_offset(p), t); } void Treap::remove(position p, count_type len) { find(p.r)->text.erase(p.c-get_tab_offset(p),len); } // Split line void Treap::split_line(position p) { string line = get_line(p.r); string newline = line.substr(p.c, line.size()); remove(p, line.size()-p.c); insert(p.r+1, newline); }