8#ifndef INCLUDED_BDLC_HASHTABLE
9#define INCLUDED_BDLC_HASHTABLE
608#include <bdlscm_version.h>
629#include <bsl_algorithm.h>
630#include <bsl_cstring.h>
631#include <bsl_functional.h>
632#include <bsl_string.h>
633#include <bsl_utility.h>
634#include <bsl_vector.h>
636#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
644struct HashTableDefaultTraits;
645struct HashTableDefaultHash1;
646struct HashTableDefaultHash2;
667 class TRAITS = HashTableDefaultTraits,
668 class HASH1 = HashTableDefaultHash1,
669 class HASH2 = HashTableDefaultHash2>
714 static const KEY& keyFromBucket(
const KEY& bucket);
722 void loadElementAt(
Handle *handle,
730 bool insertElement(
Handle *handle,
const Bucket& element);
744 void findImp(
bool *isKeyFound,
748 const KEY&
key)
const;
785 const HASH1& hashFunctor1,
786 const HASH2& hashFunctor2,
843 const KEY&
key(
const Handle& handle)
const;
877 typedef const char *ConstCharPtr;
880 static const char REMOVED_KEYWORD[];
886 template <
char t_VALUE>
887 static bool isNot(
char c);
893 template <
class BUCKET>
894 static void load(BUCKET *dstBucket,
const BUCKET& srcBucket);
899 static bool areEqual(
const KEY& key1,
const KEY& key2);
900 static bool areEqual(
const ConstCharPtr& key1,
const ConstCharPtr& key2);
904 template <
class BUCKET>
905 static bool isNull(
const BUCKET& bucket);
907 static bool isNull(
const ConstCharPtr& bucket);
908 template <
class KEY,
class VALUE>
912 template <
class BUCKET>
915 static void setToNull(ConstCharPtr *bucket);
916 template <
class KEY,
class VALUE>
921 template <
class BUCKET>
922 static bool isRemoved(
const BUCKET& bucket);
924 static bool isRemoved(
const ConstCharPtr& bucket);
925 template <
class KEY,
class VALUE>
929 template <
class BUCKET>
933 template <
class KEY,
class VALUE>
959 unsigned int operator()(
const KEY& key)
const;
986 unsigned int operator()(
const KEY& key)
const;
1022template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1029template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1031HashTable<KEY, VALUE, TRAITS, HASH1, HASH2>::keyFromBucket(
1034 return bucket.
first;
1038template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1039void HashTable<KEY, VALUE, TRAITS, HASH1, HASH2>::loadElementAt(
1042 const Bucket& element,
1048 TRAITS::load(&d_buckets[(size_type)index], element);
1053 d_maxChain = bsl::max(d_maxChain, chainLength);
1054 d_totalChain += chainLength;
1059template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1060bool HashTable<KEY, VALUE, TRAITS, HASH1, HASH2>::insertElement(
1062 const Bucket& element)
1066 if (
size() == capacity()) {
1073 findImp(&isKeyFound, &nullIndex, &chainLength, &removedIndex,
1074 keyFromBucket(element));
1080 if (-1 != removedIndex) {
1081 loadElementAt(handle, removedIndex, element, chainLength);
1086 loadElementAt(handle, nullIndex, element, chainLength);
1093template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1094void HashTable<KEY, VALUE, TRAITS, HASH1, HASH2>::findImp(
1099 const KEY& key)
const
1111 unsigned int capacity =
static_cast<unsigned int>(d_buckets.size());
1115 if (TRAITS::isNull(d_buckets[(size_type)bucketIndex])) {
1116 *isKeyFound =
false;
1117 *index = bucketIndex;
1120 else if (TRAITS::isRemoved(d_buckets[(size_type)bucketIndex])) {
1121 *removedIndex = bucketIndex;
1123 else if (TRAITS::areEqual(keyFromBucket(d_buckets[(size_type)bucketIndex]),
1126 *index = bucketIndex;
1131 % (capacity - 1)) + 1;
1134 while (*chainLength < capacity) {
1136 bucketIndex = (bucketIndex + increment) % capacity;
1138 if (TRAITS::isNull(d_buckets[(size_type)bucketIndex])) {
1139 *isKeyFound =
false;
1140 *index = bucketIndex;
1143 else if (TRAITS::isRemoved(d_buckets[(size_type)bucketIndex])) {
1144 if (*removedIndex == -1) {
1145 *removedIndex = bucketIndex;
1149 if (TRAITS::areEqual(keyFromBucket(d_buckets[(size_type)bucketIndex]),
1152 *index = bucketIndex;
1157 *isKeyFound =
false;
1162template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1169, d_capacityHint(capacityHint)
1170, d_hashFunctor1(basicAllocator)
1171, d_hashFunctor2(basicAllocator)
1181 for (Iterator it = d_buckets.begin(); it != d_buckets.end(); ++it) {
1182 TRAITS::setToNull(&(*it));
1186template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1189 const HASH1& hashFunctor1,
1190 const HASH2& hashFunctor2,
1195, d_capacityHint(capacityHint)
1196, d_hashFunctor1(hashFunctor1, basicAllocator)
1197, d_hashFunctor2(hashFunctor2, basicAllocator)
1207 for (Iterator it = d_buckets.begin(); it != d_buckets.end(); ++it) {
1208 TRAITS::setToNull(&(*it));
1212template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1219template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1228 return insertElement(handle, key);
1231template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1241 return insertElement(handle, bsl::make_pair(key, value));
1244template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1250 BSLS_ASSERT(!TRAITS::isNull (d_buckets[(size_type)handle]));
1251 BSLS_ASSERT(!TRAITS::isRemoved(d_buckets[(size_type)handle]));
1253 TRAITS::setToRemoved(&d_buckets[(size_type)handle]);
1257template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1264 BSLS_ASSERT(!TRAITS::isNull (d_buckets[(size_type)handle]));
1265 BSLS_ASSERT(!TRAITS::isRemoved(d_buckets[(size_type)handle]));
1267 return d_buckets[(size_type)handle].second;
1271template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1276 return d_buckets.size();
1279template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1284 return d_capacityHint;
1287template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1290 const KEY& key)
const
1297 findImp(&isKeyFound, handle, &chainLength, &removedIndex, key);
1302template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1305 const Handle& handle)
const
1308 BSLS_ASSERT(!TRAITS::isNull (d_buckets[(size_type)handle]));
1309 BSLS_ASSERT(!TRAITS::isRemoved(d_buckets[(size_type)handle]));
1311 return keyFromBucket(d_buckets[(size_type)handle]);
1314template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1322template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1327 return d_numCollisions;
1330template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1335 return d_numElements;
1338template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1343 return d_totalChain;
1346template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1349 const Handle& handle)
const
1354 BSLS_ASSERT(!TRAITS::isNull (d_buckets[(size_type)handle]));
1355 BSLS_ASSERT(!TRAITS::isRemoved(d_buckets[(size_type)handle]));
1357 return d_buckets[(size_type)handle].second;
1364template <
char t_VALUE>
1366bool HashTableDefaultTraits::isNot(
char c)
1368 return c != t_VALUE;
1371template <
class BUCKET>
1377 *dstBucket = srcBucket;
1384 return key1 == key2;
1389 const ConstCharPtr& key2)
1394 return 0 == bsl::strcmp(key1, key2);
1397template <
class BUCKET>
1407 const char null = 0; (void)null;
1408 const char *begin =
reinterpret_cast<const char *
>(&bucket);
1409 const char *end = begin +
sizeof bucket;
1411 return end == bsl::find_if(begin, end, isNot<null>);
1417 return 0 == bucket.
length();
1426template <
class KEY,
class VALUE>
1433template <
class BUCKET>
1445 const char null = 0;
1446 char *begin =
reinterpret_cast<char *
>(bucket);
1448 bsl::fill_n(begin,
sizeof(BUCKET), null);
1467template <
class KEY,
class VALUE>
1477template <
class BUCKET>
1487 const char removed = (char)0xFF;
1488 const char *begin =
reinterpret_cast<const char *
>(&bucket);
1489 const char *end = begin +
sizeof bucket;
1491 return end == bsl::find_if(begin, end, isNot<removed>);
1497 return 0 == bsl::strcmp(bucket.
c_str(), REMOVED_KEYWORD);
1503#if defined(BSLS_PLATFORM_CPU_32_BIT)
1504 const char *removed =
reinterpret_cast<const char *
>(0xFFFFFFFF);
1506 const char *removed =
reinterpret_cast<const char *
>(0xFFFFFFFFFFFFFFFF);
1509 return removed == bucket;
1512template <
class KEY,
class VALUE>
1519template <
class BUCKET>
1531 const char removed = (char)0xFF;
1532 char *begin =
reinterpret_cast<char *
>(bucket);
1534 bsl::fill_n(begin,
sizeof(BUCKET), removed);
1542 *bucket = REMOVED_KEYWORD;
1550#if defined(BSLS_PLATFORM_CPU_32_BIT)
1551 const char *removed =
reinterpret_cast<const char *
>(0xFFFFFFFF);
1553 const char *removed =
reinterpret_cast<const char *
>(0xFFFFFFFFFFFFFFFF);
1559template <
class KEY,
class VALUE>
1577 const char *keyData =
reinterpret_cast<const char *
>(&key);
1578 int keyLength =
sizeof key;
1586 const char *keyData = key;
1587 int keyLength =
static_cast<int>(bsl::strlen(key));
1595 const char *keyData = key.
data();
1596 int keyLength =
static_cast<int>(key.
length());
1609 const char *keyData =
reinterpret_cast<const char *
>(&key);
1610 int keyLength =
sizeof key;
1618 const char *keyData = key;
1619 int keyLength =
static_cast<int>(bsl::strlen(key));
1627 const char *keyData = key.
data();
1628 int keyLength =
static_cast<int>(key.
length());
Definition bdlc_hashtable.h:670
bsls::Types::Int64 totalChain() const
Return the total chain length encountered by this object.
Definition bdlc_hashtable.h:1341
~HashTable()
Destroy this object.
Definition bdlc_hashtable.h:1214
bool insert(Handle *handle, const KEY &key)
Definition bdlc_hashtable.h:1221
const KEY & key(const Handle &handle) const
Definition bdlc_hashtable.h:1304
BSLMF_NESTED_TRAIT_DECLARATION(HashTable, bslma::UsesBslmaAllocator)
bsls::Types::Int64 size() const
Return the number of elements stored in this object.
Definition bdlc_hashtable.h:1333
VALUE & value(const Handle &handle)
Definition bdlc_hashtable.h:1259
bsls::Types::Int64 capacity() const
Definition bdlc_hashtable.h:1274
bsls::Types::Int64 capacityHint() const
Definition bdlc_hashtable.h:1282
bsls::Types::Int64 Handle
Definition bdlc_hashtable.h:677
bsls::Types::Int64 maxChain() const
Return the maximum chain length encountered by this object.
Definition bdlc_hashtable.h:1317
void remove(const Handle &handle)
Definition bdlc_hashtable.h:1246
bsls::Types::Int64 numCollisions() const
Return the number of collisions encountered by this object.
Definition bdlc_hashtable.h:1325
bool find(Handle *handle, const KEY &key) const
Definition bdlc_hashtable.h:1289
Definition bslstl_string.h:1281
size_type length() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6601
const CHAR_TYPE * c_str() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6705
CHAR_TYPE * data() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6477
void clear() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:5430
Definition bslstl_pair.h:1210
Definition bslstl_vector.h:1025
AllocatorTraits::size_type size_type
Definition bslstl_vector.h:1052
VALUE_TYPE * iterator
Definition bslstl_vector.h:1057
Definition bslalg_constructorproxy.h:368
Definition bslma_allocator.h:457
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
Definition bdlc_bitarray.h:503
static unsigned int hash2(const char *data, int length)
static unsigned int hash1(const char *data, int length)
Definition bdlc_hashtable.h:947
unsigned int operator()(const KEY &key) const
Definition bdlc_hashtable.h:1575
const char * ConstCharPtr
Definition bdlc_hashtable.h:950
Definition bdlc_hashtable.h:974
unsigned int operator()(const KEY &key) const
Definition bdlc_hashtable.h:1607
const char * ConstCharPtr
Definition bdlc_hashtable.h:977
Definition bdlc_hashtable.h:873
static void setToRemoved(BUCKET *bucket)
Load a removed value into the specified bucket.
Definition bdlc_hashtable.h:1521
static void setToNull(BUCKET *bucket)
Load a null value into the specified bucket.
Definition bdlc_hashtable.h:1435
static bool areEqual(const KEY &key1, const KEY &key2)
Definition bdlc_hashtable.h:1382
static void load(BUCKET *dstBucket, const BUCKET &srcBucket)
Load the specified srcBucket into the specified dstBucket.
Definition bdlc_hashtable.h:1373
static bool isRemoved(const BUCKET &bucket)
Definition bdlc_hashtable.h:1479
static bool isNull(const BUCKET &bucket)
Definition bdlc_hashtable.h:1399
Definition bdlc_hashtable.h:999
static const int NUM_PRIME_NUMBERS
Definition bdlc_hashtable.h:1003
static const unsigned int * PRIME_NUMBERS
Definition bdlc_hashtable.h:1002
static unsigned int hashSize(bsls::Types::Int64 hint)
Return the hash size based on the specified hint.
TYPE first
Definition bslstl_pair.h:605
TYPE second
Definition bslstl_pair.h:908
Definition bslmf_conditional.h:120
Definition bslmf_integralconstant.h:244
Definition bslmf_istriviallydefaultconstructible.h:293
Definition bslma_usesbslmaallocator.h:343
Definition bslmf_issame.h:181
This struct is empty and represents a nil type.
Definition bslmf_nil.h:131
long long Int64
Definition bsls_types.h:132