Added hashlib::idict<>
authorClifford Wolf <clifford@clifford.at>
Sun, 18 Jan 2015 11:12:33 +0000 (12:12 +0100)
committerClifford Wolf <clifford@clifford.at>
Sun, 18 Jan 2015 11:12:33 +0000 (12:12 +0100)
CodingReadme
kernel/hashlib.h
kernel/yosys.h

index 92d54d2835207355e548cf919315615f928f90c8..78bc5a3ceed7d0563dd665590dce2bcde2acc86e 100644 (file)
@@ -72,6 +72,20 @@ replacement for std::unordered_set<T>. The main characteristics are:
        - dict<K, T> and pool<T> will have the same order of iteration across
          all compilers, standard libraries and architectures.
 
+In addition to dict<K, T> and pool<T> there is also an idict<K> that
+creates a bijective map from K to the integers. For example:
+
+       idict<string, 42> si;
+       log("%d\n", si("hello"));      // will print 42
+       log("%d\n", si("world"));      // will print 43
+       log("%d\n", si.at("world"));   // will print 43
+       log("%d\n", si.at("dummy"));   // will throw exception
+       log("%s\n", si[42].c_str()));  // will print hello
+       log("%s\n", si[43].c_str()));  // will print world
+       log("%s\n", si[44].c_str()));  // will throw exception
+
+It is not possible to remove elements from an idict.
+
   2. Standard STL data types
 
 In Yosys we use std::vector<T> and std::string whenever applicable. When
index 72e9bc2ef9f3d39080fdb1b0f33fff05f6f2499c..52b38a06413d733a64e98fc44d72640a5a6d768a 100644 (file)
@@ -163,7 +163,11 @@ inline int hashtable_size(int min_size)
        throw std::length_error("hash table exceeded maximum size.");
 }
 
-template<typename K, typename T, typename OPS = hash_ops<K>>
+template<typename K, typename T, typename OPS = hash_ops<K>> class dict;
+template<typename K, int offset = 0, typename OPS = hash_ops<K>> class idict;
+template<typename K, typename OPS = hash_ops<K>> class pool;
+
+template<typename K, typename T, typename OPS>
 class dict
 {
        struct entry_t
@@ -485,9 +489,12 @@ public:
        const_iterator end() const { return const_iterator(nullptr, -1); }
 };
 
-template<typename K, typename OPS = hash_ops<K>>
+template<typename K, typename OPS>
 class pool
 {
+       template<typename, int, typename> friend class idict;
+
+protected:
        struct entry_t
        {
                K udata;
@@ -783,6 +790,55 @@ public:
        const_iterator end() const { return const_iterator(nullptr, -1); }
 };
 
+template<typename K, int offset, typename OPS>
+class idict
+{
+       pool<K, OPS> database;
+
+public:
+       typedef typename pool<K, OPS>::const_iterator const_iterator;
+
+       int operator()(const K &key)
+       {
+               int hash = database.do_hash(key);
+               int i = database.do_lookup(key, hash);
+               if (i < 0)
+                       i = database.do_insert(key, hash);
+               return i + offset;
+       }
+
+       int at(const K &key) const
+       {
+               int hash = database.do_hash(key);
+               int i = database.do_lookup(key, hash);
+               if (i < 0)
+                       throw std::out_of_range("idict::at()");
+               return i + offset;
+       }
+
+       int count(const K &key) const
+       {
+               int hash = database.do_hash(key);
+               int i = database.do_lookup(key, hash);
+               return i < 0 ? 0 : 1;
+       }
+
+       void expect(const K &key, int i)
+       {
+               int j = (*this)(key);
+               if (i != j)
+                       throw std::out_of_range("idict::expect()");
+       }
+
+       const K &operator[](int index) const
+       {
+               return database.entries.at(index - offset).udata;
+       }
+
+       const_iterator begin() const { return database.begin(); }
+       const_iterator end() const { return database.end(); }
+};
+
 } /* namespace hashlib */
 
 #endif
index d1e01b19cb6724c0e7ea138df1e6d82435ea0711..a6f4cb665d2ce5602390149b1c086e5fd2f85ce1 100644 (file)
@@ -148,6 +148,7 @@ using hashlib::hash_cstr_ops;
 using hashlib::hash_ptr_ops;
 using hashlib::hash_obj_ops;
 using hashlib::dict;
+using hashlib::idict;
 using hashlib::pool;
 
 namespace RTLIL {