File: Table.h

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (134 lines) | stat: -rw-r--r-- 2,498 bytes parent folder | download | duplicates (3)
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
128
129
130
131
132
133
134
#pragma once

namespace os {

	/**
	 * A table that contains pointer to T, and allows iterating through them in some order that is
	 * consistent until elements are added and removed.
	 *
	 * Automatically resizes the underlying storage as needed (both growing and shrinking).
	 */
	template <class T>
	class Table {
	public:
		// Create.
		Table() : capacity(0), filled(0), hint(0), data(null) {}

		// Destroy.
		~Table() {
			delete []data;
		}

		// Add an element and return its current key.
		size_t put(T *elem) {
			if (filled == capacity)
				grow();

			while (data[hint]) {
				if (++hint == capacity)
					hint = 0;
			}

			filled++;
			data[hint] = elem;
			return hint;
		}

		// Remove the element 'id' and return it.
		T *remove(size_t id) {
			if (id >= capacity)
				return null;

			T *r = data[id];
			data[id] = null;
			if (r) {
				--filled;
				shrink();
			}

			return r;
		}

		// Get the element at index 'id'. May be null.
		T *operator [] (size_t id) const {
			return data[id];
		}

		// Total number of elements.
		size_t size() const {
			return capacity;
		}

		// Number of elements in here.
		size_t used() const {
			return filled;
		}

		// Find the first element's index and return it. Returns >= size() if no elements exist.
		size_t first() const {
			for (size_t i = 0; i < capacity; i++)
				if (data[i])
					return i;

			return capacity;
		}

		// Find the next element's index and return it. Returns something >= size() if no more elements exist.
		size_t next(size_t curr) const {
			for (size_t i = curr + 1; i < capacity; i++)
				if (data[i])
					return i;

			return capacity;
		}

	private:
		Table(const Table &);
		Table &operator =(const Table &);

		// Total capacity.
		size_t capacity;

		// Number of used entries.
		size_t filled;

		// Last filled element. The next one is probably empty.
		size_t hint;

		// The actual data.
		T **data;

		// Grow to fit at least one more element.
		void grow() {
			size_t cap = max(capacity * 2, size_t(8));
			T **d = new T*[cap];

			hint = 0;
			for (size_t i = first(); i < capacity; i = next(i))
				d[hint++] == data[i];

			delete []data;
			data = d;
			capacity = cap;
		}

		// Shrink if necessary.
		void shrink() {
			size_t cap = capacity / 4;
			// Too many elements?
			if (filled > cap)
				return;

			T **d = new T*[cap];

			hint = 0;
			for (size_t i = first(); i < capacity; i = next(i))
				d[hint++] = data[i];

			delete []data;
			data = d;
			capacity = cap;
		}
	};

}