src
ord_hash_set.h
Go to the documentation of this file.
1 #ifndef _RE2C_UTIL_ORD_HASH_SET_
2 #define _RE2C_UTIL_ORD_HASH_SET_
3 
4 #include "src/util/c99_stdint.h"
5 #include <stdlib.h> // malloc, free
6 #include <string.h> // memcpy
7 #include <map>
8 #include <vector>
9 
10 namespace re2c
11 {
12 
13 /*
14  * ordered hash set:
15  * - access element by index: O(1)
16  * - insert element (find existing or add new): O(log(n))
17  *
18  */
20 {
21  struct elem_t
22  {
23  elem_t *next;
24  size_t index;
25  size_t size;
26  char data[1]; // inlined array of variable length
27  };
28  typedef size_t hash_t;
29 
30  std::vector<elem_t*> elems;
31  std::map<hash_t, elem_t*> lookup;
32 
33  static hash_t hash(const void *data, size_t size);
34  elem_t *make_elem(elem_t *next, size_t index, size_t size, const void *data);
35 
36 public:
39  size_t size() const;
40  size_t insert(const void *data, size_t size);
41  template<typename data_t> size_t deref(size_t i, data_t *&data);
42 };
43 
44 ord_hash_set_t::hash_t ord_hash_set_t::hash(const void *data, size_t size)
45 {
46  const uint8_t *bytes = static_cast<const uint8_t*>(data);
47  hash_t h = size; // seed
48  for (size_t i = 0; i < size; ++i)
49  {
50  h = h ^ ((h << 5) + (h >> 2) + bytes[i]);
51  }
52  return h;
53 }
54 
55 ord_hash_set_t::elem_t* ord_hash_set_t::make_elem(
56  elem_t *next,
57  size_t index,
58  size_t size,
59  const void *data)
60 {
61  elem_t *e = static_cast<elem_t*>(malloc(offsetof(elem_t, data) + size));
62  e->next = next;
63  e->index = index;
64  e->size = size;
65  memcpy(e->data, data, size);
66  return e;
67 }
68 
70  : elems()
71  , lookup()
72 {}
73 
75 {
76  std::for_each(elems.begin(), elems.end(), free);
77 }
78 
79 size_t ord_hash_set_t::size() const
80 {
81  return elems.size();
82 }
83 
84 size_t ord_hash_set_t::insert(const void *data, size_t size)
85 {
86  const hash_t h = hash(data, size);
87 
88  std::map<hash_t, elem_t*>::const_iterator i = lookup.find(h);
89  if (i != lookup.end())
90  {
91  for (elem_t *e = i->second; e; e = e->next)
92  {
93  if (e->size == size
94  && memcmp(e->data, data, size) == 0)
95  {
96  return e->index;
97  }
98  }
99  }
100 
101  const size_t index = elems.size();
102  elems.push_back(lookup[h] = make_elem(lookup[h], index, size, data));
103  return index;
104 }
105 
106 template<typename data_t> size_t ord_hash_set_t::deref(size_t i, data_t *&data)
107 {
108  elem_t *e = elems[i];
109  data = reinterpret_cast<data_t*>(e->data);
110  return e->size / sizeof(data_t);
111 }
112 
113 } // namespace re2c
114 
115 #endif // _RE2C_UTIL_ORD_HASH_SET_
size_t insert(const void *data, size_t size)
Definition: ord_hash_set.h:84
size_t deref(size_t i, data_t *&data)
Definition: ord_hash_set.h:106
size_t size() const
Definition: ord_hash_set.h:79
Definition: bitmap.cc:10