Ptex
PtexHashMap.h
Go to the documentation of this file.
1 /*
2 PTEX SOFTWARE
3 Copyright 2009 Disney Enterprises, Inc. All rights reserved
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in
14  the documentation and/or other materials provided with the
15  distribution.
16 
17  * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
18  Studios" or the names of its contributors may NOT be used to
19  endorse or promote products derived from this software without
20  specific prior written permission from Walt Disney Pictures.
21 
22 Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
23 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
26 IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
31 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34 */
40 #ifndef PtexHashMap_h
41 #define PtexHashMap_h
42 
84 template<typename KeyType, typename DataType, typename HashFn>
86 {
87  struct Entry; // forward decl
88 
89 public:
90  typedef KeyType key_type;
92  typedef HashFn hash_fn;
93 
94  struct value_type {
95  key_type first;
96  data_type second;
97  value_type() : first(), second() {}
98  value_type(const KeyType& first, const DataType& second)
99  : first(first), second(second) {}
100  };
101 
102  class iterator {
103  public:
105  iterator() : e(0), h(0), b(0) {}
106 
108  iterator(const iterator& iter) : e(iter.e), h(iter.h), b(iter.b) {}
109 
112  if (e) return value_type((*e)->key, (*e)->val);
113  return value_type();
114  }
115 
117  iterator& operator=(const iterator& iter) {
118  e = iter.e; h = iter.h; b = iter.b; return *this;
119  }
120 
122  bool operator==(const iterator& iter) const { return iter.e == e; }
124  bool operator!=(const iterator& iter) const { return iter.e != e; }
126  iterator& operator++(int);
127 
128  private:
129  friend class PtexHashMap;
130  Entry** e; // pointer to prev entry or hash entry
131  const PtexHashMap* h;
132  int b; // bucket number
133  };
134 
136  iterator begin() const
137  {
138  iterator iter;
139  iter.h = this;
140  for (iter.b = 0; iter.b < _numBuckets; iter.b++) {
141  iter.e = &_buckets[iter.b];
142  if (*iter.e) return iter;
143  }
144  iter.e = 0;
145  return iter;
146  }
147 
149  iterator end() const
150  {
151  iterator iter;
152  iter.h = this; iter.b = 0; iter.e = 0;
153  return iter;
154  }
155 
156 
161 
163 
166  DataType& operator[](const KeyType& key);
167 
169 
175  iterator find(const KeyType& key) const;
176 
178  bool erase(const KeyType& key);
180  iterator erase(iterator iter);
181 
183  void clear();
184 
186  int size() const { return _numEntries; }
187 
188 private:
190  PtexHashMap(const PtexHashMap&); // disallow
192  bool operator=(const PtexHashMap&); // disallow
193 
194  friend class iterator;
195 
196  struct Entry {
197  Entry() : val() {}
199  KeyType key;
201  };
202 
204  Entry** locate(const KeyType& key) const
205  {
206  if (!_buckets) return 0;
207  for (Entry** e = &_buckets[hash(key) & _bucketMask]; *e; e = &(*e)->next)
208  if ((*e)->key == key)
209  return e;
210  return 0;
211  }
212 
214  void grow();
215 
219  Entry** _buckets;
220  HashFn hash;
221 };
222 
223 
224 template<class KeyType, class DataType, class HashFn>
227 {
228  if (e) {
229  // move to next entry
230  e = &(*e)->next;
231  if (!*e) {
232  // move to next non-empty bucket
233  for (b++; b < h->_numBuckets; b++) {
234  e = &h->_buckets[b];
235  if (*e) return *this;
236  }
237  e = 0;
238  }
239  }
240  return *this;
241 }
242 
243 
244 template<class KeyType, class DataType, class HashFn>
247 {
248  iterator iter;
249  Entry** e = locate(key);
250  if (e) {
251  iter.h = this;
252  iter.e = e;
253  iter.b = hash(key) & _bucketMask;
254  } else iter = end();
255  return iter;
256 }
257 
258 template<class KeyType, class DataType, class HashFn>
260 {
261  Entry** e = locate(key);
262  if (e) return (*e)->val;
263 
264  // create a new entry
265  _numEntries++;
266  if (_numEntries*2 >= _numBuckets) grow();
267  void* ebuf = malloc(sizeof(Entry));
268  Entry* ne = new(ebuf) Entry; // note: placement new
269  Entry** slot = &_buckets[hash(key) & _bucketMask];
270  ne->next = *slot; *slot = ne;
271  ne->key = key;
272  return ne->val;
273 }
274 
275 
276 template<class KeyType, class DataType, class HashFn>
278 {
279  if (!_buckets) {
280  _numBuckets = 16;
281  _bucketMask = _numBuckets - 1;
282  _buckets = (Entry**) calloc(_numBuckets, sizeof(Entry*));
283  } else {
284  int newsize = _numBuckets * 2;
285  _bucketMask = newsize - 1;
286  Entry** newbuckets = (Entry**) calloc(newsize, sizeof(Entry*));
287  for (int i = 0; i < _numBuckets; i++) {
288  for (Entry* e = _buckets[i]; e;) {
289  Entry* next = e->next;
290  Entry** slot = &newbuckets[hash(e->key) & _bucketMask];
291  e->next = *slot; *slot = e;
292  e = next;
293  }
294  }
295  free(_buckets);
296  _buckets = newbuckets;
297  _numBuckets = newsize;
298  }
299 }
300 
301 
302 template<class KeyType, class DataType, class HashFn>
304 {
305  iterator iter = find(key);
306  if (iter == end()) return 0;
307  erase(iter);
308  return 1;
309 }
310 
311 
312 template<class KeyType, class DataType, class HashFn>
315 {
316  Entry** eptr = iter.e;
317  if (!eptr) return iter;
318 
319  // patch around deleted entry
320  Entry* e = *eptr;
321  Entry* next = e->next;
322  if (!next) iter++; // advance iterator if at end of chain
323  *eptr = next;
324 
325 
326  // destroy entry
327  e->~Entry(); // note: explicit dtor call
328  free(e);
329  _numEntries--;
330 
331  return iter;
332 }
333 
334 
335 template<class KeyType, class DataType, class HashFn>
337 {
338  for (iterator i = begin(); i != end(); )
339  i = erase(i);
340  free(_buckets);
341  _buckets = 0;
342  _numEntries = 0;
343  _numBuckets = 0;
344 }
345 
346 #endif
iterator find(const KeyType &key) const
Locates an entry, without creating a new one.
Definition: PtexHashMap.h:246
HashFn hash_fn
Definition: PtexHashMap.h:92
Entry ** _buckets
Definition: PtexHashMap.h:219
bool operator=(const PtexHashMap &)
Assignment operator prohibited by design.
const PtexHashMap * h
Definition: PtexHashMap.h:131
iterator & operator++(int)
For advancing the iterator to the next element.
Definition: PtexHashMap.h:226
HashFn hash
Definition: PtexHashMap.h:220
Entry ** locate(const KeyType &key) const
Returns a pointer to the desired entry, based on the key.
Definition: PtexHashMap.h:204
value_type(const KeyType &first, const DataType &second)
Definition: PtexHashMap.h:98
~PtexHashMap()
Non-Virtual destructor by design, clears the entries in the hash table.
Definition: PtexHashMap.h:160
void grow()
Used to increase the size of the table if necessary.
Definition: PtexHashMap.h:277
int size() const
number of entries in the hash
Definition: PtexHashMap.h:186
DataType & operator[](const KeyType &key)
Locates an entry, creating a new one if necessary.
Definition: PtexHashMap.h:259
PtexHashMap()
Default contructor initializes the hash table.
Definition: PtexHashMap.h:158
bool erase(const KeyType &key)
Will remove an entry. It will return TRUE if an entry was found.
Definition: PtexHashMap.h:303
iterator(const iterator &iter)
Proper copy constructor implementation.
Definition: PtexHashMap.h:108
bool operator!=(const iterator &iter) const
For comparing inequality of iterators.
Definition: PtexHashMap.h:124
iterator()
Default Constructor.
Definition: PtexHashMap.h:105
if(WIN32) add_definitions(/DPTEX_EXPORTS) endif(WIN32) set(SRCS PtexCache.cpp PtexFilters.cpp PtexHalf.cpp PtexReader.cpp PtexSeparableFilter.cpp PtexSeparableKernel.cpp PtexTriangleFilter.cpp PtexTriangleKernel.cpp PtexUtils.cpp PtexWriter.cpp) add_library(Ptex_static STATIC $
DataType
Type of data stored in texture file.
Definition: Ptexture.h:196
iterator & operator=(const iterator &iter)
Proper assignment operator.
Definition: PtexHashMap.h:117
value_type operator*() const
Operator for obtaining the value that the iterator references.
Definition: PtexHashMap.h:111
iterator end() const
Returns an iteraot referencing the location just beyond the table.
Definition: PtexHashMap.h:149
friend class iterator
Definition: PtexHashMap.h:194
DataType data_type
Definition: PtexHashMap.h:91
Internal class used to provide iteration through the hash table.
Definition: PtexHashMap.h:102
KeyType key_type
Definition: PtexHashMap.h:87
iterator begin() const
Returns an iterator referencing the beginning of the table.
Definition: PtexHashMap.h:136
void clear()
clear will remove all entries and free the table
Definition: PtexHashMap.h:336
bool operator==(const iterator &iter) const
For comparing equality of iterators.
Definition: PtexHashMap.h:122
A lightweight hash table.
Definition: PtexHashMap.h:85