/* * 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. * */ #ifndef _DOM_IDSTRING_h_ #define _DOM_IDSTRING_h_ #include "misc/shared.h" #include "dom/dom_string.h" #include "xml/dom_stringimpl.h" #include "wtf/Vector.h" #include using DOM::DOMString; using DOM::DOMStringImpl; namespace khtml { // When we're working with a case-insensitive language, IDString can lookup // IDs from strings ignoring the case itself; however it needs to be told // what the canonical case is, so it knows what hash code to look for. enum CaseNormalizeMode { IDS_CaseSensitive, IDS_NormalizeUpper, IDS_NormalizeLower }; /** An IDString is used to manage an identifier namespace that has some predefined constants, but can be extended with new ones at runtime The TableFactory template parameter must point to a class that provides an idTable method returning a singleton IDTable */ template class IDString { private: unsigned short m_id; public: // id 0xFFFF is handled specially in derefId so it's our default.. IDString(): m_id(0xFFFF) {} IDString& operator=(const IDString& other) { TableFactory::idTable()->refId (other.m_id); TableFactory::idTable()->derefId(m_id); m_id = other.m_id; return *this; } IDString(const IDString& other) { m_id = other.m_id; TableFactory::idTable()->refId(m_id); } ~IDString() { TableFactory::idTable()->derefId(m_id); } unsigned id() const { return m_id; } DOMString toString() const { return TableFactory::idTable()->idToString(m_id); } static IDString fromId(unsigned short id) { IDString nw; nw.m_id = id; TableFactory::idTable()->refId(id); return nw; } static IDString fromString(const DOMString& string, CaseNormalizeMode cnm = IDS_CaseSensitive) { return fromString(string.implementation(), cnm); } static IDString fromString(DOMStringImpl* string, CaseNormalizeMode cnm = IDS_CaseSensitive) { IDString nw; nw.m_id = TableFactory::idTable()->grabId(string, cnm); // Refs it already. return nw; } bool operator==(const IDString& other) const { return m_id == other.m_id; } QDebug operator<<(QDebug stream) const { return id() ? (stream << id() << toString()) : "null idstring"; } }; class IDTableBase { struct Mapping { unsigned refCount; // # of references, 0 if not in use. DOMStringImpl* name; // same as our key, so no separate // refcount (except for hidden mappings) Mapping(): refCount(0) {} Mapping(DOMStringImpl* _name): refCount(0), name(_name) {} }; public: // Wraps around DOMString and lets us trigger key sensitivity for lookup; // that's done via a global fiddle --- warning, warning, warning. struct MappingKey { DOMStringImpl* str; bool operator==(const MappingKey& other) const; MappingKey() {} MappingKey(DOMStringImpl* v): str(v) {} static CaseNormalizeMode caseNormalizationMode; }; protected: void refId(unsigned id) { if (id == 0xFFFF) return; ++m_mappings[id].refCount; } void derefId(unsigned id) { if (id == 0xFFFF) return; --m_mappings[id].refCount; if (m_mappings[id].refCount == 0) releaseId(id); } const DOMString idToString(unsigned id) { return DOMString(m_mappings[id].name); } unsigned short grabId(DOMStringImpl* string, CaseNormalizeMode cnm); public: // Registers a compile-type known ID constant with the name. // This must be called before any other operations void addStaticMapping(unsigned id, const DOMString& string); // Registers a hidden ID constant --- it has a name, but it // can not be looked up by it. void addHiddenMapping(unsigned id, const DOMString& string); private: void releaseId(unsigned id); WTF::Vector m_idFreeList; WTF::Vector m_mappings; QHash m_mappingLookup; }; template class IDTable: public IDTableBase { public: // Export methods to our version of IDString friend class IDString; using IDTableBase::refId; using IDTableBase::derefId; IDTable() {} }; } /** Now these are the various ID types we used.. They are here to avoid circular dependenies in headers */ namespace DOM { class EventImpl; typedef khtml::IDString EventName; } #endif // kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;