File indexing completed on 2023-12-03 07:43:21
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 #ifndef _DOM_IDSTRING_h_ 0023 #define _DOM_IDSTRING_h_ 0024 0025 #include "misc/shared.h" 0026 #include "dom/dom_string.h" 0027 #include "xml/dom_stringimpl.h" 0028 #include "wtf/Vector.h" 0029 #include <QHash> 0030 0031 using DOM::DOMString; 0032 using DOM::DOMStringImpl; 0033 0034 namespace khtml 0035 { 0036 0037 // When we're working with a case-insensitive language, IDString can lookup 0038 // IDs from strings ignoring the case itself; however it needs to be told 0039 // what the canonical case is, so it knows what hash code to look for. 0040 enum CaseNormalizeMode { 0041 IDS_CaseSensitive, 0042 IDS_NormalizeUpper, 0043 IDS_NormalizeLower 0044 }; 0045 0046 /** 0047 An IDString is used to manage an identifier namespace that has some predefined constants, 0048 but can be extended with new ones at runtime 0049 0050 The TableFactory template parameter must point to a class 0051 that provides an idTable method returning a singleton IDTable<TableFactory> 0052 */ 0053 template<typename TableFactory> 0054 class IDString 0055 { 0056 private: 0057 unsigned short m_id; 0058 0059 public: 0060 // id 0xFFFF is handled specially in derefId so it's our default.. 0061 IDString(): m_id(0xFFFF) {} 0062 0063 IDString<TableFactory> &operator=(const IDString &other) 0064 { 0065 TableFactory::idTable()->refId(other.m_id); 0066 TableFactory::idTable()->derefId(m_id); 0067 m_id = other.m_id; 0068 return *this; 0069 } 0070 0071 IDString(const IDString &other) 0072 { 0073 m_id = other.m_id; 0074 TableFactory::idTable()->refId(m_id); 0075 } 0076 0077 ~IDString() 0078 { 0079 TableFactory::idTable()->derefId(m_id); 0080 } 0081 0082 unsigned id() const 0083 { 0084 return m_id; 0085 } 0086 0087 DOMString toString() const 0088 { 0089 return TableFactory::idTable()->idToString(m_id); 0090 } 0091 0092 static IDString<TableFactory> fromId(unsigned short id) 0093 { 0094 IDString<TableFactory> nw; 0095 nw.m_id = id; 0096 TableFactory::idTable()->refId(id); 0097 return nw; 0098 } 0099 0100 static IDString<TableFactory> fromString(const DOMString &string, CaseNormalizeMode cnm = IDS_CaseSensitive) 0101 { 0102 return fromString(string.implementation(), cnm); 0103 } 0104 0105 static IDString<TableFactory> fromString(DOMStringImpl *string, CaseNormalizeMode cnm = IDS_CaseSensitive) 0106 { 0107 IDString<TableFactory> nw; 0108 nw.m_id = TableFactory::idTable()->grabId(string, cnm); // Refs it already. 0109 return nw; 0110 } 0111 0112 bool operator==(const IDString<TableFactory> &other) const 0113 { 0114 return m_id == other.m_id; 0115 } 0116 0117 QDebug operator<<(QDebug stream) const 0118 { 0119 return id() ? (stream << id() << toString()) : "null idstring"; 0120 } 0121 }; 0122 0123 class IDTableBase 0124 { 0125 struct Mapping { 0126 unsigned refCount; // # of references, 0 if not in use. 0127 DOMStringImpl *name; // same as our key, so no separate 0128 // refcount (except for hidden mappings) 0129 0130 Mapping(): refCount(0) 0131 {} 0132 0133 Mapping(DOMStringImpl *_name): refCount(0), name(_name) 0134 {} 0135 }; 0136 0137 public: 0138 // Wraps around DOMString and lets us trigger key sensitivity for lookup; 0139 // that's done via a global fiddle --- warning, warning, warning. 0140 struct MappingKey { 0141 DOMStringImpl *str; 0142 bool operator==(const MappingKey &other) const; 0143 0144 MappingKey() {} 0145 MappingKey(DOMStringImpl *v): str(v) {} 0146 0147 static CaseNormalizeMode caseNormalizationMode; 0148 }; 0149 protected: 0150 void refId(unsigned id) 0151 { 0152 if (id == 0xFFFF) { 0153 return; 0154 } 0155 ++m_mappings[id].refCount; 0156 } 0157 0158 void derefId(unsigned id) 0159 { 0160 if (id == 0xFFFF) { 0161 return; 0162 } 0163 --m_mappings[id].refCount; 0164 if (m_mappings[id].refCount == 0) { 0165 releaseId(id); 0166 } 0167 } 0168 0169 const DOMString idToString(unsigned id) 0170 { 0171 return DOMString(m_mappings[id].name); 0172 } 0173 0174 unsigned short grabId(DOMStringImpl *string, CaseNormalizeMode cnm); 0175 0176 public: 0177 // Registers a compile-type known ID constant with the name. 0178 // This must be called before any other operations 0179 void addStaticMapping(unsigned id, const DOMString &string); 0180 0181 // Registers a hidden ID constant --- it has a name, but it 0182 // can not be looked up by it. 0183 void addHiddenMapping(unsigned id, const DOMString &string); 0184 private: 0185 void releaseId(unsigned id); 0186 0187 WTF::Vector <unsigned> m_idFreeList; 0188 WTF::Vector <Mapping> m_mappings; 0189 QHash <MappingKey, unsigned short> m_mappingLookup; 0190 }; 0191 0192 template<typename TableFactory> 0193 class IDTable: public IDTableBase 0194 { 0195 public: 0196 // Export methods to our version of IDString 0197 friend class IDString<TableFactory>; 0198 using IDTableBase::refId; 0199 using IDTableBase::derefId; 0200 IDTable() {} 0201 }; 0202 0203 } 0204 0205 /** 0206 Now these are the various ID types we used.. They are here to avoid circular 0207 dependenies in headers 0208 */ 0209 namespace DOM 0210 { 0211 class EventImpl; 0212 typedef khtml::IDString<EventImpl> EventName; 0213 } 0214 0215 #endif