diff --git a/build/premake/premake.lua b/build/premake/premake.lua index a48d05d64f..14f25070e7 100644 --- a/build/premake/premake.lua +++ b/build/premake/premake.lua @@ -518,6 +518,7 @@ function setup_all_libs () source_dirs = { "lib", + "lib/adts", "lib/allocators", "lib/external_libraries", "lib/file", diff --git a/source/lib/adts.h b/source/lib/adts.h deleted file mode 100644 index d2f2512338..0000000000 --- a/source/lib/adts.h +++ /dev/null @@ -1,655 +0,0 @@ -/* Copyright (c) 2010 Wildfire Games - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * useful Abstract Data Types not provided by STL. - */ - -#ifndef INCLUDED_ADTS -#define INCLUDED_ADTS - -#include "lib/fnv_hash.h" -#include "lib/bits.h" - -#include // strcmp - -//----------------------------------------------------------------------------- -// dynamic (grow-able) hash table -//----------------------------------------------------------------------------- - -template class DHT_Traits -{ -public: - static const size_t initial_entries = 16; - size_t hash(Key key) const; - bool equal(Key k1, Key k2) const; - Key get_key(T t) const; -}; - -template<> class DHT_Traits -{ -public: - static const size_t initial_entries = 512; - size_t hash(const char* key) const - { - return (size_t)fnv_lc_hash(key); - } - bool equal(const char* k1, const char* k2) const - { - return !strcmp(k1, k2); - } - const char* get_key(const char* t) const - { - return t; - } -}; - - -// intended for pointer types -template > -class DynHashTbl -{ - T* tbl; - u16 num_entries; - u16 max_entries; // when initialized, = 2**n for faster modulo - Traits tr; - - T& get_slot(Key key) const - { - size_t hash = tr.hash(key); - ENSURE(max_entries != 0); // otherwise, mask will be incorrect - const size_t mask = max_entries-1; - for(;;) - { - T& t = tbl[hash & mask]; - // empty slot encountered => not found - if(!t) - return t; - // keys are actually equal => found it - if(tr.equal(key, tr.get_key(t))) - return t; - // keep going (linear probing) - hash++; - } - } - - void expand_tbl() - { - // alloc a new table (but don't assign it to unless successful) - T* old_tbl = tbl; - tbl = (T*)calloc(max_entries*2, sizeof(T)); - if(!tbl) - { - tbl = old_tbl; - throw std::bad_alloc(); - } - - max_entries *= 2; - // must be set before get_slot - - // newly initialized, nothing to copy - done - if(!old_tbl) - return; - - // re-hash from old table into the new one - for(size_t i = 0; i < max_entries/2u; i++) - { - T t = old_tbl[i]; - if(t) - get_slot(tr.get_key(t)) = t; - } - free(old_tbl); - } - - -public: - - DynHashTbl() - { - tbl = 0; - clear(); - } - - ~DynHashTbl() - { - free(tbl); - } - - void clear() - { - // must remain usable after calling clear, so shrink the table to - // its initial size but don't deallocate it completely - SAFE_FREE(tbl); - num_entries = 0; - // rationale: must not set to 0 because expand_tbl only doubles the size. - // don't keep the previous size when clearing because it may have become - // huge and there is no provision for shrinking. - max_entries = tr.initial_entries/2; // will be doubled in expand_tbl - expand_tbl(); - } - - void insert(const Key key, const T t) - { - // more than 75% full - increase table size. - // do so before determining slot; this will invalidate previous pnodes. - if(num_entries*4 >= max_entries*3) - expand_tbl(); - - T& slot = get_slot(key); - ENSURE(slot == 0); // not already present - slot = t; - num_entries++; - } - - T find(Key key) const - { - return get_slot(key); - } - - size_t size() const - { - return num_entries; - } - - - class iterator - { - public: - typedef std::forward_iterator_tag iterator_category; - typedef T value_type; - typedef ptrdiff_t difference_type; - typedef const T* pointer; - typedef const T& reference; - - iterator() - { - } - iterator(T* pos_, T* end_) : pos(pos_), end(end_) - { - } - T& operator*() const - { - return *pos; - } - iterator& operator++() // pre - { - do - pos++; - while(pos != end && *pos == 0); - return (*this); - } - bool operator==(const iterator& rhs) const - { - return pos == rhs.pos; - } - bool operator<(const iterator& rhs) const - { - return (pos < rhs.pos); - } - - // derived - const T* operator->() const - { - return &**this; - } - bool operator!=(const iterator& rhs) const - { - return !(*this == rhs); - } - iterator operator++(int) // post - { - iterator tmp = *this; ++*this; return tmp; - } - - protected: - T* pos; - T* end; - // only used when incrementing (avoid going beyond end of table) - }; - - iterator begin() const - { - T* pos = tbl; - while(pos != tbl+max_entries && *pos == 0) - pos++; - return iterator(pos, tbl+max_entries); - } - iterator end() const - { - return iterator(tbl+max_entries, 0); - } -}; - - -//----------------------------------------------------------------------------- -// FIFO bit queue -//----------------------------------------------------------------------------- - -struct BitBuf -{ - uintptr_t buf; - uintptr_t cur; // bit to be appended (toggled by add()) - size_t len; // |buf| [bits] - - void reset() - { - buf = 0; - cur = 0; - len = 0; - } - - // toggle current bit if desired, and add to buffer (new bit is LSB) - void add(uintptr_t toggle) - { - cur ^= toggle; - buf <<= 1; - buf |= cur; - len++; - } - - // extract LS n bits - size_t extract(uintptr_t n) - { - const uintptr_t bits = buf & bit_mask(n); - buf >>= n; - - return bits; - } -}; - - -//----------------------------------------------------------------------------- -// ring buffer - static array, accessible modulo n -//----------------------------------------------------------------------------- - -template class RingBuf -{ - size_t size_; // # of entries in buffer - size_t head; // index of oldest item - size_t tail; // index of newest item - T data[n]; - -public: - RingBuf() : data() { clear(); } - void clear() { size_ = 0; head = 0; tail = n-1; } - - size_t size() const { return size_; } - bool empty() const { return size_ == 0; } - - const T& operator[](int ofs) const - { - ENSURE(!empty()); - size_t idx = (size_t)(head + ofs); - return data[idx % n]; - } - T& operator[](int ofs) - { - ENSURE(!empty()); - size_t idx = (size_t)(head + ofs); - return data[idx % n]; - } - - T& front() - { - ENSURE(!empty()); - return data[head]; - } - const T& front() const - { - ENSURE(!empty()); - return data[head]; - } - T& back() - { - ENSURE(!empty()); - return data[tail]; - } - const T& back() const - { - ENSURE(!empty()); - return data[tail]; - } - - void push_back(const T& item) - { - if(size_ < n) - size_++; - // do not complain - overwriting old values is legit - // (e.g. sliding window). - else - head = (head + 1) % n; - - tail = (tail + 1) % n; - data[tail] = item; - } - - void pop_front() - { - if(size_ != 0) - { - size_--; - head = (head + 1) % n; - } - else - ENSURE(0); // underflow - } - - class iterator - { - public: - typedef std::random_access_iterator_tag iterator_category; - typedef T value_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef T& reference; - - iterator() : data(0), pos(0) - {} - iterator(T* data_, size_t pos_) : data(data_), pos(pos_) - {} - T& operator[](int idx) const - { return data[(pos+idx) % n]; } - T& operator*() const - { return data[pos % n]; } - T* operator->() const - { return &**this; } - iterator& operator++() // pre - { ++pos; return (*this); } - iterator operator++(int) // post - { iterator tmp = *this; ++*this; return tmp; } - bool operator==(const iterator& rhs) const - { return data == rhs.data && pos == rhs.pos; } - bool operator!=(const iterator& rhs) const - { return !(*this == rhs); } - bool operator<(const iterator& rhs) const - { return (pos < rhs.pos); } - iterator& operator+=(difference_type ofs) - { pos += ofs; return *this; } - iterator& operator-=(difference_type ofs) - { return (*this += -ofs); } - iterator operator+(difference_type ofs) const - { iterator tmp = *this; return (tmp += ofs); } - iterator operator-(difference_type ofs) const - { iterator tmp = *this; return (tmp -= ofs); } - difference_type operator-(const iterator right) const - { return (difference_type)(pos - right.pos); } - - protected: - T* data; - size_t pos; - // not mod-N so that begin != end when buffer is full. - }; - - class const_iterator - { - public: - typedef std::random_access_iterator_tag iterator_category; - typedef T value_type; - typedef ptrdiff_t difference_type; - typedef const T* pointer; - typedef const T& reference; - - const_iterator() : data(0), pos(0) - {} - const_iterator(const T* data_, size_t pos_) : data(data_), pos(pos_) - {} - const T& operator[](int idx) const - { return data[(pos+idx) % n]; } - const T& operator*() const - { return data[pos % n]; } - const T* operator->() const - { return &**this; } - const_iterator& operator++() // pre - { ++pos; return (*this); } - const_iterator operator++(int) // post - { const_iterator tmp = *this; ++*this; return tmp; } - bool operator==(const const_iterator& rhs) const - { return data == rhs.data && pos == rhs.pos; } - bool operator!=(const const_iterator& rhs) const - { return !(*this == rhs); } - bool operator<(const const_iterator& rhs) const - { return (pos < rhs.pos); } - iterator& operator+=(difference_type ofs) - { pos += ofs; return *this; } - iterator& operator-=(difference_type ofs) - { return (*this += -ofs); } - iterator operator+(difference_type ofs) const - { iterator tmp = *this; return (tmp += ofs); } - iterator operator-(difference_type ofs) const - { iterator tmp = *this; return (tmp -= ofs); } - difference_type operator-(const iterator right) const - { return (difference_type)(pos - right.pos); } - - protected: - const T* data; - size_t pos; - // not mod-N so that begin != end when buffer is full. - }; - - iterator begin() - { - return iterator(data, head); - } - const_iterator begin() const - { - return const_iterator(data, head); - } - iterator end() - { - return iterator(data, head+size_); - } - const_iterator end() const - { - return const_iterator(data, head+size_); - } -}; - - -// Matei's slightly friendlier hashtable for value-type keys -template -class MateiHashTbl -{ - static const size_t initial_entries = 16; - - struct Entry { - bool valid; - K key; - T value; - Entry() : valid(false) {} - Entry(const K& k, T v) { key=k; value=v; } - Entry& operator=(const Entry& other) { - valid = other.valid; - key = other.key; - value = other.value; - return *this; - } - }; - - Entry* tbl; - u16 num_entries; - u16 max_entries; // when initialized, = 2**n for faster modulo - HashCompare hashFunc; - - Entry& get_slot(K key) const - { - size_t hash = hashFunc(key); - //ENSURE(max_entries != 0); // otherwise, mask will be incorrect - const size_t mask = max_entries-1; - int stride = 1; // for quadratic probing - for(;;) - { - Entry& e = tbl[hash & mask]; - // empty slot encountered => not found - if(!e.valid) - return e; - // keys are actually equal => found it - if(e.key == key) - return e; - // keep going (quadratic probing) - hash += stride; - stride++; - } - } - - void expand_tbl() - { - // alloc a new table (but don't assign it to unless successful) - Entry* old_tbl = tbl; - tbl = new Entry[max_entries*2]; - if(!tbl) - { - tbl = old_tbl; - throw std::bad_alloc(); - } - - max_entries += max_entries; - // must be set before get_slot - - // newly initialized, nothing to copy - done - if(!old_tbl) - return; - - // re-hash from old table into the new one - for(size_t i = 0; i < max_entries/2u; i++) - { - Entry& e = old_tbl[i]; - if(e.valid) - get_slot(e.key) = e; - } - delete[] old_tbl; - } - - void delete_contents() - { - if(tbl) - { - delete[] tbl; - tbl = 0; - } - } - -public: - - MateiHashTbl() - { - tbl = 0; - num_entries = 0; - max_entries = initial_entries/2; // will be doubled in expand_tbl - //ENSURE(is_pow2(max_entries)); - expand_tbl(); - } - - ~MateiHashTbl() - { - delete_contents(); - } - - void clear() - { - delete_contents(); - num_entries = 0; - // rationale: must not set to 0 because expand_tbl only doubles the size. - // don't keep the previous size because it may have become huge and - // there is no provision for shrinking. - max_entries = initial_entries/2; // will be doubled in expand_tbl - expand_tbl(); - } - - bool contains(const K& key) const - { - return get_slot(key).valid; - } - - T& operator[](const K& key) - { - Entry* slot = &get_slot(key); - if(slot->valid) - { - return slot->value; - } - - // no element exists for this key - insert it into the table - // (this is slightly different from STL::hash_map in that we insert a new element - // on a get for a nonexistent key, but hopefully that's not a problem) - - // if more than 75% full, increase table size and find slot again - if(num_entries*4 >= max_entries*2) - { - expand_tbl(); - slot = &get_slot(key); // find slot again since we expanded - } - - slot->valid = true; - slot->key = key; - num_entries++; - return slot->value; - } - - size_t size() const - { - return num_entries; - } - - // Not an STL iterator, more like a Java one - // Usage: for(HashTable::Iterator it(table); it.valid(); it.advance()) { do stuff to it.key() and it.value() } - class Iterator - { - private: - Entry* pos; - Entry* end; - - public: - Iterator(const MateiHashTbl& ht) - { - pos = ht.tbl; - end = ht.tbl + ht.max_entries; - while(pos < end && !pos->valid) - pos++; - }; - - bool valid() const - { - return pos < end; - } - - void advance() - { - do { - pos++; - } - while(pos < end && !pos->valid); - } - - const K& key() - { - return pos->key; - } - - T& value() - { - return pos->value; - } - }; -}; - - -#endif // #ifndef INCLUDED_ADTS diff --git a/source/lib/adts/bit_buf.h b/source/lib/adts/bit_buf.h new file mode 100644 index 0000000000..15cb644a3b --- /dev/null +++ b/source/lib/adts/bit_buf.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2011 Wildfire Games + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * FIFO bit queue + */ + +#ifndef INCLUDED_ADTS_BIT_BUF +#define INCLUDED_ADTS_BIT_BUF + +#include "lib/bits.h" + +struct BitBuf +{ + uintptr_t buf; + uintptr_t cur; // bit to be appended (toggled by add()) + size_t len; // |buf| [bits] + + void reset() + { + buf = 0; + cur = 0; + len = 0; + } + + // toggle current bit if desired, and add to buffer (new bit is LSB) + void add(uintptr_t toggle) + { + cur ^= toggle; + buf <<= 1; + buf |= cur; + len++; + } + + // extract LS n bits + size_t extract(uintptr_t n) + { + const uintptr_t bits = buf & bit_mask(n); + buf >>= n; + + return bits; + } +}; + +#endif // #ifndef INCLUDED_ADTS_BIT_BUF diff --git a/source/lib/cache_adt.h b/source/lib/adts/cache_adt.h similarity index 100% rename from source/lib/cache_adt.h rename to source/lib/adts/cache_adt.h diff --git a/source/lib/adts/dyn_hash_tbl.h b/source/lib/adts/dyn_hash_tbl.h new file mode 100644 index 0000000000..ba2e50cd99 --- /dev/null +++ b/source/lib/adts/dyn_hash_tbl.h @@ -0,0 +1,238 @@ +/* Copyright (c) 2011 Wildfire Games + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * dynamic (grow-able) hash table + */ + +#ifndef INCLUDED_ADTS_DYN_HASH_TBL +#define INCLUDED_ADTS_DYN_HASH_TBL + +#include // strcmp + +#include "lib/fnv_hash.h" + +template class DHT_Traits +{ +public: + static const size_t initial_entries = 16; + size_t hash(Key key) const; + bool equal(Key k1, Key k2) const; + Key get_key(T t) const; +}; + +template<> class DHT_Traits +{ +public: + static const size_t initial_entries = 512; + size_t hash(const char* key) const + { + return (size_t)fnv_lc_hash(key); + } + bool equal(const char* k1, const char* k2) const + { + return !strcmp(k1, k2); + } + const char* get_key(const char* t) const + { + return t; + } +}; + + +// intended for pointer types +template > +class DynHashTbl +{ + T* tbl; + u16 num_entries; + u16 max_entries; // when initialized, = 2**n for faster modulo + Traits tr; + + T& get_slot(Key key) const + { + size_t hash = tr.hash(key); + ENSURE(max_entries != 0); // otherwise, mask will be incorrect + const size_t mask = max_entries-1; + for(;;) + { + T& t = tbl[hash & mask]; + // empty slot encountered => not found + if(!t) + return t; + // keys are actually equal => found it + if(tr.equal(key, tr.get_key(t))) + return t; + // keep going (linear probing) + hash++; + } + } + + void expand_tbl() + { + // alloc a new table (but don't assign it to unless successful) + T* old_tbl = tbl; + tbl = (T*)calloc(max_entries*2, sizeof(T)); + if(!tbl) + { + tbl = old_tbl; + throw std::bad_alloc(); + } + + max_entries *= 2; + // must be set before get_slot + + // newly initialized, nothing to copy - done + if(!old_tbl) + return; + + // re-hash from old table into the new one + for(size_t i = 0; i < max_entries/2u; i++) + { + T t = old_tbl[i]; + if(t) + get_slot(tr.get_key(t)) = t; + } + free(old_tbl); + } + + +public: + + DynHashTbl() + { + tbl = 0; + clear(); + } + + ~DynHashTbl() + { + free(tbl); + } + + void clear() + { + // must remain usable after calling clear, so shrink the table to + // its initial size but don't deallocate it completely + SAFE_FREE(tbl); + num_entries = 0; + // rationale: must not set to 0 because expand_tbl only doubles the size. + // don't keep the previous size when clearing because it may have become + // huge and there is no provision for shrinking. + max_entries = tr.initial_entries/2; // will be doubled in expand_tbl + expand_tbl(); + } + + void insert(const Key key, const T t) + { + // more than 75% full - increase table size. + // do so before determining slot; this will invalidate previous pnodes. + if(num_entries*4 >= max_entries*3) + expand_tbl(); + + T& slot = get_slot(key); + ENSURE(slot == 0); // not already present + slot = t; + num_entries++; + } + + T find(Key key) const + { + return get_slot(key); + } + + size_t size() const + { + return num_entries; + } + + + class iterator + { + public: + typedef std::forward_iterator_tag iterator_category; + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef const T* pointer; + typedef const T& reference; + + iterator() + { + } + iterator(T* pos_, T* end_) : pos(pos_), end(end_) + { + } + T& operator*() const + { + return *pos; + } + iterator& operator++() // pre + { + do + pos++; + while(pos != end && *pos == 0); + return (*this); + } + bool operator==(const iterator& rhs) const + { + return pos == rhs.pos; + } + bool operator<(const iterator& rhs) const + { + return (pos < rhs.pos); + } + + // derived + const T* operator->() const + { + return &**this; + } + bool operator!=(const iterator& rhs) const + { + return !(*this == rhs); + } + iterator operator++(int) // post + { + iterator tmp = *this; ++*this; return tmp; + } + + protected: + T* pos; + T* end; + // only used when incrementing (avoid going beyond end of table) + }; + + iterator begin() const + { + T* pos = tbl; + while(pos != tbl+max_entries && *pos == 0) + pos++; + return iterator(pos, tbl+max_entries); + } + iterator end() const + { + return iterator(tbl+max_entries, 0); + } +}; + + +#endif // #ifndef INCLUDED_ADTS_DYN_HASH_TBL diff --git a/source/lib/adts/ring_buf.h b/source/lib/adts/ring_buf.h new file mode 100644 index 0000000000..4e91dbc8ce --- /dev/null +++ b/source/lib/adts/ring_buf.h @@ -0,0 +1,212 @@ +/* Copyright (c) 2011 Wildfire Games + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * static array, accessible modulo n + */ + +#ifndef INCLUDED_ADTS_RING_BUF +#define INCLUDED_ADTS_RING_BUF + +template class RingBuf +{ + size_t size_; // # of entries in buffer + size_t head; // index of oldest item + size_t tail; // index of newest item + T data[n]; + +public: + RingBuf() : data() { clear(); } + void clear() { size_ = 0; head = 0; tail = n-1; } + + size_t size() const { return size_; } + bool empty() const { return size_ == 0; } + + const T& operator[](int ofs) const + { + ENSURE(!empty()); + size_t idx = (size_t)(head + ofs); + return data[idx % n]; + } + T& operator[](int ofs) + { + ENSURE(!empty()); + size_t idx = (size_t)(head + ofs); + return data[idx % n]; + } + + T& front() + { + ENSURE(!empty()); + return data[head]; + } + const T& front() const + { + ENSURE(!empty()); + return data[head]; + } + T& back() + { + ENSURE(!empty()); + return data[tail]; + } + const T& back() const + { + ENSURE(!empty()); + return data[tail]; + } + + void push_back(const T& item) + { + if(size_ < n) + size_++; + // do not complain - overwriting old values is legit + // (e.g. sliding window). + else + head = (head + 1) % n; + + tail = (tail + 1) % n; + data[tail] = item; + } + + void pop_front() + { + if(size_ != 0) + { + size_--; + head = (head + 1) % n; + } + else + ENSURE(0); // underflow + } + + class iterator + { + public: + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef T& reference; + + iterator() : data(0), pos(0) + {} + iterator(T* data_, size_t pos_) : data(data_), pos(pos_) + {} + T& operator[](int idx) const + { return data[(pos+idx) % n]; } + T& operator*() const + { return data[pos % n]; } + T* operator->() const + { return &**this; } + iterator& operator++() // pre + { ++pos; return (*this); } + iterator operator++(int) // post + { iterator tmp = *this; ++*this; return tmp; } + bool operator==(const iterator& rhs) const + { return data == rhs.data && pos == rhs.pos; } + bool operator!=(const iterator& rhs) const + { return !(*this == rhs); } + bool operator<(const iterator& rhs) const + { return (pos < rhs.pos); } + iterator& operator+=(difference_type ofs) + { pos += ofs; return *this; } + iterator& operator-=(difference_type ofs) + { return (*this += -ofs); } + iterator operator+(difference_type ofs) const + { iterator tmp = *this; return (tmp += ofs); } + iterator operator-(difference_type ofs) const + { iterator tmp = *this; return (tmp -= ofs); } + difference_type operator-(const iterator right) const + { return (difference_type)(pos - right.pos); } + + protected: + T* data; + size_t pos; + // not mod-N so that begin != end when buffer is full. + }; + + class const_iterator + { + public: + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef const T* pointer; + typedef const T& reference; + + const_iterator() : data(0), pos(0) + {} + const_iterator(const T* data_, size_t pos_) : data(data_), pos(pos_) + {} + const T& operator[](int idx) const + { return data[(pos+idx) % n]; } + const T& operator*() const + { return data[pos % n]; } + const T* operator->() const + { return &**this; } + const_iterator& operator++() // pre + { ++pos; return (*this); } + const_iterator operator++(int) // post + { const_iterator tmp = *this; ++*this; return tmp; } + bool operator==(const const_iterator& rhs) const + { return data == rhs.data && pos == rhs.pos; } + bool operator!=(const const_iterator& rhs) const + { return !(*this == rhs); } + bool operator<(const const_iterator& rhs) const + { return (pos < rhs.pos); } + iterator& operator+=(difference_type ofs) + { pos += ofs; return *this; } + iterator& operator-=(difference_type ofs) + { return (*this += -ofs); } + iterator operator+(difference_type ofs) const + { iterator tmp = *this; return (tmp += ofs); } + iterator operator-(difference_type ofs) const + { iterator tmp = *this; return (tmp -= ofs); } + difference_type operator-(const iterator right) const + { return (difference_type)(pos - right.pos); } + + protected: + const T* data; + size_t pos; + // not mod-N so that begin != end when buffer is full. + }; + + iterator begin() + { + return iterator(data, head); + } + const_iterator begin() const + { + return const_iterator(data, head); + } + iterator end() + { + return iterator(data, head+size_); + } + const_iterator end() const + { + return const_iterator(data, head+size_); + } +}; + +#endif // #ifndef INCLUDED_ADTS_RING_BUF diff --git a/source/lib/debug.h b/source/lib/debug.h index 94f87ea73e..9facc20118 100644 --- a/source/lib/debug.h +++ b/source/lib/debug.h @@ -303,7 +303,7 @@ LIB_API LibError debug_WriteCrashlog(const wchar_t* text); #define ASSERT(expr) ENSURE(expr) #ifdef NDEBUG # undef ASSERT -# define ASSERT(expr) (void)expr +# define ASSERT(expr) #endif /** diff --git a/source/lib/file/vfs/file_cache.cpp b/source/lib/file/vfs/file_cache.cpp index 1203d531f5..a91ca6e917 100644 --- a/source/lib/file/vfs/file_cache.cpp +++ b/source/lib/file/vfs/file_cache.cpp @@ -30,7 +30,7 @@ #include "lib/external_libraries/suppress_boost_warnings.h" #include "lib/file/common/file_stats.h" -#include "lib/cache_adt.h" // Cache +#include "lib/adts/cache_adt.h" #include "lib/bits.h" // round_up #include "lib/allocators/allocator_checker.h" #include "lib/allocators/shared_ptr.h" diff --git a/source/lib/sysdep/os/win/whrt/whrt.cpp b/source/lib/sysdep/os/win/whrt/whrt.cpp index ef74e34bb2..0fe0797677 100644 --- a/source/lib/sysdep/os/win/whrt/whrt.cpp +++ b/source/lib/sysdep/os/win/whrt/whrt.cpp @@ -33,7 +33,6 @@ #include "lib/sysdep/os/win/win.h" #include "lib/sysdep/os/win/winit.h" #include "lib/sysdep/acpi.h" -//#include "lib/adts.h" #include "lib/bits.h" #include "lib/sysdep/os/win/whrt/counter.h" diff --git a/source/lib/tests/test_adts.h b/source/lib/tests/test_adts.h index b4b3873277..371cc54848 100644 --- a/source/lib/tests/test_adts.h +++ b/source/lib/tests/test_adts.h @@ -22,7 +22,7 @@ #include "lib/self_test.h" -#include "lib/adts.h" +#include "lib/adts/ring_buf.h" #include "lib/rand.h" class TestRingbuf : public CxxTest::TestSuite diff --git a/source/lib/tests/test_cache_adt.h b/source/lib/tests/test_cache_adt.h index d08a9aa5dc..1351b82714 100644 --- a/source/lib/tests/test_cache_adt.h +++ b/source/lib/tests/test_cache_adt.h @@ -22,7 +22,7 @@ #include "lib/self_test.h" -#include "lib/cache_adt.h" +#include "lib/adts/cache_adt.h" #include "lib/rand.h" class TestCache: public CxxTest::TestSuite diff --git a/source/ps/Profile.h b/source/ps/Profile.h index 8c2f801989..8ee102806e 100644 --- a/source/ps/Profile.h +++ b/source/ps/Profile.h @@ -24,7 +24,7 @@ #include -#include "lib/adts.h" +#include "lib/adts/ring_buf.h" #include "ps/Singleton.h" #include "ps/ThreadUtil.h"