File: Dictionary.h

package info (click to toggle)
abyss 2.3.10-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 8,284 kB
  • sloc: cpp: 78,182; ansic: 6,512; makefile: 2,252; perl: 672; sh: 509; haskell: 412; python: 4
file content (127 lines) | stat: -rw-r--r-- 2,977 bytes parent folder | download | duplicates (5)
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