diff --git a/src/include/interval-map/interval-map.hh b/src/include/interval-map/interval-map.hh index a514daf..b518f24 100644 --- a/src/include/interval-map/interval-map.hh +++ b/src/include/interval-map/interval-map.hh @@ -15,26 +15,45 @@ public: if (!(begin < end)) return; - auto const end_val = (*this)[end]; - underlying_.erase(underlying_.lower_bound(begin), - underlying_.upper_bound(end)); - if (!((*this)[begin] == val)) - underlying_.insert({begin, val}); - if (!((*this)[end] == end_val)) - underlying_.insert({end, end_val}); + auto it = underlying_.upper_bound(end); + auto const end_val = at_upper_bound(it); + + bool insert_begin = !(val == init_); + + while (it != underlying_.begin()) { + it = std::prev(it); + auto begin_found = it->first < begin; + if (begin_found) { + insert_begin = !(val == it->second); + break; + } + if (it != underlying_.end()) + // Account for up-coming `std::prev` with `++` + underlying_.erase(it++); + } + + if (insert_begin) + it = underlying_.insert(it, {begin, val}); + // Get the proper upper-bound for `end` + it = (it == underlying_.end() || end < it->first) ? it : std::next(it); + if (!(at_upper_bound(it) == end_val)) + underlying_.insert(it, {end, end_val}); } V const& operator[](K const& key) const { - auto it = underlying_.upper_bound(key); - if (it == underlying_.begin()) - return init_; - return std::prev(it)->second; + return at_upper_bound(underlying_.upper_bound(key)); } // Used in testing friend class ::IntervalMapTest; private: + V const& at_upper_bound(std::map::const_iterator it) const { + if (it == underlying_.begin()) + return init_; + return std::prev(it)->second; + } + V init_; std::map underlying_{}; }; diff --git a/src/meson.build b/src/meson.build index 0e8c25d..3c30a37 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1 +1,3 @@ interval_map_dep = declare_dependency(include_directories: 'include') + +install_headers('include/interval-map/interval-map.hh', subdir: 'interval-map') diff --git a/tests/unit/unit_test.cc b/tests/unit/unit_test.cc index c429d29..53675c3 100644 --- a/tests/unit/unit_test.cc +++ b/tests/unit/unit_test.cc @@ -242,6 +242,12 @@ TEST_F(IntervalMapTest, fuzzing_003) { assign(-110, -10, 4); } +TEST_F(IntervalMapTest, fuzzing_004) { + assign(-20, 120, 1); + assign(50, 110, 0); + assign(-120, 100, 0); +} + TEST_F(IntervalMapTest, randomized_test) { auto const seed = []() { std::random_device r;