#include "everything.hpp" // Get size uf a subtreap count_type Treap::get_size(line* l) { if(l == nullptr) return 0; return l->size; } string Treap::substitute_tabs(string s) { string ret = ""; for(count_type i = 0; i < s.size(); ++i) { if(s[i] == '\t') { ret += ' '; while(ret.size() % TAB_SIZE != 0) ret += ' '; } else ret += s[i]; } return ret; } // 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)) ); } 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); } // File access 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 = find(r)->text; if(substitute_tab) return substitute_tabs(line); else return line; } // Get multiple adjacent vertices count_type Treap::bulk_find(vector *vec, line *l, count_type k, count_type count) { if(l == nullptr) return count; // Wanted vertex is on the left if(k <= get_size(l->left)) { count_type r = bulk_find(vec, l->left, k, count); if(r > 0) vec->push_back(substitute_tabs(l->text)); if(r > 1) return bulk_find(vec, l->right, 0, r-1); else return 0; } // This is the wanted vertex else if(k == get_size(l->left)+1) { vec->push_back(substitute_tabs(l->text)); if(count > 1) return bulk_find(vec, l->right, 0, count-1); else return 0; } else return bulk_find(vec, l->right, k - (1+get_size(l->left)), count); } // Access multiple adjacent vertices vector Treap::bulk_get_line(count_type r, count_type count) { vector ret(0); bulk_find(&ret, root, r+1, count); return ret; } // Get how much tabs changed position on a row 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 - (i+tab_offset) % TAB_SIZE - 1; if(i + tab_offset > p.c) tab_offset -= i + tab_offset - p.c; } return tab_offset; } 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); }