#ifndef __JTOOLS__JHASHMAP__ #define __JTOOLS__JHASHMAP__ #include #include "JLang/JException.hh" #include "JLang/JClass.hh" #include "JLang/JStreamAvailable.hh" #include "JTools/JMappableCollection.hh" #include "JTools/JHashCollection.hh" #include "JTools/JHashEvaluator.hh" #include "JTools/JRouter.hh" /** * \file * * General purpose class for hash map of unique elements. * \author mdejong */ namespace JTOOLS {} namespace JPP { using namespace JTOOLS; } namespace JTOOLS { using JLANG::JClass; using JLANG::JIndexOutOfRange; /** * Auxiliary class for hash evaluation of map keys and elements. */ template struct JHashMapEvaluator : public JEvaluator_t { using JEvaluator_t::operator(); /** * Constructor. * * \param evaluator evaluator */ JHashMapEvaluator(const JEvaluator_t& evaluator) : JEvaluator_t(evaluator) {} /** * Get hash value of given pair. * * \param pair pair * \return hash value */ template inline int operator()(const std::pair& pair) { return JEvaluator_t::operator()(pair.first); } }; /** * General purpose class for hash map of unique keys. * * The keys in a hash collection are unique according to the specified evaluation. * The evaluation of keys corresponds to a unary method returning an integer value for a given key; * The default evaluator is JHashEvaluator. * * This class implements the JMappableCollection interface. */ template struct JHashMap : public JHashCollection, JHashMapEvaluator >, public JMappableCollection { public: typedef JKey_t key_type; typedef JValue_t mapped_type; typedef std::pair value_type; typedef JHashMapEvaluator evaluator_type; typedef JHashCollection collection_type; typedef typename collection_type::container_type container_type; typedef typename container_type::const_iterator const_iterator; typedef typename container_type::const_reverse_iterator const_reverse_iterator; typedef typename container_type::iterator iterator; typedef typename container_type::reverse_iterator reverse_iterator; using JMappableCollection::operator[]; /** * Constructor. * * \param evaluator evaluator */ JHashMap(const JEvaluator_t& evaluator = JEvaluator_t()) : collection_type(evaluator) {} /** * Clear. */ virtual void clear() override { collection_type::clear(); } /** * Reset values. */ void reset() { for (iterator i = this->begin(); i != this->end(); ++i) { i->second = mapped_type(); } } /** * Set values corresponding to keys in given source. * * \param source source * \param value value */ void set(const JHashMap& source, const mapped_type& value) { this->clear(); for (const_iterator i = source.begin(); i != source.end(); ++i) { (*this)[i->first] = value; } } /** * Get mapped value. * * \param key key * \return mapped value */ virtual mapped_type& get(typename JClass::argument_type key) override { const int ival = this->getValue(key); if (!this->router.has(ival)) { collection_type::insert(value_type(key, mapped_type())); } return container_type::operator[](this->router.get(ival)).second; } /** * Get mapped value. * * This method will throw an exception if given key is not present following the prerequisite of constness. * * \param key key * \return mapped value */ virtual const mapped_type& get(typename JClass::argument_type key) const override { const int ival = this->getValue(key); if (this->router.has(ival)) return container_type::operator[](this->router.get(ival)).second; else THROW(JIndexOutOfRange, "JHasMap::get(): invalid key " << STREAM("?") << key); } }; } #endif