/* * This file is part of the DOM implementation for KDE. * * Copyright (C) 2008, 2009 Maksim Orlovich (maksim@kde.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "idstring.h" #include namespace khtml { CaseNormalizeMode IDTableBase::MappingKey::caseNormalizationMode; bool IDTableBase::MappingKey::operator==(const MappingKey& other) const { if (IDTableBase::MappingKey::caseNormalizationMode == IDS_CaseSensitive) return !strcmp(str, other.str); else return !strcasecmp(str, other.str); } static inline unsigned int qHash(const IDTableBase::MappingKey& key) { if (!key.str) { return 82610334; //same as empty } else if (key.caseNormalizationMode == IDS_CaseSensitive) { return key.str->hash(); } else if (key.caseNormalizationMode == IDS_NormalizeLower) { return key.str->lowerHash(); } else { // caseNormalizationMode == IDS_NormalizeUpper return key.str->upperHash(); } } void IDTableBase::releaseId(unsigned id) { IDTableBase::MappingKey::caseNormalizationMode = IDS_CaseSensitive; m_mappingLookup.remove(m_mappings[id].name); m_mappings[id].name->deref(); m_idFreeList.append(id); } unsigned short IDTableBase::grabId(DOMStringImpl* origName, CaseNormalizeMode cnm) { unsigned short newId; // Check for existing one, ignoring case if needed IDTableBase::MappingKey::caseNormalizationMode = cnm; QHash::const_iterator i = m_mappingLookup.constFind(origName); if (i != m_mappingLookup.constEnd()) { newId = *i; refId(newId); return newId; } // Nope. Allocate new ID. If there is normalization going on, we may now have to // update our case so the canonical mapping is of the expected case. We // may also have to deep-copy DOMStringImpl* name; switch (cnm) { case IDS_CaseSensitive: if (origName->m_shallowCopy) { // Create a new copy of the data since we may be extending its // lifetime indefinitely name = new DOMStringImpl(origName->s, origName->l); name->m_hash = origName->m_hash; } else { name = origName; } break; case IDS_NormalizeUpper: name = origName->upper(); break; case IDS_NormalizeLower: name = origName->lower(); break; } name->ref(); if (!m_idFreeList.isEmpty()) { // Grab from freelist.. newId = m_idFreeList.last(); m_idFreeList.removeLast(); m_mappings[newId].name = name; } else { // Make a new one --- if we can (we keep one spot for "last resort" mapping) if (m_mappings.size() < 0xFFFE) { m_mappings.append(Mapping(name)); newId = m_mappings.size() - 1; } else { // We ran out of resources. Did we add a fallback mapping yet? // We use the same one for everything; and don't even keep track // of what it may go to, as we will have no way of freeing // the aliases. In particular, this means we no longer need the name.. name->deref(); if (m_mappings.size() == 0xFFFE) { // Need a new mapping.. name = new DOMStringImpl("_khtml_fallback"); m_mappings.append(Mapping(name)); m_mappings[0xFFFF].refCount = 1; // pin it. name->ref(); } else { name = m_mappings[0xFFFF].name; // No need to ref the name // here as the entry is eternal anyway } newId = 0xFFFF; } } m_mappingLookup[name] = newId; refId(newId); return newId; } void IDTableBase::addStaticMapping(unsigned id, const DOMString& name) { addHiddenMapping(id, name); IDTableBase::MappingKey::caseNormalizationMode = IDS_CaseSensitive; m_mappingLookup[name.implementation()] = id; } void IDTableBase::addHiddenMapping(unsigned id, const DOMString& name) { DOMStringImpl* nameImpl = name.implementation(); if (nameImpl) nameImpl->ref(); if (id >= m_mappings.size()) m_mappings.resize(id + 1); m_mappings[id] = Mapping(nameImpl); m_mappings[id].refCount = 1; // Pin it. } } // kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;