webengine/osswebengine/WebCore/dom/QualifiedName.cpp
changeset 0 dd21522fd290
child 13 10e98eab6f85
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /**
       
     2  * This file is part of the DOM implementation for KDE.
       
     3  *
       
     4  * Copyright (C) 2005, 2006 Apple Computer, Inc.
       
     5  *
       
     6  * This library is free software; you can redistribute it and/or
       
     7  * modify it under the terms of the GNU Library General Public
       
     8  * License as published by the Free Software Foundation; either
       
     9  * version 2 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This library is distributed in the hope that it will be useful,
       
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    14  * Library General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU Library General Public License
       
    17  * along with this library; see the file COPYING.LIB.  If not, write to
       
    18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    19  * Boston, MA 02110-1301, USA.
       
    20  */
       
    21 
       
    22 #include "config.h"
       
    23 
       
    24 #ifdef AVOID_STATIC_CONSTRUCTORS
       
    25 #define WEBCORE_QUALIFIEDNAME_HIDE_GLOBALS 1
       
    26 #else
       
    27 #define QNAME_DEFAULT_CONSTRUCTOR
       
    28 #endif
       
    29 
       
    30 #include "QualifiedName.h"
       
    31 #include "StaticConstructors.h"
       
    32 #include <wtf/Assertions.h>
       
    33 #include <wtf/HashSet.h>
       
    34 
       
    35 namespace WebCore {
       
    36 
       
    37 struct QualifiedNameComponents {
       
    38     StringImpl* m_prefix;
       
    39     StringImpl* m_localName;
       
    40     StringImpl* m_namespace;
       
    41 };
       
    42 
       
    43 // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
       
    44 static const unsigned PHI = 0x9e3779b9U;
       
    45     
       
    46 static inline unsigned hashComponents(const QualifiedNameComponents& buf)
       
    47 {
       
    48     ASSERT(sizeof(QualifiedNameComponents) % (sizeof(uint16_t) * 2) == 0);
       
    49 
       
    50     unsigned l = sizeof(QualifiedNameComponents) / (sizeof(uint16_t) * 2);
       
    51     const uint16_t* s = reinterpret_cast<const uint16_t*>(&buf);
       
    52     uint32_t hash = PHI;
       
    53 
       
    54     // Main loop
       
    55     for (; l > 0; l--) {
       
    56         hash += s[0];
       
    57         uint32_t tmp = (s[1] << 11) ^ hash;
       
    58         hash = (hash << 16) ^ tmp;
       
    59         s += 2;
       
    60         hash += hash >> 11;
       
    61     }
       
    62         
       
    63     // Force "avalanching" of final 127 bits
       
    64     hash ^= hash << 3;
       
    65     hash += hash >> 5;
       
    66     hash ^= hash << 2;
       
    67     hash += hash >> 15;
       
    68     hash ^= hash << 10;
       
    69 
       
    70     // this avoids ever returning a hash code of 0, since that is used to
       
    71     // signal "hash not computed yet", using a value that is likely to be
       
    72     // effectively the same as 0 when the low bits are masked
       
    73     if (hash == 0)
       
    74         hash = 0x80000000;
       
    75 
       
    76     return hash;
       
    77 }
       
    78 
       
    79 struct QNameHash {
       
    80     static unsigned hash(const QualifiedName::QualifiedNameImpl* name) {    
       
    81         QualifiedNameComponents c = { name->m_prefix.impl(), name->m_localName.impl(), name->m_namespace.impl() };
       
    82         return hashComponents(c);
       
    83     }
       
    84     static bool equal(const QualifiedName::QualifiedNameImpl* a, const QualifiedName::QualifiedNameImpl* b) { return a == b; }
       
    85 };
       
    86 
       
    87 typedef HashSet<QualifiedName::QualifiedNameImpl*, QNameHash> QNameSet;
       
    88 
       
    89 struct QNameComponentsTranslator {
       
    90     static unsigned hash(const QualifiedNameComponents& components) { 
       
    91         return hashComponents(components); 
       
    92     }
       
    93     static bool equal(QualifiedName::QualifiedNameImpl* name, const QualifiedNameComponents& c) {
       
    94         return c.m_prefix == name->m_prefix.impl() && c.m_localName == name->m_localName.impl() && c.m_namespace == name->m_namespace.impl();
       
    95     }
       
    96     static void translate(QualifiedName::QualifiedNameImpl*& location, const QualifiedNameComponents& components, unsigned hash) {
       
    97         location = new QualifiedName::QualifiedNameImpl(components.m_prefix, components.m_localName, components.m_namespace);
       
    98     }
       
    99 };
       
   100 
       
   101 static QNameSet* gNameCache;
       
   102 
       
   103 QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const AtomicString& n)
       
   104     : m_impl(0)
       
   105 {
       
   106     if (!gNameCache)
       
   107         gNameCache = new QNameSet;
       
   108     QualifiedNameComponents components = { p.impl(), l.impl(), n.impl() };
       
   109     m_impl = *gNameCache->add<QualifiedNameComponents, QNameComponentsTranslator>(components).first;    
       
   110     ref();
       
   111 }
       
   112 
       
   113 QualifiedName::~QualifiedName()
       
   114 {
       
   115     deref();
       
   116 }
       
   117 
       
   118 QualifiedName::QualifiedName(const QualifiedName& other)
       
   119 {
       
   120     m_impl = other.m_impl;
       
   121     ref();
       
   122 }
       
   123 
       
   124 const QualifiedName& QualifiedName::operator=(const QualifiedName& other)
       
   125 {
       
   126     if (m_impl != other.m_impl) {
       
   127         deref();
       
   128         m_impl = other.m_impl;
       
   129         ref();
       
   130     }
       
   131     
       
   132     return *this;
       
   133 }
       
   134 
       
   135 void QualifiedName::deref()
       
   136 {
       
   137 #ifdef QNAME_DEFAULT_CONSTRUCTOR
       
   138     if (!m_impl)
       
   139         return;
       
   140 #endif
       
   141 
       
   142     if (m_impl->hasOneRef())
       
   143         gNameCache->remove(m_impl);
       
   144     m_impl->deref();
       
   145 }
       
   146 
       
   147 void QualifiedName::setPrefix(const AtomicString& prefix)
       
   148 {
       
   149     QualifiedName other(prefix, localName(), namespaceURI());
       
   150     *this = other;
       
   151 }
       
   152 
       
   153 String QualifiedName::toString() const
       
   154 {
       
   155     String local = localName();
       
   156     if (hasPrefix())
       
   157         return prefix() + ":" + local;
       
   158     return local;
       
   159 }
       
   160 
       
   161 // Global init routines
       
   162 DEFINE_GLOBAL(QualifiedName, anyName, nullAtom, starAtom, starAtom)
       
   163 
       
   164 void QualifiedName::init()
       
   165 {
       
   166     static bool initialized;
       
   167     if (!initialized) {
       
   168         // Use placement new to initialize the globals.
       
   169         
       
   170         AtomicString::init();
       
   171         new ((void*)&anyName) QualifiedName(nullAtom, starAtom, starAtom);
       
   172         initialized = true;
       
   173     }
       
   174 }
       
   175 
       
   176 }