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>
715 static const KEY& keyFromBucket(
const KEY& bucket);
723 void loadElementAt(
Handle *handle,
731 bool insertElement(
Handle *handle,
const Bucket& element);
746 void findImp(
bool *isKeyFound,
750 const KEY&
key)
const;
791 const HASH1& hashFunctor1,
792 const HASH2& hashFunctor2,
858 const KEY&
key(
const Handle& handle)
const;
897 typedef const char *ConstCharPtr;
900 static const char REMOVED_KEYWORD[];
906 template <
char t_VALUE>
907 static bool isNot(
char c);
913 template <
class BUCKET>
914 static void load(BUCKET *dstBucket,
const BUCKET& srcBucket);
919 static bool areEqual(
const KEY& key1,
const KEY& key2);
920 static bool areEqual(
const ConstCharPtr& key1,
const ConstCharPtr& key2);
924 template <
class BUCKET>
925 static bool isNull(
const BUCKET& bucket);
927 static bool isNull(
const ConstCharPtr& bucket);
928 template <
class KEY,
class VALUE>
932 template <
class BUCKET>
935 static void setToNull(ConstCharPtr *bucket);
936 template <
class KEY,
class VALUE>
941 template <
class BUCKET>
942 static bool isRemoved(
const BUCKET& bucket);
944 static bool isRemoved(
const ConstCharPtr& bucket);
945 template <
class KEY,
class VALUE>
949 template <
class BUCKET>
953 template <
class KEY,
class VALUE>
983 unsigned int operator()(
const KEY& key)
const;
1013 template <
class KEY>
1014 unsigned int operator()(
const KEY& key)
const;
1052template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1059template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1061HashTable<KEY, VALUE, TRAITS, HASH1, HASH2>::keyFromBucket(
1064 return bucket.
first;
1068template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1069void HashTable<KEY, VALUE, TRAITS, HASH1, HASH2>::loadElementAt(
1072 const Bucket& element,
1078 TRAITS::load(&d_buckets[(size_type)index], element);
1083 d_maxChain = bsl::max(d_maxChain, chainLength);
1084 d_totalChain += chainLength;
1089template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1090bool HashTable<KEY, VALUE, TRAITS, HASH1, HASH2>::insertElement(
1092 const Bucket& element)
1096 if (
size() == capacity()) {
1103 findImp(&isKeyFound, &nullIndex, &chainLength, &removedIndex,
1104 keyFromBucket(element));
1110 if (-1 != removedIndex) {
1111 loadElementAt(handle, removedIndex, element, chainLength);
1116 loadElementAt(handle, nullIndex, element, chainLength);
1123template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1124void HashTable<KEY, VALUE, TRAITS, HASH1, HASH2>::findImp(
1129 const KEY& key)
const
1141 unsigned int capacity =
static_cast<unsigned int>(d_buckets.size());
1145 if (TRAITS::isNull(d_buckets[(size_type)bucketIndex])) {
1146 *isKeyFound =
false;
1147 *index = bucketIndex;
1150 else if (TRAITS::isRemoved(d_buckets[(size_type)bucketIndex])) {
1151 *removedIndex = bucketIndex;
1153 else if (TRAITS::areEqual(keyFromBucket(d_buckets[(size_type)bucketIndex]),
1156 *index = bucketIndex;
1161 % (capacity - 1)) + 1;
1164 while (*chainLength < capacity) {
1166 bucketIndex = (bucketIndex + increment) % capacity;
1168 if (TRAITS::isNull(d_buckets[(size_type)bucketIndex])) {
1169 *isKeyFound =
false;
1170 *index = bucketIndex;
1173 else if (TRAITS::isRemoved(d_buckets[(size_type)bucketIndex])) {
1174 if (*removedIndex == -1) {
1175 *removedIndex = bucketIndex;
1179 if (TRAITS::areEqual(keyFromBucket(d_buckets[(size_type)bucketIndex]),
1182 *index = bucketIndex;
1187 *isKeyFound =
false;
1192template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1199, d_capacityHint(capacityHint)
1200, d_hashFunctor1(basicAllocator)
1201, d_hashFunctor2(basicAllocator)
1211 for (Iterator it = d_buckets.begin(); it != d_buckets.end(); ++it) {
1212 TRAITS::setToNull(&(*it));
1216template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1219 const HASH1& hashFunctor1,
1220 const HASH2& hashFunctor2,
1225, d_capacityHint(capacityHint)
1226, d_hashFunctor1(hashFunctor1, basicAllocator)
1227, d_hashFunctor2(hashFunctor2, basicAllocator)
1237 for (Iterator it = d_buckets.begin(); it != d_buckets.end(); ++it) {
1238 TRAITS::setToNull(&(*it));
1242template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1249template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1258 return insertElement(handle, key);
1261template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1271 return insertElement(handle, bsl::make_pair(key, value));
1274template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1280 BSLS_ASSERT(!TRAITS::isNull (d_buckets[(size_type)handle]));
1281 BSLS_ASSERT(!TRAITS::isRemoved(d_buckets[(size_type)handle]));
1283 TRAITS::setToRemoved(&d_buckets[(size_type)handle]);
1287template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1294 BSLS_ASSERT(!TRAITS::isNull (d_buckets[(size_type)handle]));
1295 BSLS_ASSERT(!TRAITS::isRemoved(d_buckets[(size_type)handle]));
1297 return d_buckets[(size_type)handle].second;
1301template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1306 return d_buckets.size();
1309template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1314 return d_capacityHint;
1317template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1320 const KEY& key)
const
1327 findImp(&isKeyFound, handle, &chainLength, &removedIndex, key);
1332template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1335 const Handle& handle)
const
1338 BSLS_ASSERT(!TRAITS::isNull (d_buckets[(size_type)handle]));
1339 BSLS_ASSERT(!TRAITS::isRemoved(d_buckets[(size_type)handle]));
1341 return keyFromBucket(d_buckets[(size_type)handle]);
1344template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1352template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1357 return d_numCollisions;
1360template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1365 return d_numElements;
1368template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1373 return d_totalChain;
1376template <
class KEY,
class VALUE,
class TRAITS,
class HASH1,
class HASH2>
1379 const Handle& handle)
const
1384 BSLS_ASSERT(!TRAITS::isNull (d_buckets[(size_type)handle]));
1385 BSLS_ASSERT(!TRAITS::isRemoved(d_buckets[(size_type)handle]));
1387 return d_buckets[(size_type)handle].second;
1394template <
char t_VALUE>
1396bool HashTableDefaultTraits::isNot(
char c)
1398 return c != t_VALUE;
1401template <
class BUCKET>
1407 *dstBucket = srcBucket;
1414 return key1 == key2;
1419 const ConstCharPtr& key2)
1424 return 0 == bsl::strcmp(key1, key2);
1427template <
class BUCKET>
1437 const char null = 0; (void)null;
1438 const char *begin =
reinterpret_cast<const char *
>(&bucket);
1439 const char *end = begin +
sizeof bucket;
1441 return end == bsl::find_if(begin, end, isNot<null>);
1447 return 0 == bucket.
length();
1456template <
class KEY,
class VALUE>
1463template <
class BUCKET>
1475 const char null = 0;
1476 char *begin =
reinterpret_cast<char *
>(bucket);
1478 bsl::fill_n(begin,
sizeof(BUCKET), null);
1497template <
class KEY,
class VALUE>
1507template <
class BUCKET>
1517 const char removed = (char)0xFF;
1518 const char *begin =
reinterpret_cast<const char *
>(&bucket);
1519 const char *end = begin +
sizeof bucket;
1521 return end == bsl::find_if(begin, end, isNot<removed>);
1527 return 0 == bsl::strcmp(bucket.
c_str(), REMOVED_KEYWORD);
1533#if defined(BSLS_PLATFORM_CPU_32_BIT)
1534 const char *removed =
reinterpret_cast<const char *
>(0xFFFFFFFF);
1536 const char *removed =
reinterpret_cast<const char *
>(0xFFFFFFFFFFFFFFFF);
1539 return removed == bucket;
1542template <
class KEY,
class VALUE>
1549template <
class BUCKET>
1561 const char removed = (char)0xFF;
1562 char *begin =
reinterpret_cast<char *
>(bucket);
1564 bsl::fill_n(begin,
sizeof(BUCKET), removed);
1572 *bucket = REMOVED_KEYWORD;
1580#if defined(BSLS_PLATFORM_CPU_32_BIT)
1581 const char *removed =
reinterpret_cast<const char *
>(0xFFFFFFFF);
1583 const char *removed =
reinterpret_cast<const char *
>(0xFFFFFFFFFFFFFFFF);
1589template <
class KEY,
class VALUE>
1607 const char *keyData =
reinterpret_cast<const char *
>(&key);
1608 int keyLength =
sizeof key;
1616 const char *keyData = key;
1617 int keyLength =
static_cast<int>(bsl::strlen(key));
1625 const char *keyData = key.
data();
1626 int keyLength =
static_cast<int>(key.
length());
1639 const char *keyData =
reinterpret_cast<const char *
>(&key);
1640 int keyLength =
sizeof key;
1648 const char *keyData = key;
1649 int keyLength =
static_cast<int>(bsl::strlen(key));
1657 const char *keyData = key.
data();
1658 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:1371
~HashTable()
Destroy this object.
Definition bdlc_hashtable.h:1244
bool insert(Handle *handle, const KEY &key)
Definition bdlc_hashtable.h:1251
const KEY & key(const Handle &handle) const
Definition bdlc_hashtable.h:1334
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:1363
VALUE & value(const Handle &handle)
Definition bdlc_hashtable.h:1289
bsls::Types::Int64 capacity() const
Definition bdlc_hashtable.h:1304
bsls::Types::Int64 capacityHint() const
Definition bdlc_hashtable.h:1312
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:1347
void remove(const Handle &handle)
Definition bdlc_hashtable.h:1276
bsls::Types::Int64 numCollisions() const
Return the number of collisions encountered by this object.
Definition bdlc_hashtable.h:1355
bool find(Handle *handle, const KEY &key) const
Definition bdlc_hashtable.h:1319
Definition bslstl_string.h:1252
size_type length() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7301
const CHAR_TYPE * c_str() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7405
CHAR_TYPE * data() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7177
void clear() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6043
Definition bslstl_pair.h:1280
Definition bslstl_vector.h:1120
AllocatorTraits::size_type size_type
Definition bslstl_vector.h:1147
VALUE_TYPE * iterator
Definition bslstl_vector.h:1152
Definition bslalg_constructorproxy.h:376
Definition bslma_allocator.h:545
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
Definition bdlc_bitarray.h:506
static unsigned int hash2(const char *data, int length)
static unsigned int hash1(const char *data, int length)
Definition bdlc_hashtable.h:971
unsigned int operator()(const KEY &key) const
Definition bdlc_hashtable.h:1605
const char * ConstCharPtr
Definition bdlc_hashtable.h:974
Definition bdlc_hashtable.h:1002
unsigned int operator()(const KEY &key) const
Definition bdlc_hashtable.h:1637
const char * ConstCharPtr
Definition bdlc_hashtable.h:1005
Definition bdlc_hashtable.h:893
static void setToRemoved(BUCKET *bucket)
Load a removed value into the specified bucket.
Definition bdlc_hashtable.h:1551
static void setToNull(BUCKET *bucket)
Load a null value into the specified bucket.
Definition bdlc_hashtable.h:1465
static bool areEqual(const KEY &key1, const KEY &key2)
Definition bdlc_hashtable.h:1412
static void load(BUCKET *dstBucket, const BUCKET &srcBucket)
Load the specified srcBucket into the specified dstBucket.
Definition bdlc_hashtable.h:1403
static bool isRemoved(const BUCKET &bucket)
Definition bdlc_hashtable.h:1509
static bool isNull(const BUCKET &bucket)
Definition bdlc_hashtable.h:1429
Definition bdlc_hashtable.h:1029
static const int NUM_PRIME_NUMBERS
Definition bdlc_hashtable.h:1033
static const unsigned int * PRIME_NUMBERS
Definition bdlc_hashtable.h:1032
static unsigned int hashSize(bsls::Types::Int64 hint)
Return the hash size based on the specified hint.
TYPE first
Definition bslstl_pair.h:587
TYPE second
Definition bslstl_pair.h:933
Definition bslmf_conditional.h:123
Definition bslmf_integralconstant.h:261
Definition bslmf_istriviallydefaultconstructible.h:296
Definition bslma_usesbslmaallocator.h:344
Definition bslmf_issame.h:182
Definition bslmf_nil.h:133
long long Int64
Definition bsls_types.h:134