summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CodingReadme14
-rw-r--r--kernel/hashlib.h60
-rw-r--r--kernel/yosys.h1
3 files changed, 73 insertions, 2 deletions
diff --git a/CodingReadme b/CodingReadme
index 92d54d28..78bc5a3c 100644
--- a/CodingReadme
+++ b/CodingReadme
@@ -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
diff --git a/kernel/hashlib.h b/kernel/hashlib.h
index 72e9bc2e..52b38a06 100644
--- a/kernel/hashlib.h
+++ b/kernel/hashlib.h
@@ -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
diff --git a/kernel/yosys.h b/kernel/yosys.h
index d1e01b19..a6f4cb66 100644
--- a/kernel/yosys.h
+++ b/kernel/yosys.h
@@ -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 {