src/corelib/tools/qhash.h
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    67 inline uint qHash(uint key) { return key; }
    67 inline uint qHash(uint key) { return key; }
    68 inline uint qHash(int key) { return uint(key); }
    68 inline uint qHash(int key) { return uint(key); }
    69 inline uint qHash(ulong key)
    69 inline uint qHash(ulong key)
    70 {
    70 {
    71     if (sizeof(ulong) > sizeof(uint)) {
    71     if (sizeof(ulong) > sizeof(uint)) {
    72         return uint((key >> (8 * sizeof(uint) - 1)) ^ key);
    72         return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U));
    73     } else {
    73     } else {
    74         return uint(key);
    74         return uint(key & (~0U));
    75     }
    75     }
    76 }
    76 }
    77 inline uint qHash(long key) { return qHash(ulong(key)); }
    77 inline uint qHash(long key) { return qHash(ulong(key)); }
    78 inline uint qHash(quint64 key)
    78 inline uint qHash(quint64 key)
    79 {
    79 {
    80     if (sizeof(quint64) > sizeof(uint)) {
    80     if (sizeof(quint64) > sizeof(uint)) {
    81         return uint((key >> (8 * sizeof(uint) - 1)) ^ key);
    81         return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U));
    82     } else {
    82     } else {
    83         return uint(key);
    83         return uint(key & (~0U));
    84     }
    84     }
    85 }
    85 }
    86 inline uint qHash(qint64 key) { return qHash(quint64(key)); }
    86 inline uint qHash(qint64 key) { return qHash(quint64(key)); }
    87 inline uint qHash(QChar key) { return qHash(key.unicode()); }
    87 inline uint qHash(QChar key) { return qHash(key.unicode()); }
    88 Q_CORE_EXPORT uint qHash(const QByteArray &key);
    88 Q_CORE_EXPORT uint qHash(const QByteArray &key);
   123     int nodeSize;
   123     int nodeSize;
   124     short userNumBits;
   124     short userNumBits;
   125     short numBits;
   125     short numBits;
   126     int numBuckets;
   126     int numBuckets;
   127     uint sharable : 1;
   127     uint sharable : 1;
   128 
   128     uint strictAlignment : 1;
   129     void *allocateNode();
   129     uint reserved : 30;
       
   130 
       
   131     void *allocateNode(); // ### Qt5 remove me
       
   132     void *allocateNode(int nodeAlign);
   130     void freeNode(void *node);
   133     void freeNode(void *node);
   131     QHashData *detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize); // ### Qt5 remove me
   134     QHashData *detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize); // ### Qt5 remove me
   132     QHashData *detach_helper(void (*node_duplicate)(Node *, void *), void (*node_delete)(Node *),
   135     QHashData *detach_helper2(void (*node_duplicate)(Node *, void *), void (*node_delete)(Node *),
   133             int nodeSize);
   136                               int nodeSize, int nodeAlign);
   134     void mightGrow();
   137     void mightGrow();
   135     bool willGrow();
   138     bool willGrow();
   136     void hasShrunk();
   139     void hasShrunk();
   137     void rehash(int hint);
   140     void rehash(int hint);
   138     void free_helper(void (*node_delete)(Node *));
   141     void free_helper(void (*node_delete)(Node *));
   265 
   268 
   266     static inline Node *concrete(QHashData::Node *node) {
   269     static inline Node *concrete(QHashData::Node *node) {
   267         return reinterpret_cast<Node *>(node);
   270         return reinterpret_cast<Node *>(node);
   268     }
   271     }
   269 
   272 
       
   273 #ifdef Q_ALIGNOF
       
   274     static inline int alignOfNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(Node)); }
       
   275     static inline int alignOfDummyNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(DummyNode)); }
       
   276 #else
       
   277     static inline int alignOfNode() { return 0; }
       
   278     static inline int alignOfDummyNode() { return 0; }
       
   279 #endif
       
   280 
   270 public:
   281 public:
   271     inline QHash() : d(&QHashData::shared_null) { d->ref.ref(); }
   282     inline QHash() : d(&QHashData::shared_null) { d->ref.ref(); }
   272     inline QHash(const QHash<Key, T> &other) : d(other.d) { d->ref.ref(); if (!d->sharable) detach(); }
   283     inline QHash(const QHash<Key, T> &other) : d(other.d) { d->ref.ref(); if (!d->sharable) detach(); }
   273     inline ~QHash() { if (!d->ref.deref()) freeData(d); }
   284     inline ~QHash() { if (!d->ref.deref()) freeData(d); }
   274 
   285 
   481     void detach_helper();
   492     void detach_helper();
   482     void freeData(QHashData *d);
   493     void freeData(QHashData *d);
   483     Node **findNode(const Key &key, uint *hp = 0) const;
   494     Node **findNode(const Key &key, uint *hp = 0) const;
   484     Node *createNode(uint h, const Key &key, const T &value, Node **nextNode);
   495     Node *createNode(uint h, const Key &key, const T &value, Node **nextNode);
   485     void deleteNode(Node *node);
   496     void deleteNode(Node *node);
   486     static void deleteNode(QHashData::Node *node);
   497     static void deleteNode2(QHashData::Node *node);
   487 
   498 
   488     static void duplicateNode(QHashData::Node *originalNode, void *newNode);
   499     static void duplicateNode(QHashData::Node *originalNode, void *newNode);
   489 };
   500 };
   490 
   501 
   491 
   502 
   492 template <class Key, class T>
   503 template <class Key, class T>
   493 Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(Node *node)
   504 Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(Node *node)
   494 {
   505 {
   495     deleteNode(reinterpret_cast<QHashData::Node*>(node));
   506     deleteNode2(reinterpret_cast<QHashData::Node*>(node));
   496 }
   507     d->freeNode(node);
   497 
   508 }
   498 
   509 
   499 template <class Key, class T>
   510 template <class Key, class T>
   500 Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(QHashData::Node *node)
   511 Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode2(QHashData::Node *node)
   501 {
   512 {
   502 #ifdef Q_CC_BOR
   513 #ifdef Q_CC_BOR
   503     concrete(node)->~QHashNode<Key, T>();
   514     concrete(node)->~QHashNode<Key, T>();
   504 #elif defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION)
   515 #elif defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION)
   505     concrete(node)->~QHashNode();
   516     concrete(node)->~QHashNode();
   506 #else
   517 #else
   507     concrete(node)->~Node();
   518     concrete(node)->~Node();
   508 #endif
   519 #endif
   509     qFree(node);
       
   510 }
   520 }
   511 
   521 
   512 template <class Key, class T>
   522 template <class Key, class T>
   513 Q_INLINE_TEMPLATE void QHash<Key, T>::duplicateNode(QHashData::Node *node, void *newNode)
   523 Q_INLINE_TEMPLATE void QHash<Key, T>::duplicateNode(QHashData::Node *node, void *newNode)
   514 {
   524 {
   525 QHash<Key, T>::createNode(uint ah, const Key &akey, const T &avalue, Node **anextNode)
   535 QHash<Key, T>::createNode(uint ah, const Key &akey, const T &avalue, Node **anextNode)
   526 {
   536 {
   527     Node *node;
   537     Node *node;
   528 
   538 
   529     if (QTypeInfo<T>::isDummy) {
   539     if (QTypeInfo<T>::isDummy) {
   530         node = reinterpret_cast<Node *>(new (d->allocateNode()) DummyNode(akey));
   540         node = reinterpret_cast<Node *>(new (d->allocateNode(alignOfDummyNode())) DummyNode(akey));
   531     } else {
   541     } else {
   532         node = new (d->allocateNode()) Node(akey, avalue);
   542         node = new (d->allocateNode(alignOfNode())) Node(akey, avalue);
   533     }
   543     }
   534 
   544 
   535     node->h = ah;
   545     node->h = ah;
   536     node->next = *anextNode;
   546     node->next = *anextNode;
   537     *anextNode = node;
   547     *anextNode = node;
   552 }
   562 }
   553 
   563 
   554 template <class Key, class T>
   564 template <class Key, class T>
   555 Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::freeData(QHashData *x)
   565 Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::freeData(QHashData *x)
   556 {
   566 {
   557     x->free_helper(deleteNode);
   567     x->free_helper(deleteNode2);
   558 }
   568 }
   559 
   569 
   560 template <class Key, class T>
   570 template <class Key, class T>
   561 Q_INLINE_TEMPLATE void QHash<Key, T>::clear()
   571 Q_INLINE_TEMPLATE void QHash<Key, T>::clear()
   562 {
   572 {
   564 }
   574 }
   565 
   575 
   566 template <class Key, class T>
   576 template <class Key, class T>
   567 Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::detach_helper()
   577 Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::detach_helper()
   568 {
   578 {
   569     QHashData *x = d->detach_helper(duplicateNode, deleteNode,
   579     QHashData *x = d->detach_helper2(duplicateNode, deleteNode2,
   570         QTypeInfo<T>::isDummy ? sizeof(DummyNode) : sizeof(Node));
   580         QTypeInfo<T>::isDummy ? sizeof(DummyNode) : sizeof(Node),
       
   581         QTypeInfo<T>::isDummy ? alignOfDummyNode() : alignOfNode());
   571     if (!d->ref.deref())
   582     if (!d->ref.deref())
   572         freeData(d);
   583         freeData(d);
   573     d = x;
   584     d = x;
   574 }
   585 }
   575 
   586