Ptex
PtexDict.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 PtexDict_h
41 #define PtexDict_h
42 
110 template<class T>
111 class PtexDict
112 {
113  class Entry;
114 
115 public: // Public Types
116  class iterator;
118  friend class iterator;
119  friend class const_iterator;
120 
121  typedef const char* key_type;
122  typedef T mapped_type;
123 
124  struct value_type {
125  public:
127  value_type(): first(0), second() {}
129  value_type(key_type f, const T& s): first(f), second(s) {}
130 
131  const key_type first;
132  T second;
133  };
134 
135 public: // Public Member Interfce
136 
140  virtual ~PtexDict() { clear(); }
141 
143 
146  T& operator[](const char* key);
147 
150  {
151  iterator iter;
152  iter._d = this;
153  for (iter._b = 0; iter._b < _numBuckets; iter._b++) {
154  iter._e = &_buckets[iter._b];
155  if (*iter._e) return iter;
156  }
157  iter._e = 0;
158  return iter;
159  }
160 
162  inline iterator end() { return iterator( 0, this, 0 ); }
163 
166  {
167  const_iterator iter;
168  iter._d = this;
169  for (iter._b = 0; iter._b < _numBuckets; iter._b++) {
170  iter._e = &_buckets[iter._b];
171  if (*iter._e) return iter;
172  }
173  iter._e = 0;
174  return iter;
175  }
176 
178  inline const_iterator end() const { return const_iterator( 0, this, 0 ); }
179 
181 
187  iterator find(const char* key);
189  const_iterator find(const char* key) const;
190 
192  bool erase(const char* key);
194 
196  iterator erase(iterator iter);
197 
199  void clear();
200 
202  int size() const { return _numEntries; }
203 
204 private: // Private Member Interface
205 
207  class Entry {
208  public: // Public Member Interface
210  Entry() : _next(0), _hashval(0), _keylen(0),
211  _val(_u._key,T())
212  { _u._pad = 0; }
213  ~Entry() {}
214  private: // Private Member Interface
216  Entry(const Entry&);
218  Entry& operator=(const Entry&);
219 
220  public:
222  int _hashval;
223  int _keylen;
225  union {
226  int _pad;
227  char _key[1];
228  } _u;
229  };
230 
232  PtexDict(const PtexDict&);
234  PtexDict& operator=(const PtexDict&);
235 
237  int hash(const char* key, int& keylen) const
238  {
239  // this is similar to perl's hash function
240  int hashval = 0;
241  const char* cp = key;
242  char c;
243  while ((c = *cp++)) hashval = hashval * 33 + c;
244  keylen = int(cp-key)-1;
245  return hashval;
246  }
247 
249  Entry** locate(const char* key, int& keylen, int& hashval) const
250  {
251  hashval = hash(key, keylen);
252  if (!_buckets) return 0;
253  for (Entry** e = &_buckets[hashval & _bucketMask]; *e; e=&(*e)->_next)
254  if ((*e)->_hashval == hashval && (*e)->_keylen == keylen &&
255  streq(key, (*e)->_u._key, keylen))
256  return e;
257  return 0;
258  }
259 
261 
264  static inline bool streq(const char* s1, const char* s2, int len)
265  {
266  // first make sure s1 is quad-aligned (s2 is always aligned)
267  if (((intptr_t)s1 & 3) == 0) {
268  int len4 = len >> 2;
269  while (len4--) {
270  if (*(int*)s1 != *(int*)s2) return 0;
271  s1 += 4; s2 += 4;
272  }
273  len &= 3;
274  }
275  while (len--) if (*s1++ != *s2++) return 0;
276  return 1;
277  }
278 
280  void grow();
281 
282 private: // Private Member data
283 
287  Entry** _buckets;
288 };
289 
290 
305 template<class T>
306 class PtexDict<T>::iterator {
307 public:
309  iterator() : _d(0), _e(0), _b(0) {}
310 
312  iterator(const iterator& iter) :
313  _d(iter._d), _e(iter._e), _b(iter._b) {}
315  inline iterator& operator=(const iterator& iter)
316  { _e = iter._e; _d = iter._d; _b = iter._b; return *this; }
317 
319  inline value_type& operator*() const { return getValue(); }
321  inline value_type* operator->() const { return &getValue(); }
322 
324  inline operator bool() { return _e != 0; }
325 
327  inline bool operator==(const iterator& iter) const
328  { return iter._e == _e; }
330  inline bool operator!=(const iterator& iter) const
331  { return iter._e != _e; }
333  inline bool operator==(const const_iterator& iter) const
334  { return iter._e == _e; }
336  inline bool operator!=(const const_iterator& iter) const
337  { return iter._e != _e; }
339  iterator& operator++(int);
340 
341 private: // Private interface
342 
344  iterator( Entry** e, const PtexDict* d, int b): _d(d), _e(e), _b(b) {}
345 
347  inline value_type& getValue() const{
348  if (_e) return (*_e)->_val;
349  else return _defaultVal;
350  }
351 
352  friend class PtexDict;
353  friend class const_iterator;
354  const PtexDict* _d;
355  Entry** _e;
356  int _b;
357 
359 };
360 
361 // define the static type for the iterator
363 
376 template<class T>
378 public:
380  const_iterator() : _d(0), _e(0), _b(0) {}
381 
384  _d(iter._d), _e(iter._e), _b(iter._b) {}
386  const_iterator(const iterator& iter) :
387  _d(iter._d), _e(iter._e), _b(iter._b) {}
390  { _e = iter._e; _d = iter._d; _b = iter._b; return *this; }
393  { _e = iter._e; _d = iter._d; _b = iter._b; return *this; }
394 
396  inline const value_type& operator*() const { return getValue(); }
398  inline const value_type* operator->() const { return &getValue(); }
399 
401  inline operator bool() { return _e != 0; }
402 
404  inline bool operator==(const iterator& iter) const
405  { return iter._e == _e; }
407  inline bool operator!=(const iterator& iter) const
408  { return iter._e != _e; }
410  inline bool operator==(const const_iterator& iter) const
411  { return iter._e == _e; }
413  inline bool operator!=(const const_iterator& iter) const
414  { return iter._e != _e; }
416  const_iterator& operator++(int);
417 
418 private: // Private interface
419 
421  const_iterator( Entry** e, const PtexDict* d, int b): _d(d),_e(e),_b(b) {}
422 
424  inline const value_type& getValue() const{
425  if (_e) return (*_e)->_val;
426  else return _defaultVal;
427  }
428 
429  friend class PtexDict;
430  friend class iterator;
431  const PtexDict* _d;
432  Entry** _e;
433  int _b;
434 
436 };
437 
438 // define the static type for the iterator
440 
441 template<class T>
443 {
444  if (_e) {
445  // move to next entry
446  _e = &(*_e)->_next;
447  if (!*_e) {
448  // move to next non-empty bucket
449  for (_b++; _b < _d->_numBuckets; _b++) {
450  _e = &_d->_buckets[_b];
451  if (*_e) return *this;
452  }
453  _e = 0;
454  }
455  }
456  return *this;
457 }
458 
459 template<class T>
461 {
462  if (_e) {
463  // move to next entry
464  _e = &(*_e)->_next;
465  if (!*_e) {
466  // move to next non-empty bucket
467  for (_b++; _b < _d->_numBuckets; _b++) {
468  _e = &_d->_buckets[_b];
469  if (*_e) return *this;
470  }
471  _e = 0;
472  }
473  }
474  return *this;
475 }
476 
477 template<class T>
478 typename PtexDict<T>::iterator PtexDict<T>::find(const char* key)
479 {
480  int keylen, hashval;
481  Entry** e = locate(key, keylen, hashval);
482 
484  if (e) return iterator( e, this, hashval & _bucketMask );
485  else return end();
486 }
487 
488 template<class T>
489 typename PtexDict<T>::const_iterator PtexDict<T>::find(const char* key) const
490 {
491  int keylen, hashval;
492  Entry** e = locate(key, keylen, hashval);
493 
495  if (e) return const_iterator( e, this, hashval & _bucketMask );
496  else return end();
497 }
498 
499 template<class T>
500 T& PtexDict<T>::operator[](const char* key)
501 {
502  int keylen, hashval;
503  Entry** e = locate(key, keylen, hashval);
504  if (e) return (*e)->_val.second;
505 
506  // create a new entry
507  _numEntries++;
508  if (_numEntries*2 >= _numBuckets) grow();
509 
510  // allocate a buffer big enough to hold Entry + (the key length )
511  // Note: the NULL character is already accounted for by Entry::_key's size
512  void* ebuf = malloc( sizeof(Entry) + (keylen) * sizeof(char) );
513  Entry* ne = new(ebuf) Entry; // note: placement new
514 
515  // Store the values in the Entry structure
516  Entry** slot = &_buckets[hashval & _bucketMask];
517  ne->_next = *slot; *slot = ne;
518  ne->_hashval = hashval;
519  ne->_keylen = keylen;
520 
521  // copy the string given into the new location
522  memcpy(ne->_u._key, key, keylen);
523  ne->_u._key[keylen] = '\0';
524  return ne->_val.second;
525 }
526 
527 
528 template<class T>
530 {
531  if (!_buckets) {
532  _numBuckets = 16;
533  _bucketMask = _numBuckets - 1;
534  _buckets = (Entry**) calloc(_numBuckets, sizeof(Entry*));
535  } else {
536  int newsize = _numBuckets * 2;
537  _bucketMask = newsize - 1;
538  Entry** newbuckets = (Entry**) calloc(newsize, sizeof(Entry*));
539  for (int i = 0; i < _numBuckets; i++) {
540  for (Entry* e = _buckets[i]; e;) {
541  Entry* _next = e->_next;
542  Entry** slot = &newbuckets[e->_hashval & _bucketMask];
543  e->_next = *slot; *slot = e;
544  e = _next;
545  }
546  }
547  free(_buckets);
548  _buckets = newbuckets;
549  _numBuckets = newsize;
550  }
551 }
552 
553 
554 template<class T>
555 bool PtexDict<T>::erase(const char* key)
556 {
557  iterator iter = find(key);
558  if (!iter) return false;
559 
560  erase(iter);
561  return true; // valid entry to remove
562 }
563 
564 
565 template<class T>
567 {
568  Entry** eptr = iter._e;
569  if (!eptr) return iter;
570 
571  // patch around deleted entry
572  Entry* e = *eptr;
573  Entry* next = e->_next;
574  if (!next) iter++; // advance iterator if at end of chain
575  *eptr = next;
576 
577  // destroy entry. This is a strange destroy but is necessary because of
578  // the way Entry() is allocated by using malloc above.
579  e->~Entry(); // note: explicit dtor call
580  free(e); // free memory allocated.
581  _numEntries--;
582 
583  return iter;
584 }
585 
586 
587 template<class T>
589 {
590  for (iterator i=begin(); i != end(); )
591  i = erase(i);
592  free(_buckets);
593  _buckets = 0;
594  _numEntries = 0;
595  _numBuckets = 0;
596 }
597 
598 #endif //PtexDict_h
int _numEntries
The number of entries in the dictionary.
Definition: PtexDict.h:284
static bool streq(const char *s1, const char *s2, int len)
Used for string compares, much faster then strcmp.
Definition: PtexDict.h:264
iterator(Entry **e, const PtexDict *d, int b)
Constructor Helper for inline creation.
Definition: PtexDict.h:344
T second
Reference to the data.
Definition: PtexDict.h:132
PtexDict()
Default contructor initializes the dictionary.
Definition: PtexDict.h:138
Entry ** _e
pointer to entry in table this iterator refs
Definition: PtexDict.h:432
const_iterator end() const
Const access to the end of the list.
Definition: PtexDict.h:178
bool operator==(const const_iterator &iter) const
For comparing equality of const_iterators.
Definition: PtexDict.h:410
bool operator==(const iterator &iter) const
For comparing equality of iterators.
Definition: PtexDict.h:327
bool erase(const char *key)
Will remove an entry. It will return TRUE if an entry was found.
Definition: PtexDict.h:555
Entry * _next
Pointer to the next element in the structure.
Definition: PtexDict.h:221
iterator end()
Returns an iterator referencing the end of the table.
Definition: PtexDict.h:162
const_iterator begin() const
Const access to the beginning of the list.
Definition: PtexDict.h:165
virtual ~PtexDict()
clears the entries in the dictionary
Definition: PtexDict.h:140
iterator(const iterator &iter)
Proper copy constructor implementation.
Definition: PtexDict.h:312
value_type & operator*() const
Operator for obtaining the value that the iterator references.
Definition: PtexDict.h:319
const_iterator()
Default Constructor.
Definition: PtexDict.h:380
union PtexDict::Entry::@0 _u
const value_type * operator->() const
Pointer reference operator.
Definition: PtexDict.h:398
void clear()
clear will remove all entries from the dictionary. O(n)
Definition: PtexDict.h:588
value_type * operator->() const
Pointer reference operator.
Definition: PtexDict.h:321
iterator begin()
Returns an iterator referencing the beginning of the table.
Definition: PtexDict.h:149
bool operator!=(const iterator &iter) const
For comparing inequality of iterators.
Definition: PtexDict.h:407
char _key[1]
1 is dummy length - actual size will be allocated
Definition: PtexDict.h:227
value_type(key_type f, const T &s)
Creation constructor.
Definition: PtexDict.h:129
bool operator==(const const_iterator &iter) const
For comparing equality of iterators.
Definition: PtexDict.h:333
value_type & getValue() const
simple helper function for retrieving the value from the Entry
Definition: PtexDict.h:347
int _numBuckets
The number of buckets in use.
Definition: PtexDict.h:285
Entry()
Default constructor initiaizes val with the defaul value.
Definition: PtexDict.h:210
int hash(const char *key, int &keylen) const
Returns the integer hash index for the key and length of the key.
Definition: PtexDict.h:237
static value_type _defaultVal
Default value.
Definition: PtexDict.h:358
This internal structure is used to store the dictionary elements.
Definition: PtexDict.h:207
value_type _val
The stored value of the hash table.
Definition: PtexDict.h:224
int size() const
Returns the number of entries in the dictionary. O(1) time to call.
Definition: PtexDict.h:202
int _b
bucket number this references
Definition: PtexDict.h:356
const char * key_type
This is the lookup type.
Definition: PtexDict.h:121
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 $
int _pad
for integer align of _key, for fast compares
Definition: PtexDict.h:226
iterator()
Default Constructor.
Definition: PtexDict.h:309
const_iterator & operator=(iterator &iter)
Proper assignment operator for iterator.
Definition: PtexDict.h:392
const value_type & operator*() const
Operator for obtaining the value that the const_iterator references.
Definition: PtexDict.h:396
iterator find(const char *key)
Locates an entry, without creating a new one.
Definition: PtexDict.h:478
iterator & operator++(int)
For advancing the iterator to the next element.
Definition: PtexDict.h:442
bool operator!=(const iterator &iter) const
For comparing inequality of iterators.
Definition: PtexDict.h:330
value_type()
Default constructor references default_value, with a 0 for first.
Definition: PtexDict.h:127
bool operator!=(const const_iterator &iter) const
For comparing inequality of iterators.
Definition: PtexDict.h:413
bool operator!=(const const_iterator &iter) const
For comparing inequality of iterators.
Definition: PtexDict.h:336
iterator & operator=(const iterator &iter)
Proper assignment operator.
Definition: PtexDict.h:315
const_iterator(const const_iterator &iter)
Proper copy constructor implementation for const_iterator.
Definition: PtexDict.h:383
Internal class used to provide a return value for the value type.
Definition: PtexDict.h:124
int _keylen
cached length of key
Definition: PtexDict.h:223
T mapped_type
The data type stored.
Definition: PtexDict.h:122
A string-keyed dictionary template, using a hash table.
Definition: PtexDict.h:111
const_iterator & operator++(int)
For advancing the iterator to the next element.
Definition: PtexDict.h:460
Entry & operator=(const Entry &)
Assignment operator prohibited by design.
void grow()
Used to increase the size of the table if necessary.
Definition: PtexDict.h:529
int _hashval
cached hashval of key
Definition: PtexDict.h:222
friend class const_iterator
Definition: PtexDict.h:119
const_iterator(const iterator &iter)
Conversion constructor for iterator.
Definition: PtexDict.h:386
int _b
bucket number this references
Definition: PtexDict.h:433
const PtexDict * _d
dictionary back reference
Definition: PtexDict.h:431
const_iterator & operator=(const const_iterator &iter)
Proper assignment operator for const_iterator.
Definition: PtexDict.h:389
PtexDict & operator=(const PtexDict &)
Assignment operator prohibited by design.
Entry ** _buckets
The pointer to the bucket structure.
Definition: PtexDict.h:287
Internal class used to provide iteration through the dictionary.
Definition: PtexDict.h:306
Entry ** _e
pointer to entry in table this iterator refs
Definition: PtexDict.h:355
bool operator==(const iterator &iter) const
For comparing equality of iterators.
Definition: PtexDict.h:404
const value_type & getValue() const
simple helper function for retrieving the value from the Entry
Definition: PtexDict.h:424
T & operator[](const char *key)
Locates an entry, creating a new one if necessary.
Definition: PtexDict.h:500
friend class iterator
forward declared class
Definition: PtexDict.h:117
Entry ** locate(const char *key, int &keylen, int &hashval) const
Returns a pointer to the desired entry, based on the key.
Definition: PtexDict.h:249
const key_type first
Reference to the key type.
Definition: PtexDict.h:131
static value_type _defaultVal
Default value.
Definition: PtexDict.h:435
const PtexDict * _d
dictionary back reference
Definition: PtexDict.h:354
Internal class used to provide iteration through the dictionary.
Definition: PtexDict.h:377
const_iterator(Entry **e, const PtexDict *d, int b)
Constructor Helper for inline creation.
Definition: PtexDict.h:421
int _bucketMask
The mask for the buckets.
Definition: PtexDict.h:286