File indexing completed on 2024-10-13 12:12:53
0001 /* 0002 * This file is part of the DOM implementation for KDE. 0003 * 0004 * Copyright (C) 2008, 2009 Maksim Orlovich (maksim@kde.org) 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 * 0021 */ 0022 0023 #include "idstring.h" 0024 #include <assert.h> 0025 0026 namespace khtml 0027 { 0028 0029 CaseNormalizeMode IDTableBase::MappingKey::caseNormalizationMode; 0030 0031 bool IDTableBase::MappingKey::operator==(const MappingKey &other) const 0032 { 0033 if (IDTableBase::MappingKey::caseNormalizationMode == IDS_CaseSensitive) { 0034 return !strcmp(str, other.str); 0035 } else { 0036 return !strcasecmp(str, other.str); 0037 } 0038 } 0039 0040 static inline unsigned int qHash(const IDTableBase::MappingKey &key) 0041 { 0042 if (!key.str) { 0043 return 82610334; //same as empty 0044 } else if (key.caseNormalizationMode == IDS_CaseSensitive) { 0045 return key.str->hash(); 0046 } else if (key.caseNormalizationMode == IDS_NormalizeLower) { 0047 return key.str->lowerHash(); 0048 } else { // caseNormalizationMode == IDS_NormalizeUpper 0049 return key.str->upperHash(); 0050 } 0051 } 0052 0053 void IDTableBase::releaseId(unsigned id) 0054 { 0055 IDTableBase::MappingKey::caseNormalizationMode = IDS_CaseSensitive; 0056 0057 m_mappingLookup.remove(m_mappings[id].name); 0058 m_mappings[id].name->deref(); 0059 m_idFreeList.append(id); 0060 } 0061 0062 unsigned short IDTableBase::grabId(DOMStringImpl *origName, CaseNormalizeMode cnm) 0063 { 0064 unsigned short newId; 0065 0066 // Check for existing one, ignoring case if needed 0067 IDTableBase::MappingKey::caseNormalizationMode = cnm; 0068 QHash<MappingKey, unsigned short>::const_iterator i = m_mappingLookup.constFind(origName); 0069 if (i != m_mappingLookup.constEnd()) { 0070 newId = *i; 0071 refId(newId); 0072 return newId; 0073 } 0074 0075 // Nope. Allocate new ID. If there is normalization going on, we may now have to 0076 // update our case so the canonical mapping is of the expected case. We 0077 // may also have to deep-copy 0078 DOMStringImpl *name = nullptr; 0079 switch (cnm) { 0080 case IDS_CaseSensitive: 0081 if (origName->m_shallowCopy) { 0082 // Create a new copy of the data since we may be extending its 0083 // lifetime indefinitely 0084 name = new DOMStringImpl(origName->s, origName->l); 0085 name->m_hash = origName->m_hash; 0086 } else { 0087 name = origName; 0088 } 0089 break; 0090 case IDS_NormalizeUpper: 0091 name = origName->upper(); 0092 break; 0093 case IDS_NormalizeLower: 0094 name = origName->lower(); 0095 break; 0096 } 0097 0098 Q_ASSERT(name); 0099 name->ref(); 0100 0101 if (!m_idFreeList.isEmpty()) { 0102 // Grab from freelist.. 0103 newId = m_idFreeList.last(); 0104 m_idFreeList.removeLast(); 0105 m_mappings[newId].name = name; 0106 } else { 0107 // Make a new one --- if we can (we keep one spot for "last resort" mapping) 0108 if (m_mappings.size() < 0xFFFE) { 0109 m_mappings.append(Mapping(name)); 0110 newId = m_mappings.size() - 1; 0111 } else { 0112 // We ran out of resources. Did we add a fallback mapping yet? 0113 // We use the same one for everything; and don't even keep track 0114 // of what it may go to, as we will have no way of freeing 0115 // the aliases. In particular, this means we no longer need the name.. 0116 name->deref(); 0117 0118 if (m_mappings.size() == 0xFFFE) { 0119 // Need a new mapping.. 0120 name = new DOMStringImpl("_khtml_fallback"); 0121 m_mappings.append(Mapping(name)); 0122 m_mappings[0xFFFF].refCount = 1; // pin it. 0123 name->ref(); 0124 } else { 0125 name = m_mappings[0xFFFF].name; // No need to ref the name 0126 // here as the entry is eternal anyway 0127 } 0128 newId = 0xFFFF; 0129 } 0130 } 0131 0132 m_mappingLookup[name] = newId; 0133 0134 refId(newId); 0135 return newId; 0136 } 0137 0138 void IDTableBase::addStaticMapping(unsigned id, const DOMString &name) 0139 { 0140 addHiddenMapping(id, name); 0141 IDTableBase::MappingKey::caseNormalizationMode = IDS_CaseSensitive; 0142 m_mappingLookup[name.implementation()] = id; 0143 } 0144 0145 void IDTableBase::addHiddenMapping(unsigned id, const DOMString &name) 0146 { 0147 DOMStringImpl *nameImpl = name.implementation(); 0148 if (nameImpl) { 0149 nameImpl->ref(); 0150 } 0151 0152 if (id >= m_mappings.size()) { 0153 m_mappings.resize(id + 1); 0154 } 0155 m_mappings[id] = Mapping(nameImpl); 0156 m_mappings[id].refCount = 1; // Pin it. 0157 } 0158 0159 } 0160