|
|
|
|
|
#ifndef DLIB_HASH_TABLE_KERNEl_2_ |
|
#define DLIB_HASH_TABLE_KERNEl_2_ |
|
|
|
#include "hash_table_kernel_abstract.h" |
|
#include "../general_hash/general_hash.h" |
|
#include "../algs.h" |
|
#include "../interfaces/map_pair.h" |
|
#include "../interfaces/enumerable.h" |
|
#include "../interfaces/remover.h" |
|
#include "../assert.h" |
|
#include "../serialize.h" |
|
#include <functional> |
|
|
|
namespace dlib |
|
{ |
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager = default_memory_manager, |
|
typename compare = std::less<domain> |
|
> |
|
class hash_table_kernel_2 : public enumerable<map_pair<domain,range> >, |
|
public pair_remover<domain,range> |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
typedef domain domain_type; |
|
typedef range range_type; |
|
typedef compare compare_type; |
|
typedef mem_manager mem_manager_type; |
|
|
|
explicit hash_table_kernel_2( |
|
unsigned long expnum |
|
); |
|
|
|
virtual ~hash_table_kernel_2( |
|
) |
|
{ pool.deallocate_array(table); } |
|
|
|
void clear( |
|
); |
|
|
|
unsigned long count ( |
|
const domain& item |
|
) const; |
|
|
|
inline void add ( |
|
domain& d, |
|
range& r |
|
); |
|
|
|
void destroy ( |
|
const domain& d |
|
); |
|
|
|
void remove ( |
|
const domain& d, |
|
domain& d_copy, |
|
range& r |
|
); |
|
|
|
const range* operator[] ( |
|
const domain& item |
|
) const; |
|
|
|
range* operator[] ( |
|
const domain& item |
|
); |
|
|
|
inline void swap ( |
|
hash_table_kernel_2& item |
|
); |
|
|
|
|
|
void remove_any ( |
|
domain& d, |
|
range& r |
|
); |
|
|
|
|
|
inline size_t size ( |
|
) const; |
|
|
|
inline bool at_start ( |
|
) const; |
|
|
|
inline void reset ( |
|
) const; |
|
|
|
bool current_element_valid ( |
|
) const; |
|
|
|
inline const map_pair<domain,range>& element ( |
|
) const; |
|
|
|
inline map_pair<domain,range>& element ( |
|
); |
|
|
|
bool move_next ( |
|
) const; |
|
|
|
private: |
|
|
|
|
|
typename mem_manager::template rebind<bst_base>::other pool; |
|
unsigned long mask; |
|
unsigned long hash_size; |
|
unsigned long num_of_buckets; |
|
bst_base* table; |
|
general_hash<domain> hash; |
|
mutable bst_base* current_bucket; |
|
mutable bool at_start_; |
|
compare comp; |
|
|
|
|
|
hash_table_kernel_2(hash_table_kernel_2&); |
|
hash_table_kernel_2& operator=(hash_table_kernel_2&); |
|
|
|
}; |
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
inline void swap ( |
|
hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>& a, |
|
hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>& b |
|
) { a.swap(b); } |
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
void deserialize ( |
|
hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>& item, |
|
std::istream& in |
|
) |
|
{ |
|
try |
|
{ |
|
item.clear(); |
|
unsigned long size; |
|
deserialize(size,in); |
|
domain d; |
|
range r; |
|
for (unsigned long i = 0; i < size; ++i) |
|
{ |
|
deserialize(d,in); |
|
deserialize(r,in); |
|
item.add(d,r); |
|
} |
|
} |
|
catch (serialization_error& e) |
|
{ |
|
item.clear(); |
|
throw serialization_error(e.info + "\n while deserializing object of type hash_table_kernel_2"); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
hash_table_kernel_2( |
|
unsigned long expnum |
|
) : |
|
hash_size(0), |
|
current_bucket(0), |
|
at_start_(true) |
|
{ |
|
|
|
num_of_buckets = 1; |
|
while (expnum != 0) |
|
{ |
|
--expnum; |
|
num_of_buckets <<= 1; |
|
} |
|
mask = num_of_buckets-1; |
|
|
|
table = pool.allocate_array(num_of_buckets); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
void hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
clear( |
|
) |
|
{ |
|
if (hash_size != 0) |
|
{ |
|
hash_size = 0; |
|
for (unsigned long i = 0; i < num_of_buckets; ++i) |
|
table[i].clear(); |
|
} |
|
|
|
reset(); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
size_t hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
size( |
|
) const |
|
{ |
|
return hash_size; |
|
} |
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
unsigned long hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
count( |
|
const domain& item |
|
) const |
|
{ |
|
return table[hash(item)&mask].count(item); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
void hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
destroy( |
|
const domain& item |
|
) |
|
{ |
|
table[hash(item)&mask].destroy(item); |
|
--hash_size; |
|
|
|
|
|
reset(); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
void hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
add( |
|
domain& d, |
|
range& r |
|
) |
|
{ |
|
table[hash(d)&mask].add(d,r); |
|
++hash_size; |
|
|
|
|
|
reset(); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
void hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
remove( |
|
const domain& d, |
|
domain& d_copy, |
|
range& r |
|
) |
|
{ |
|
table[hash(d)&mask].remove(d,d_copy,r); |
|
--hash_size; |
|
|
|
|
|
reset(); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
void hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
remove_any( |
|
domain& d, |
|
range& r |
|
) |
|
{ |
|
unsigned long i = 0; |
|
while (table[i].size() == 0) |
|
{ |
|
++i; |
|
} |
|
table[i].remove_any(d,r); |
|
--hash_size; |
|
|
|
|
|
reset(); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
const range* hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
operator[]( |
|
const domain& d |
|
) const |
|
{ |
|
return table[hash(d)&mask][d]; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
range* hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
operator[]( |
|
const domain& d |
|
) |
|
{ |
|
return table[hash(d)&mask][d]; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
void hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
swap( |
|
hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>& item |
|
) |
|
{ |
|
pool.swap(item.pool); |
|
exchange(mask,item.mask); |
|
exchange(hash_size,item.hash_size); |
|
exchange(num_of_buckets,item.num_of_buckets); |
|
exchange(table,item.table); |
|
exchange(current_bucket,item.current_bucket); |
|
exchange(at_start_,item.at_start_); |
|
exchange(comp,item.comp); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
bool hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
at_start ( |
|
) const |
|
{ |
|
return at_start_; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
void hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
reset ( |
|
) const |
|
{ |
|
at_start_ = true; |
|
if (current_bucket != 0) |
|
{ |
|
current_bucket->reset(); |
|
current_bucket = 0; |
|
} |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
bool hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
current_element_valid ( |
|
) const |
|
{ |
|
return (current_bucket != 0); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
const map_pair<domain,range>& hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
element ( |
|
) const |
|
{ |
|
return current_bucket->element(); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
map_pair<domain,range>& hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
element ( |
|
) |
|
{ |
|
return current_bucket->element(); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename domain, |
|
typename range, |
|
typename bst_base, |
|
typename mem_manager, |
|
typename compare |
|
> |
|
bool hash_table_kernel_2<domain,range,bst_base,mem_manager,compare>:: |
|
move_next ( |
|
) const |
|
{ |
|
if (at_start_) |
|
{ |
|
at_start_ = false; |
|
|
|
if (hash_size == 0) |
|
{ |
|
return false; |
|
} |
|
else |
|
{ |
|
|
|
current_bucket = table; |
|
while (current_bucket->size() == 0) |
|
{ |
|
++current_bucket; |
|
} |
|
|
|
current_bucket->move_next(); |
|
|
|
return true; |
|
} |
|
} |
|
else |
|
{ |
|
|
|
if (current_bucket == 0) |
|
{ |
|
return false; |
|
} |
|
else |
|
{ |
|
if (current_bucket->move_next()) |
|
{ |
|
|
|
return true; |
|
} |
|
else |
|
{ |
|
|
|
bst_base* end = table + num_of_buckets; |
|
current_bucket->reset(); |
|
|
|
while (true) |
|
{ |
|
++current_bucket; |
|
|
|
if (current_bucket == end) |
|
{ |
|
current_bucket = 0; |
|
return false; |
|
} |
|
if (current_bucket->size() > 0) |
|
{ |
|
current_bucket->move_next(); |
|
return true; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
} |
|
|
|
#endif |
|
|
|
|