1 // -*- c-basic-offset: 2 -*-
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
5 * Copyright (C) 2003 Apple Computer, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "identifier.h"
33 * An entry in a hash table.
37 * s is the key (e.g. a property name)
41 * value is the result value (usually an enum value)
45 * attr is a set for flags (e.g. the property flags, see object.h)
49 * params is another number. For property hashtables, it is used to
50 * denote the number of argument of the function
54 * next is the pointer to the next entry for the same hash value
56 const HashEntry *next;
61 * Usually the hashtable is generated by the create_hash_table script, from a .table file.
63 * The implementation uses an array of entries, "size" is the total size of that array.
64 * The entries between 0 and hashSize-1 are the entry points
65 * for each hash value, and the entries between hashSize and size-1
66 * are the overflow entries for the hash values that need one.
67 * The "next" pointer of the entry links entry points to overflow entries,
68 * and links overflow entries between them.
72 * type is a version number. Currently always 2
76 * size is the total number of entries in the hashtable, including the null entries,
77 * i.e. the size of the "entries" array.
78 * Used to iterate over all entries in the table
82 * pointer to the array of entries
83 * Mind that some entries in the array are null (0,0,0,0).
85 const HashEntry *entries;
87 * the maximum value for the hash. Always smaller than size.
93 * @short Fast keyword lookup.
98 * Find an entry in the table, and return its value (i.e. the value field of HashEntry)
100 static int find(const struct HashTable *table, const Identifier &s);
101 static int find(const struct HashTable *table,
102 const UChar *c, unsigned int len);
105 * Find an entry in the table, and return the entry
106 * This variant gives access to the other attributes of the entry,
107 * especially the attr field.
109 static const HashEntry* findEntry(const struct HashTable *table,
110 const Identifier &s);
111 static const HashEntry* findEntry(const struct HashTable *table,
112 const UChar *c, unsigned int len);
115 * Calculate the hash value for a given key
117 static unsigned int hash(const Identifier &key);
118 static unsigned int hash(const UChar *c, unsigned int len);
119 static unsigned int hash(const char *s);
126 * Helper for lookupFunction and lookupValueOrFunction
128 template <class FuncImp>
129 inline Value lookupOrCreateFunction(ExecState *exec, const Identifier &propertyName,
130 const ObjectImp *thisObj, int token, int params, int attr)
132 // Look for cached value in dynamic map of properties (in ObjectImp)
133 ValueImp * cachedVal = thisObj->ObjectImp::getDirect(propertyName);
135 fprintf(stderr, "lookupOrCreateFunction: Function -> looked up in ObjectImp, found type=%d\n", cachedVal->type());*/
137 return Value(cachedVal);
139 Value val = Value(new FuncImp(exec,token, params));
140 ObjectImp *thatObj = const_cast<ObjectImp *>(thisObj);
141 thatObj->ObjectImp::put(exec, propertyName, val, attr);
146 * Helper method for property lookups
148 * This method does it all (looking in the hashtable, checking for function
149 * overrides, creating the function or retrieving from cache, calling
150 * getValueProperty in case of a non-function property, forwarding to parent if
153 * Template arguments:
154 * @param FuncImp the class which implements this object's functions
155 * @param ThisImp the class of "this". It must implement the getValueProperty(exec,token) method,
156 * for non-function properties.
157 * @param ParentImp the class of the parent, to propagate the lookup.
160 * @param exec execution state, as usual
161 * @param propertyName the property we're looking for
162 * @param table the static hashtable for this class
163 * @param thisObj "this"
165 template <class FuncImp, class ThisImp, class ParentImp>
166 inline Value lookupGet(ExecState *exec, const Identifier &propertyName,
167 const HashTable* table, const ThisImp* thisObj)
169 const HashEntry* entry = Lookup::findEntry(table, propertyName);
171 if (!entry) // not found, forward to parent
172 return thisObj->ParentImp::get(exec, propertyName);
174 //fprintf(stderr, "lookupGet: found value=%d attr=%d\n", entry->value, entry->attr);
175 if (entry->attr & Function)
176 return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
177 return thisObj->getValueProperty(exec, entry->value);
181 * Simplified version of lookupGet in case there are only functions.
182 * Using this instead of lookupGet prevents 'this' from implementing a dummy getValueProperty.
184 template <class FuncImp, class ParentImp>
185 inline Value lookupGetFunction(ExecState *exec, const Identifier &propertyName,
186 const HashTable* table, const ObjectImp* thisObj)
188 const HashEntry* entry = Lookup::findEntry(table, propertyName);
190 if (!entry) // not found, forward to parent
191 return static_cast<const ParentImp *>(thisObj)->ParentImp::get(exec, propertyName);
193 if (entry->attr & Function)
194 return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
196 fprintf(stderr, "Function bit not set! Shouldn't happen in lookupGetFunction!\n" );
201 * Simplified version of lookupGet in case there are no functions, only "values".
202 * Using this instead of lookupGet removes the need for a FuncImp class.
204 template <class ThisImp, class ParentImp>
205 inline Value lookupGetValue(ExecState *exec, const Identifier &propertyName,
206 const HashTable* table, const ThisImp* thisObj)
208 const HashEntry* entry = Lookup::findEntry(table, propertyName);
210 if (!entry) // not found, forward to parent
211 return thisObj->ParentImp::get(exec, propertyName);
213 if (entry->attr & Function)
214 fprintf(stderr, "Function bit set! Shouldn't happen in lookupGetValue! propertyName was %s\n", propertyName.ascii() );
215 return thisObj->getValueProperty(exec, entry->value);
219 * This one is for "put".
220 * Lookup hash entry for property to be set, and set the value.
222 template <class ThisImp, class ParentImp>
223 inline void lookupPut(ExecState *exec, const Identifier &propertyName,
224 const Value& value, int attr,
225 const HashTable* table, const ThisImp* thisObj)
227 const HashEntry* entry = Lookup::findEntry(table, propertyName);
229 if (!entry) // not found: forward to parent
230 thisObj->ParentImp::put(exec, propertyName, value, attr);
231 else if (entry->attr & Function) // function: put as override property
232 thisObj->ObjectImp::put(exec, propertyName, value, attr);
233 else if (entry->attr & ReadOnly) // readonly! Can't put!
235 fprintf(stderr,"WARNING: Attempt to change value of readonly property '%s'\n",propertyName.ascii());
240 thisObj->putValueProperty(exec, entry->value, value, attr);
244 * List of things to do when porting an objectimp to the 'static hashtable' mechanism:
245 * - write the hashtable source, between @begin and @end
246 * - add a rule to build the .lut.h
247 * - include the .lut.h
248 * - mention the table in the classinfo (add a classinfo if necessary)
249 * - write/update the class enum (for the tokens)
250 * - turn get() into getValueProperty(), put() into putValueProperty(), using a switch and removing funcs
251 * - write get() and/or put() using a template method
252 * - cleanup old stuff (e.g. hasProperty)
253 * - compile, test, commit ;)