Qt 4.8
qhash.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qhash.h"
43 
44 #ifdef truncate
45 #undef truncate
46 #endif
47 
48 #include <qbitarray.h>
49 #include <qstring.h>
50 #include <stdlib.h>
51 #ifdef QT_QHASH_DEBUG
52 #include <qstring.h>
53 #endif
54 
56 
57 
58 // ### Qt 5: see tests/benchmarks/corelib/tools/qhash/qhash_string.cpp
59 // Hashing of the whole string is a waste of cycles.
60 
61 /*
62  These functions are based on Peter J. Weinberger's hash function
63  (from the Dragon Book). The constant 24 in the original function
64  was replaced with 23 to produce fewer collisions on input such as
65  "a", "aa", "aaa", "aaaa", ...
66 */
67 
68 static uint hash(const uchar *p, int n)
69 {
70  uint h = 0;
71 
72  while (n--) {
73  h = (h << 4) + *p++;
74  h ^= (h & 0xf0000000) >> 23;
75  h &= 0x0fffffff;
76  }
77  return h;
78 }
79 
80 static uint hash(const QChar *p, int n)
81 {
82  uint h = 0;
83 
84  while (n--) {
85  h = (h << 4) + (*p++).unicode();
86  h ^= (h & 0xf0000000) >> 23;
87  h &= 0x0fffffff;
88  }
89  return h;
90 }
91 
93 {
94  return hash(reinterpret_cast<const uchar *>(key.constData()), key.size());
95 }
96 
98 {
99  return hash(key.unicode(), key.size());
100 }
101 
103 {
104  return hash(key.unicode(), key.size());
105 }
106 
107 uint qHash(const QBitArray &bitArray)
108 {
109  int m = bitArray.d.size() - 1;
110  uint result = hash(reinterpret_cast<const uchar *>(bitArray.d.constData()), qMax(0, m));
111 
112  // deal with the last 0 to 7 bits manually, because we can't trust that
113  // the padding is initialized to 0 in bitArray.d
114  int n = bitArray.size();
115  if (n & 0x7)
116  result = ((result << 4) + bitArray.d.at(m)) & ((1 << n) - 1);
117  return result;
118 }
119 
120 /*
121  The prime_deltas array is a table of selected prime values, even
122  though it doesn't look like one. The primes we are using are 1,
123  2, 5, 11, 17, 37, 67, 131, 257, ..., i.e. primes in the immediate
124  surrounding of a power of two.
125 
126  The primeForNumBits() function returns the prime associated to a
127  power of two. For example, primeForNumBits(8) returns 257.
128 */
129 
130 static const uchar prime_deltas[] = {
131  0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
132  1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
133 };
134 
135 static inline int primeForNumBits(int numBits)
136 {
137  return (1 << numBits) + prime_deltas[numBits];
138 }
139 
140 /*
141  Returns the smallest integer n such that
142  primeForNumBits(n) >= hint.
143 */
144 static int countBits(int hint)
145 {
146  int numBits = 0;
147  int bits = hint;
148 
149  while (bits > 1) {
150  bits >>= 1;
151  numBits++;
152  }
153 
154  if (numBits >= (int)sizeof(prime_deltas)) {
155  numBits = sizeof(prime_deltas) - 1;
156  } else if (primeForNumBits(numBits) < hint) {
157  ++numBits;
158  }
159  return numBits;
160 }
161 
162 /*
163  A QHash has initially around pow(2, MinNumBits) buckets. For
164  example, if MinNumBits is 4, it has 17 buckets.
165 */
166 const int MinNumBits = 4;
167 
169  0, 0, Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, MinNumBits, 0, 0, true, false, 0
170 };
171 
173 {
174  return allocateNode(0);
175 }
176 
177 void *QHashData::allocateNode(int nodeAlign)
178 {
179  void *ptr = strictAlignment ? qMallocAligned(nodeSize, nodeAlign) : qMalloc(nodeSize);
180  Q_CHECK_PTR(ptr);
181  return ptr;
182 }
183 
184 void QHashData::freeNode(void *node)
185 {
186  if (strictAlignment)
187  qFreeAligned(node);
188  else
189  qFree(node);
190 }
191 
192 QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize)
193 {
194  return detach_helper2( node_duplicate, 0, nodeSize, 0 );
195 }
196 
197 QHashData *QHashData::detach_helper2(void (*node_duplicate)(Node *, void *),
198  void (*node_delete)(Node *),
199  int nodeSize,
200  int nodeAlign)
201 {
202  union {
203  QHashData *d;
204  Node *e;
205  };
206  d = new QHashData;
207  d->fakeNext = 0;
208  d->buckets = 0;
209  d->ref = 1;
210  d->size = size;
211  d->nodeSize = nodeSize;
212  d->userNumBits = userNumBits;
213  d->numBits = numBits;
214  d->numBuckets = numBuckets;
215  d->sharable = true;
216  d->strictAlignment = nodeAlign > 8;
217  d->reserved = 0;
218 
219  if (numBuckets) {
220  QT_TRY {
221  d->buckets = new Node *[numBuckets];
222  } QT_CATCH(...) {
223  // restore a consistent state for d
224  d->numBuckets = 0;
225  // roll back
226  d->free_helper(node_delete);
227  QT_RETHROW;
228  }
229 
230  Node *this_e = reinterpret_cast<Node *>(this);
231  for (int i = 0; i < numBuckets; ++i) {
232  Node **nextNode = &d->buckets[i];
233  Node *oldNode = buckets[i];
234  while (oldNode != this_e) {
235  QT_TRY {
236  Node *dup = static_cast<Node *>(allocateNode(nodeAlign));
237 
238  QT_TRY {
239  node_duplicate(oldNode, dup);
240  } QT_CATCH(...) {
241  freeNode( dup );
242  QT_RETHROW;
243  }
244 
245  dup->h = oldNode->h;
246  *nextNode = dup;
247  nextNode = &dup->next;
248  oldNode = oldNode->next;
249  } QT_CATCH(...) {
250  // restore a consistent state for d
251  *nextNode = e;
252  d->numBuckets = i+1;
253  // roll back
254  d->free_helper(node_delete);
255  QT_RETHROW;
256  }
257  }
258  *nextNode = e;
259  }
260  }
261  return d;
262 }
263 
264 void QHashData::free_helper(void (*node_delete)(Node *))
265 {
266  if (node_delete) {
267  Node *this_e = reinterpret_cast<Node *>(this);
268  Node **bucket = reinterpret_cast<Node **>(this->buckets);
269 
270  int n = numBuckets;
271  while (n--) {
272  Node *cur = *bucket++;
273  while (cur != this_e) {
274  Node *next = cur->next;
275  node_delete(cur);
276  freeNode(cur);
277  cur = next;
278  }
279  }
280  }
281  delete [] buckets;
282  delete this;
283 }
284 
286 {
287  union {
288  Node *next;
289  Node *e;
290  QHashData *d;
291  };
292  next = node->next;
293  Q_ASSERT_X(next, "QHash", "Iterating beyond end()");
294  if (next->next)
295  return next;
296 
297  int start = (node->h % d->numBuckets) + 1;
298  Node **bucket = d->buckets + start;
299  int n = d->numBuckets - start;
300  while (n--) {
301  if (*bucket != e)
302  return *bucket;
303  ++bucket;
304  }
305  return e;
306 }
307 
309 {
310  union {
311  Node *e;
312  QHashData *d;
313  };
314 
315  e = node;
316  while (e->next)
317  e = e->next;
318 
319  int start;
320  if (node == e)
321  start = d->numBuckets - 1;
322  else
323  start = node->h % d->numBuckets;
324 
325  Node *sentinel = node;
326  Node **bucket = d->buckets + start;
327  while (start >= 0) {
328  if (*bucket != sentinel) {
329  Node *prev = *bucket;
330  while (prev->next != sentinel)
331  prev = prev->next;
332  return prev;
333  }
334 
335  sentinel = e;
336  --bucket;
337  --start;
338  }
339  Q_ASSERT_X(start >= 0, "QHash", "Iterating backward beyond begin()");
340  return e;
341 }
342 
343 /*
344  If hint is negative, -hint gives the approximate number of
345  buckets that should be used for the hash table. If hint is
346  nonnegative, (1 << hint) gives the approximate number
347  of buckets that should be used.
348 */
349 void QHashData::rehash(int hint)
350 {
351  if (hint < 0) {
352  hint = countBits(-hint);
353  if (hint < MinNumBits)
354  hint = MinNumBits;
355  userNumBits = hint;
356  while (primeForNumBits(hint) < (size >> 1))
357  ++hint;
358  } else if (hint < MinNumBits) {
359  hint = MinNumBits;
360  }
361 
362  if (numBits != hint) {
363  Node *e = reinterpret_cast<Node *>(this);
364  Node **oldBuckets = buckets;
365  int oldNumBuckets = numBuckets;
366 
367  int nb = primeForNumBits(hint);
368  buckets = new Node *[nb];
369  numBits = hint;
370  numBuckets = nb;
371  for (int i = 0; i < numBuckets; ++i)
372  buckets[i] = e;
373 
374  for (int i = 0; i < oldNumBuckets; ++i) {
375  Node *firstNode = oldBuckets[i];
376  while (firstNode != e) {
377  uint h = firstNode->h;
378  Node *lastNode = firstNode;
379  while (lastNode->next != e && lastNode->next->h == h)
380  lastNode = lastNode->next;
381 
382  Node *afterLastNode = lastNode->next;
383  Node **beforeFirstNode = &buckets[h % numBuckets];
384  while (*beforeFirstNode != e)
385  beforeFirstNode = &(*beforeFirstNode)->next;
386  lastNode->next = *beforeFirstNode;
387  *beforeFirstNode = firstNode;
388  firstNode = afterLastNode;
389  }
390  }
391  delete [] oldBuckets;
392  }
393 }
394 
396 {
397  free_helper(0);
398 }
399 
400 #ifdef QT_QHASH_DEBUG
401 
402 void QHashData::dump()
403 {
404  qDebug("Hash data (ref = %d, size = %d, nodeSize = %d, userNumBits = %d, numBits = %d, numBuckets = %d)",
406  numBuckets);
407  qDebug(" %p (fakeNode = %p)", this, fakeNext);
408  for (int i = 0; i < numBuckets; ++i) {
409  QString line;
410  Node *n = buckets[i];
411  if (n != reinterpret_cast<Node *>(this)) {
412  line.sprintf("%d:", i);
413  while (n != reinterpret_cast<Node *>(this)) {
414  line += QString().sprintf(" -> [%p]", n);
415  if (!n) {
416  line += " (CORRUPT)";
417  break;
418  }
419  n = n->next;
420  }
421  qDebug(qPrintable(line));
422  }
423  }
424 }
425 
426 void QHashData::checkSanity()
427 {
428  if (fakeNext)
429  qFatal("Fake next isn't 0");
430 
431  for (int i = 0; i < numBuckets; ++i) {
432  Node *n = buckets[i];
433  Node *p = n;
434  if (!n)
435  qFatal("%d: Bucket entry is 0", i);
436  if (n != reinterpret_cast<Node *>(this)) {
437  while (n != reinterpret_cast<Node *>(this)) {
438  if (!n->next)
439  qFatal("%d: Next of %p is 0, should be %p", i, n, this);
440  n = n->next;
441  }
442  }
443  }
444 }
445 #endif
446 
double d
Definition: qnumeric_p.h:62
static uint hash(const uchar *p, int n)
Definition: qhash.cpp:68
QString & sprintf(const char *format,...)
Safely builds a formatted string from the format string cformat and an arbitrary list of arguments...
Definition: qstring.cpp:5567
QBasicAtomicInt ref
Definition: qhash.h:121
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
Q_CORE_EXPORT void * qMallocAligned(size_t size, size_t alignment)
Definition: qmalloc.cpp:68
void * allocateNode()
Definition: qhash.cpp:172
static Node * previousNode(Node *node)
Definition: qhash.cpp:308
Q_CORE_EXPORT void qFree(void *ptr)
Definition: qmalloc.cpp:58
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
Node * firstNode()
Definition: qhash.h:181
int size
Definition: qhash.h:122
QHashData * detach_helper(void(*node_duplicate)(Node *, void *), int nodeSize)
Definition: qhash.cpp:192
short numBits
Definition: qhash.h:125
QHashData * detach_helper2(void(*node_duplicate)(Node *, void *), void(*node_delete)(Node *), int nodeSize, int nodeAlign)
Definition: qhash.cpp:197
static Node * nextNode(Node *node)
Definition: qhash.cpp:285
Q_CORE_EXPORT void * qMalloc(size_t size)
Definition: qmalloc.cpp:53
void rehash(int hint)
Definition: qhash.cpp:349
The QString class provides a Unicode character string.
Definition: qstring.h:83
int numBuckets
Definition: qhash.h:126
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
Node * next
Definition: qhash.h:115
void destroyAndFree()
Definition: qhash.cpp:395
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
Node ** buckets
Definition: qhash.h:120
static int countBits(int hint)
Definition: qhash.cpp:144
QByteArray d
Definition: qbitarray.h:59
Q_CORE_EXPORT void qDebug(const char *,...)
#define QT_RETHROW
Definition: qglobal.h:1539
unsigned char uchar
Definition: qglobal.h:994
int size() const
Returns the number of characters referred to by the string reference.
Definition: qstring.h:1114
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
int size() const
Returns the number of characters in this string.
Definition: qstring.h:102
const QChar * unicode() const
Returns a &#39;\0&#39;-terminated Unicode representation of the string.
Definition: qstring.h:706
short userNumBits
Definition: qhash.h:124
unsigned int uint
Definition: qglobal.h:996
const QChar * unicode() const
Returns a Unicode representation of the string reference.
Definition: qstring.h:1153
const T * ptr(const T &t)
void free_helper(void(*node_delete)(Node *))
Definition: qhash.cpp:264
static QHashData shared_null
Definition: qhash.h:151
#define QT_CATCH(A)
Definition: qglobal.h:1537
The QStringRef class provides a thin wrapper around QString substrings.
Definition: qstring.h:1099
The QBitArray class provides an array of bits.
Definition: qbitarray.h:54
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
Q_CORE_EXPORT void qFatal(const char *,...)
#define Q_CHECK_PTR(p)
Definition: qglobal.h:1853
uint qHash(const QUrl &url)
Definition: qurl.h:285
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
const int MinNumBits
Definition: qhash.cpp:166
static const uchar prime_deltas[]
Definition: qhash.cpp:130
int key
Node * fakeNext
Definition: qhash.h:119
static QString dump(const QByteArray &)
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
void freeNode(void *node)
Definition: qhash.cpp:184
static int primeForNumBits(int numBits)
Definition: qhash.cpp:135
uint strictAlignment
Definition: qhash.h:128
char at(int i) const
Returns the character at index position i in the byte array.
Definition: qbytearray.h:413
#define qPrintable(string)
Definition: qglobal.h:1750
int size() const
Returns the number of bits stored in the bit array.
Definition: qbitarray.h:73
#define QT_TRY
Definition: qglobal.h:1536
int nodeSize
Definition: qhash.h:123
Q_CORE_EXPORT void qFreeAligned(void *ptr)
Definition: qmalloc.cpp:118