#ifndef __JTOOLS__JROUTER__ #define __JTOOLS__JROUTER__ #include #include #include "JLang/JComparisonAvailable.hh" #include "JLang/JClass.hh" /** * \author mdejong */ namespace JTOOLS {} namespace JPP { using namespace JTOOLS; } namespace JTOOLS { using JLANG::JComparisonAvailable; /** * Direct addressing of elements with unique identifiers. */ template::has_eq> class JRouter; /** * Template specialisation of JRouter without default address comparison. */ template class JRouter : protected std::vector { typedef typename JLANG::JClass::argument_type argument_type; public: /** * Default constructor. */ JRouter() : std::vector(), first(0) {} /** * Virtual destructor. */ virtual ~JRouter() {} /** * Get default address. * * \return default address */ virtual const JAddress_t& getDefaultAddress() const { static JAddress_t address; return address; } /** * Clear. */ void clear() { static_cast&>(*this).clear(); this->first = 0; } /** * Swap router. * * \param router router */ void swap(JRouter& router) { std::swap(this->first, router.first); static_cast&>(*this).swap(router); } /** * Align router. * * \param router router */ void align(const JRouter& router) { this->first = router.first; if (router.size() > this->size()) { this->resize(router.size()); } } /** * Store address for given identifier. * * \param id identifier * \param address address */ void put(const int id, argument_type address) { if (this->empty()) { this->push_back(address); this->first = id; } else if (id < this->first) { this->insert(this->begin(), this->first - id, getDefaultAddress()); this->first = id; (*this)[0] = address; } else { const size_t index = (size_t) (id - this->first); if (index >= this->size()) { this->resize(index + 1, getDefaultAddress()); } (*this)[index] = address; } } /** * Check whether given identifier is in range of this router. * * \param id identifier * \return true if in range; else false */ bool in_range(const int id) const { return (id >= this->first && id < this->first + (int) this->size()); } /** * Get address of given identifier. * * \param id identifier * \return address */ const JAddress_t& get(const int id) const { return (*this)[id - this->first]; } protected: int first; }; /** * Template specialisation of JRouter with default address comparison. */ template class JRouter : public JRouter { typedef typename JLANG::JClass::argument_type argument_type; protected: /** * Simple data structure for validation of address. */ class JAddress { public: /** * Default constructor. */ JAddress() : __is_valid(false), __address () {} /** * Constructor. * * \param address default address */ JAddress(argument_type address) : __is_valid(true), __address (address) {} /** * Check validity. * * \return true if valid; else false */ bool is_valid() const { return __is_valid; } /** * Get address. * * \return address */ const JAddress_t& getAddress() const { return __address; } /** * Compare to given address. * * \param address address * \return true if valid and equal; else false */ bool equals(argument_type address) const { return __is_valid && address == __address; } private: bool __is_valid; JAddress_t __address; }; public: /** * Default constructor. */ JRouter() : JRouter(), defaultAddress() {} /** * Constructor. * * \param address default address */ JRouter(argument_type address) : JRouter(), defaultAddress(address) {} /** * Check availability of default address. * * \return true if available; else false */ bool hasDefaultAddress() const { return defaultAddress.is_valid(); } /** * Get default address. * * \return default address */ virtual const JAddress_t& getDefaultAddress() const override { return defaultAddress.getAddress(); } /** * Set default address. * * \param address default address */ void setDefaultAddress(argument_type address) { defaultAddress = JAddress(address); } /** * Test whether given identifier has valid address (i.e identifier is in range and corresponding address is not equal to default address). * * \param id identifier * \return true if identifier in range and address not equal to default; else false */ bool has(const int id) const { return (this->in_range(id) && !this->defaultAddress.equals(this->get(id))); } private: JAddress defaultAddress; }; } #endif