148 lines
3.3 KiB
C++
148 lines
3.3 KiB
C++
#include "everything.hpp"
|
|
|
|
// 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)) );
|
|
}
|
|
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<string> *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<string> Treap::bulk_get_line(count_type r, count_type count) {
|
|
vector<string> ret(0);
|
|
bulk_find(&ret, root, r+1, count);
|
|
return ret;
|
|
}
|
|
|
|
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);
|
|
}
|