#ifndef UTIL_H #define UTIL_H #include #include #include #include // makes dynamically allocated objects zero-initialised struct zero_initialised { void *operator new (size_t s) { void *p = malloc (s); memset (p, 0, s); return p; } void *operator new[] (size_t s) { void *p = malloc (s); memset (p, 0, s); return p; } void operator delete (void *p, size_t s) { free (p); } void operator delete[] (void *p, size_t s) { free (p); } }; /** * Mostly the same as std::vector, but erase can reorder * the elements, making insert/remove O(1) instead of O(n). * * NOTE: only some forms of erase are available * (Taken from Crossfire TRT http://cf.schmorp.de/) */ template > struct unordered_vector : std::vector { typedef typename unordered_vector::iterator iterator; void erase (unsigned pos) { if (pos < this->size () - 1) (*this)[pos] = (*this)[this->size () - 1]; this->pop_back (); } void erase (iterator pos) { erase ((unsigned)(pos - this->begin ())); } void insert (T const &val) { push_back (val); } }; /** * The following templates find a sufficiently large integer type to contain * the given number of bits. * * Usage: * * unsigned_type<16>::type a; // 16-bit unsigned if available (probably unsigned short) * signed_type<8>::type a; // 8-bit signed if available (probably char) */ // Empty class if everything failed struct empty_base { }; // To allow inheritance from this and get the integer type out template struct identity { typedef T type; }; /** * The following two templates are a compile-time if-statement. */ template struct If { typedef Then ret; }; template struct If { typedef Else ret; }; // Looks whether the desired type exists template struct type_if_size : If= bits, identity, Else>::ret { }; template struct unsigned_type : type_if_size > > > { }; template struct signed_type : type_if_size > > > { }; template > struct indexing_vector : std::vector { typedef typename indexing_vector::size_type size_type; typedef typename indexing_vector::iterator iterator; void erase (T *obj) { size_type pos = obj->*index - 1; obj->*index = 0; if (pos <= this->size ()) { (*this)[pos] = (*this)[this->size () - 1]; (*this)[pos]->*index = pos; } this->pop_back (); } void insert (T *obj) { this->push_back (obj); obj->*index = this->size (); } }; struct str_hash { std::size_t operator () (char const *s) const { unsigned long hash = 0; // use the one-at-a-time hash function. // see http://burtleburtle.net/bob/hash/doobs.html while (*s) { hash += *s++; hash += hash << 10; hash ^= hash >> 6; } hash += hash << 3; hash ^= hash >> 11; hash += hash << 15; return hash; } }; struct str_eq { bool operator () (char const * const s1, char const * const s2) const { if (s1 == NULL || s2 == NULL) throw nullpointer_exception (); return !strcmp (s1, s2); } }; struct str_lt { bool operator () (char const * const s1, char const * const s2) const { if (s1 == NULL || s2 == NULL) throw nullpointer_exception (); return strcmp (s1, s2) < 0; } }; #endif