Created
October 10, 2019 21:57
-
-
Save loliGothicK/a7c924f49f6fe5a4e3a55311978ce34b to your computer and use it in GitHub Desktop.
range wrapper for TopExp_Explorer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef CADDi_OCC_EXTENSIONS_EXPLORER_HPP | |
#define CADDi_OCC_EXTENSIONS_EXPLORER_HPP | |
#include <iterator> | |
#include <type_traits> | |
#include <utility> | |
#include <functional> | |
#include <memory> | |
#include <TopExp_Explorer.hxx> | |
#include <TopoDS_Shape.hxx> | |
#include <boost/container/flat_map.hpp> | |
#include <mitama/container/entry.hpp> | |
namespace caddi::occ_ex { | |
struct explorer_sentinel {}; | |
namespace _detail { | |
class control_block_t { | |
boost::container::flat_map<std::size_t, TopoDS_Shape> table_; | |
public: | |
std::size_t upper_bound = std::numeric_limits<std::size_t>::max(); | |
auto entry(std::size_t index) { | |
return mitama::entry_t(table_, index); | |
} | |
}; | |
} | |
class explorer_iterator { | |
TopExp_Explorer* exp_; | |
std::shared_ptr<_detail::control_block_t> storage_; | |
std::size_t index_; | |
public: | |
using difference_type = std::ptrdiff_t; | |
using value_type = TopoDS_Shape; | |
using reference = TopoDS_Shape&; | |
using pointer = TopoDS_Shape*; | |
using iterator_category = std::bidirectional_iterator_tag; | |
explorer_iterator(TopExp_Explorer* exp, std::shared_ptr<_detail::control_block_t> storage) | |
: exp_(exp) | |
, storage_(storage) | |
{} | |
explorer_iterator() = default; | |
explorer_iterator(explorer_iterator const&) = default; | |
explorer_iterator(explorer_iterator&&) = default; | |
explorer_iterator& operator=(explorer_iterator const&) = default; | |
explorer_iterator& operator=(explorer_iterator&&) = default; | |
~explorer_iterator() = default; | |
explorer_iterator& operator++() & { | |
index_++; | |
exp_->Next(); | |
if (!exp_->More()) storage_->upper_bound = index_; | |
else storage_->entry(index_).or_emplace(exp_->Current()); | |
return *this; | |
} | |
explorer_iterator operator++(int) & { | |
auto iter = *this; | |
index_++; | |
exp_->Next(); | |
if (!exp_->More()) storage_->upper_bound = index_; | |
else storage_->entry(index_).or_emplace(exp_->Current()); | |
return iter; | |
} | |
explorer_iterator& operator--() & { | |
index_--; | |
return *this; | |
} | |
explorer_iterator operator--(int) & { | |
auto iter = *this; | |
index_--; | |
return iter; | |
} | |
TopoDS_Shape& operator*() const { | |
return storage_->entry(index_).or_emplace(exp_->Current()); | |
} | |
friend bool operator==(explorer_iterator const& lhs, explorer_iterator const& rhs) | |
{ return lhs.exp_ == rhs.exp_ && lhs.index_ == rhs.index_; } | |
friend bool operator!=(explorer_iterator const& lhs, explorer_iterator const& rhs) | |
{ return !(lhs == rhs); } | |
friend bool operator==(explorer_sentinel const&, explorer_iterator const& iter) | |
{ return !iter.exp_->More() && iter.index_ >= iter.storage_->upper_bound; } | |
friend bool operator==(explorer_iterator const& iter, explorer_sentinel const& sentinel) | |
{ return sentinel == iter; } | |
friend bool operator!=(explorer_sentinel const& sentinel, explorer_iterator const& iter) | |
{ return !(sentinel == iter); } | |
friend bool operator!=(explorer_iterator const& iter, explorer_sentinel const& sentinel) | |
{ return !(sentinel == iter); } | |
}; | |
bool operator==(explorer_sentinel, explorer_sentinel) { return true; } | |
bool operator!=(explorer_sentinel, explorer_sentinel) { return false; } | |
class explorer { | |
std::reference_wrapper<TopExp_Explorer> exp_; | |
std::shared_ptr<_detail::control_block_t> storage_; | |
public: | |
explicit explorer(TopExp_Explorer& exp): exp_(exp), storage_( std::make_shared<_detail::control_block_t>() ) {} | |
explorer() = delete; | |
explorer(explorer const&) = default; | |
explorer(explorer&&) = default; | |
explorer& operator=(explorer const&) = default; | |
explorer& operator=(explorer&&) = default; | |
explorer_iterator begin() const { return explorer_iterator{&exp_.get(), storage_}; } | |
explorer_sentinel end() const { return {}; } | |
}; | |
explorer_iterator begin(explorer const& exp) | |
{ return exp.begin(); } | |
explorer_sentinel end(explorer const&) | |
{ return {}; } | |
} | |
namespace std { | |
template <> | |
class iterator_traits<caddi::occ_ex::explorer_iterator> { | |
public: | |
using difference_type = std::ptrdiff_t; | |
using value_type = TopoDS_Shape; | |
using reference = TopoDS_Shape&; | |
using pointer = TopoDS_Shape*; | |
using iterator_category = std::bidirectional_iterator_tag; | |
}; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
entry.hpp