#ifndef MARKER_INDEX_H_ #define MARKER_INDEX_H_ #include #include #include "flat_set.h" #include "point.h" #include "range.h" class MarkerIndex { public: using MarkerId = unsigned; using MarkerIdSet = flat_set; struct SpliceResult { flat_set touch; flat_set inside; flat_set overlap; flat_set surround; }; struct Boundary { Point position; flat_set starting; flat_set ending; }; struct BoundaryQueryResult { std::vector containing_start; std::vector boundaries; }; MarkerIndex(unsigned seed = 0u); ~MarkerIndex(); int generate_random_number(); void insert(MarkerId id, Point start, Point end); void set_exclusive(MarkerId id, bool exclusive); void remove(MarkerId id); bool has(MarkerId id); SpliceResult splice(Point start, Point old_extent, Point new_extent); Point get_start(MarkerId id) const; Point get_end(MarkerId id) const; Range get_range(MarkerId id) const; int compare(MarkerId id1, MarkerId id2) const; flat_set find_intersecting(Point start, Point end); flat_set find_containing(Point start, Point end); flat_set find_contained_in(Point start, Point end); flat_set find_starting_in(Point start, Point end); flat_set find_starting_at(Point position); flat_set find_ending_in(Point start, Point end); flat_set find_ending_at(Point position); BoundaryQueryResult find_boundaries_after(Point start, size_t max_count); std::unordered_map dump(); private: friend class Iterator; struct Node { Node *parent; Node *left; Node *right; Point left_extent; flat_set left_marker_ids; flat_set right_marker_ids; flat_set start_marker_ids; flat_set end_marker_ids; int priority; Node(Node *parent, Point left_extent); bool is_marker_endpoint(); }; class Iterator { public: Iterator(MarkerIndex *marker_index); void reset(); Node* insert_marker_start(const MarkerId &id, const Point &start_position, const Point &end_position); Node* insert_marker_end(const MarkerId &id, const Point &start_position, const Point &end_position); Node* insert_splice_boundary(const Point &position, bool is_insertion_end); void find_intersecting(const Point &start, const Point &end, flat_set *result); void find_contained_in(const Point &start, const Point &end, flat_set *result); void find_starting_in(const Point &start, const Point &end, flat_set *result); void find_ending_in(const Point &start, const Point &end, flat_set *result); void find_boundaries_after(Point start, size_t max_count, BoundaryQueryResult *result); std::unordered_map dump(); private: void ascend(); void descend_left(); void descend_right(); void move_to_successor(); void seek_to_first_node_greater_than_or_equal_to(const Point &position); void mark_right(const MarkerId &id, const Point &start_position, const Point &end_position); void mark_left(const MarkerId &id, const Point &start_position, const Point &end_position); Node* insert_left_child(const Point &position); Node* insert_right_child(const Point &position); void check_intersection(const Point &start, const Point &end, flat_set *results); void cache_node_position() const; MarkerIndex *marker_index; Node *current_node; Point current_node_position; Point left_ancestor_position; Point right_ancestor_position; std::vector left_ancestor_position_stack; std::vector right_ancestor_position_stack; }; Point get_node_position(const Node *node) const; void delete_node(Node *node); void delete_subtree(Node *node); void bubble_node_up(Node *node); void bubble_node_down(Node *node); void rotate_node_left(Node *pivot); void rotate_node_right(Node *pivot); void get_starting_and_ending_markers_within_subtree(const Node *node, flat_set *starting, flat_set *ending); void populate_splice_invalidation_sets(SpliceResult *invalidated, const Node *start_node, const Node *end_node, const flat_set &starting_inside_splice, const flat_set &ending_inside_splice); std::default_random_engine random_engine; std::uniform_int_distribution random_distribution; Node *root; std::unordered_map start_nodes_by_id; std::unordered_map end_nodes_by_id; Iterator iterator; flat_set exclusive_marker_ids; mutable std::unordered_map node_position_cache; }; #endif // MARKER_INDEX_H_