Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'marker-index/master'
Browse files Browse the repository at this point in the history
Signed-off-by: Max Brunsfeld <maxbrunsfeld@github.com>
  • Loading branch information
Nathan Sobo authored and Max Brunsfeld committed Dec 19, 2016
2 parents 509d163 + 2e89712 commit b19b011
Show file tree
Hide file tree
Showing 14 changed files with 1,897 additions and 0 deletions.
1 change: 1 addition & 0 deletions .npmignore
@@ -1,2 +1,3 @@
test
build
.gitignore
4 changes: 4 additions & 0 deletions binding.gyp
Expand Up @@ -7,6 +7,7 @@
],
"sources": [
"src/bindings/binding.cc"
"src/bindings/marker-index-wrapper.cc",
],
"include_dirs": [
"src/core",
Expand All @@ -20,6 +21,9 @@
"src/core/patch.cc",
"src/core/point.cc",
"src/core/text.cc",
"src/core/iterator.cc",
"src/core/marker-index.cc",
"src/core/node.cc",
]
},
],
Expand Down
348 changes: 348 additions & 0 deletions src/bindings/marker-index-wrapper.cc

Large diffs are not rendered by default.

347 changes: 347 additions & 0 deletions src/core/iterator.cc
@@ -0,0 +1,347 @@
#include <unordered_set>
#include <vector>
#include "iterator.h"
#include "marker-index.h"
#include "range.h"

using std::unordered_map;
using std::unordered_set;

Iterator::Iterator(MarkerIndex *marker_index) :
marker_index {marker_index},
current_node {nullptr} {}

void Iterator::Reset() {
current_node = marker_index->root;
if (current_node) {
current_node_position = current_node->left_extent;
}
left_ancestor_position = Point(0, 0);
right_ancestor_position = Point::Max();
left_ancestor_position_stack.clear();
right_ancestor_position_stack.clear();
}

Node* Iterator::InsertMarkerStart(const MarkerId &id, const Point &start_position, const Point &end_position) {
Reset();

if (!current_node) {
return marker_index->root = new Node(nullptr, start_position);
}

while (true) {
switch (start_position.Compare(current_node_position)) {
case 0:
MarkRight(id, start_position, end_position);
return current_node;
case -1:
MarkRight(id, start_position, end_position);
if (current_node->left) {
DescendLeft();
break;
} else {
InsertLeftChild(start_position);
DescendLeft();
MarkRight(id, start_position, end_position);
return current_node;
}
case 1:
if (current_node->right) {
DescendRight();
break;
} else {
InsertRightChild(start_position);
DescendRight();
MarkRight(id, start_position, end_position);
return current_node;
}
}
}
}

Node* Iterator::InsertMarkerEnd(const MarkerId &id, const Point &start_position, const Point &end_position) {
Reset();

if (!current_node) {
return marker_index->root = new Node(nullptr, end_position);
}

while (true) {
switch (end_position.Compare(current_node_position)) {
case 0:
MarkLeft(id, start_position, end_position);
return current_node;
case -1:
if (current_node->left) {
DescendLeft();
break;
} else {
InsertLeftChild(end_position);
DescendLeft();
MarkLeft(id, start_position, end_position);
return current_node;
}
case 1:
MarkLeft(id, start_position, end_position);
if (current_node->right) {
DescendRight();
break;
} else {
InsertRightChild(end_position);
DescendRight();
MarkLeft(id, start_position, end_position);
return current_node;
}
}
}
}

Node* Iterator::InsertSpliceBoundary(const Point &position, bool is_insertion_end) {
Reset();

while (true) {
int comparison = position.Compare(current_node_position);
if (comparison == 0 && !is_insertion_end) {
return current_node;
} else if (comparison < 0) {
if (current_node->left) {
DescendLeft();
} else {
InsertLeftChild(position);
return current_node->left;
}
} else { // comparison > 0
if (current_node->right) {
DescendRight();
} else {
InsertRightChild(position);
return current_node->right;
}
}
}
}

void Iterator::FindIntersecting(const Point &start, const Point &end, std::unordered_set<MarkerId> *result) {
Reset();

if (!current_node) return;

while (true) {
CacheNodePosition();
if (start < current_node_position) {
if (current_node->left) {
CheckIntersection(start, end, result);
DescendLeft();
} else {
break;
}
} else {
if (current_node->right) {
CheckIntersection(start, end, result);
DescendRight();
} else {
break;
}
}
}

do {
CheckIntersection(start, end, result);
MoveToSuccessor();
CacheNodePosition();
} while (current_node && current_node_position <= end);
}

void Iterator::FindContainedIn(const Point &start, const Point &end, std::unordered_set<MarkerId> *result) {
Reset();

if (!current_node) return;

SeekToFirstNodeGreaterThanOrEqualTo(start);

unordered_set<MarkerId> started;
while (current_node && current_node_position <= end) {
started.insert(current_node->start_marker_ids.begin(), current_node->start_marker_ids.end());
for (MarkerId id : current_node->end_marker_ids) {
if (started.count(id) > 0) result->insert(id);
}
CacheNodePosition();
MoveToSuccessor();
}
}

void Iterator::FindStartingIn(const Point &start, const Point &end, std::unordered_set<MarkerId> *result) {
Reset();

if (!current_node) return;

SeekToFirstNodeGreaterThanOrEqualTo(start);

while (current_node && current_node_position <= end) {
result->insert(current_node->start_marker_ids.begin(), current_node->start_marker_ids.end());
CacheNodePosition();
MoveToSuccessor();
}
}

void Iterator::FindEndingIn(const Point &start, const Point &end, std::unordered_set<MarkerId> *result) {
Reset();

if (!current_node) return;

SeekToFirstNodeGreaterThanOrEqualTo(start);

while (current_node && current_node_position <= end) {
result->insert(current_node->end_marker_ids.begin(), current_node->end_marker_ids.end());
CacheNodePosition();
MoveToSuccessor();
}
}

unordered_map<MarkerId, Range> Iterator::Dump() {
Reset();

unordered_map<MarkerId, Range> snapshot;

if (!current_node) return snapshot;

while (current_node && current_node->left) {
CacheNodePosition();
DescendLeft();
}

while (current_node) {
for (MarkerId id : current_node->start_marker_ids) {
Range range;
range.start = current_node_position;
snapshot.insert({id, range});
}

for (MarkerId id : current_node->end_marker_ids) {
snapshot[id].end = current_node_position;
}

CacheNodePosition();
MoveToSuccessor();
}

return snapshot;
}

void Iterator::Ascend() {
if (current_node->parent) {
if (current_node->parent->left == current_node) {
current_node_position = right_ancestor_position;
} else {
current_node_position = left_ancestor_position;
}
left_ancestor_position = left_ancestor_position_stack.back();
left_ancestor_position_stack.pop_back();
right_ancestor_position = right_ancestor_position_stack.back();
right_ancestor_position_stack.pop_back();
current_node = current_node->parent;
} else {
current_node = nullptr;
current_node_position = Point();
left_ancestor_position = Point();
right_ancestor_position = Point::Max();
}
}

void Iterator::DescendLeft() {
left_ancestor_position_stack.push_back(left_ancestor_position);
right_ancestor_position_stack.push_back(right_ancestor_position);

right_ancestor_position = current_node_position;
current_node = current_node->left;
current_node_position = left_ancestor_position.Traverse(current_node->left_extent);
}

void Iterator::DescendRight() {
left_ancestor_position_stack.push_back(left_ancestor_position);
right_ancestor_position_stack.push_back(right_ancestor_position);

left_ancestor_position = current_node_position;
current_node = current_node->right;
current_node_position = left_ancestor_position.Traverse(current_node->left_extent);
}

void Iterator::MoveToSuccessor() {
if (!current_node) return;

if (current_node->right) {
DescendRight();
while (current_node->left) {
DescendLeft();
}
} else {
while (current_node->parent && current_node->parent->right == current_node) {
Ascend();
}
Ascend();
}
}

void Iterator::SeekToFirstNodeGreaterThanOrEqualTo(const Point &position) {
while (true) {
CacheNodePosition();
if (position == current_node_position) {
break;
} else if (position < current_node_position) {
if (current_node->left) {
DescendLeft();
} else {
break;
}
} else { // position > current_node_position
if (current_node->right) {
DescendRight();
} else {
break;
}
}
}

if (current_node_position < position) MoveToSuccessor();
}

void Iterator::MarkRight(const MarkerId &id, const Point &start_position, const Point &end_position) {
if (left_ancestor_position < start_position
&& start_position <= current_node_position
&& right_ancestor_position <= end_position) {
current_node->right_marker_ids.insert(id);
}
}

void Iterator::MarkLeft(const MarkerId &id, const Point &start_position, const Point &end_position) {
if (!current_node_position.IsZero() && start_position <= left_ancestor_position && current_node_position <= end_position) {
current_node->left_marker_ids.insert(id);
}
}

Node* Iterator::InsertLeftChild(const Point &position) {
return current_node->left = new Node(current_node, position.Traversal(left_ancestor_position));
}

Node* Iterator::InsertRightChild(const Point &position) {
return current_node->right = new Node(current_node, position.Traversal(current_node_position));
}

void Iterator::CheckIntersection(const Point &start, const Point &end, unordered_set<MarkerId> *result) {
if (left_ancestor_position <= end && start <= current_node_position) {
result->insert(current_node->left_marker_ids.begin(), current_node->left_marker_ids.end());
}

if (start <= current_node_position && current_node_position <= end) {
result->insert(current_node->start_marker_ids.begin(), current_node->start_marker_ids.end());
result->insert(current_node->end_marker_ids.begin(), current_node->end_marker_ids.end());
}

if (current_node_position <= end && start <= right_ancestor_position) {
result->insert(current_node->right_marker_ids.begin(), current_node->right_marker_ids.end());
}
}

void Iterator::CacheNodePosition() const {
marker_index->node_position_cache.insert({current_node, current_node_position});
}

0 comments on commit b19b011

Please sign in to comment.