1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
#ifndef DICTIONARY_H
#define DICTIONARY_H 1
#include "ConstString.h"
#include "UnorderedMap.h"
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
/** A bidirectional map of indices and names. */
class Dictionary
{
public:
typedef unsigned index_type;
typedef unsigned index_reference;
typedef std::string name_type;
typedef cstring name_reference;
typedef std::vector<const_string> Vector;
typedef unordered_map<name_reference, index_type,
hash<name_reference> > Map;
Dictionary() : m_locked(false) { }
/** Insert the specified name. */
index_reference insert(const name_type& name)
{
m_vec.push_back(name);
std::pair<Map::const_iterator, bool> inserted
= m_map.insert(Map::value_type(
m_vec.back(), m_map.size()));
if (!inserted.second) {
std::cerr << "error: duplicate ID: `"
<< name << "'\n";
abort();
}
return inserted.first->second;
}
/** If the specified index is within this dictionary, ensure
* that the name is identical, otherwise append the name to
* this dictionary.
*/
void put(index_type index, const name_type& name)
{
if (index < m_vec.size()) {
assert(getName(index) == name);
} else {
assert(!m_locked);
assert(index == m_vec.size());
index_type i = insert(name);
assert(i == index);
(void)i;
}
}
/** Return the index of the specified name. */
index_reference getIndex(const name_type& name) const
{
Map::const_iterator it = m_map.find(name);
if (it == m_map.end()) {
std::cerr << "error: unexpected ID: `"
<< name << "'\n";
abort();
}
return it->second;
}
/** Return the name of the specified index. */
name_reference getName(index_type index) const
{
assert(index < m_vec.size());
return m_vec[index];
}
/** Lock this dictionary. No further elements may be added. */
void lock() { m_locked = true; }
/** Unlock this dictionary. */
void unlock() { m_locked = false; }
/** Return true if this dictionary is empty. */
bool empty() const { return m_vec.empty(); }
/** Return the number of elements in this dictionary. */
size_t size() const { return m_vec.size(); }
/** Return the number of elements with the specified name. */
size_t count(const name_type& name) const
{
return m_map.count(name);
}
/** Return the last name in this dictionary. */
name_reference back() const
{
assert(!m_vec.empty());
return m_vec.back();
}
private:
Map m_map;
Vector m_vec;
bool m_locked;
};
static inline Dictionary::name_reference get(
const Dictionary& pmap, Dictionary::index_type index)
{
return pmap.getName(index);
}
static inline void put(Dictionary& pmap, Dictionary::index_type index,
const Dictionary::name_type& name)
{
pmap.put(index, name);
}
static inline Dictionary::index_reference get(
const Dictionary& pmap, Dictionary::name_type name)
{
return pmap.getIndex(name);
}
#endif
|