kjs Library API Documentation

lookup.h

00001 // -*- c-basic-offset: 2 -*- 00002 /* 00003 * This file is part of the KDE libraries 00004 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 00005 * Copyright (C) 2003 Apple Computer, Inc. 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 * 00021 */ 00022 00023 #ifndef _KJSLOOKUP_H_ 00024 #define _KJSLOOKUP_H_ 00025 00026 #include "identifier.h" 00027 #include "value.h" 00028 #include "object.h" 00029 #include "interpreter.h" 00030 #include <stdio.h> 00031 00032 namespace KJS { 00033 00037 struct HashEntry { 00041 unsigned short soffset; 00045 short int value; 00049 unsigned char attr; 00054 unsigned char params; 00058 short next; 00059 }; 00060 00072 struct HashTable { 00076 int type; 00082 int size; 00087 const HashEntry *const entries; 00091 int hashSize; 00092 00096 const char* const sbase; 00097 }; 00098 00102 class Lookup { 00103 public: 00107 static int find(const struct HashTable *table, const Identifier &s); 00108 static int find(const struct HashTable *table, 00109 const UChar *c, unsigned int len); 00110 00116 static const HashEntry* findEntry(const struct HashTable *table, 00117 const Identifier &s); 00118 static const HashEntry* findEntry(const struct HashTable *table, 00119 const UChar *c, unsigned int len); 00120 00124 static unsigned int hash(const Identifier &key); 00125 static unsigned int hash(const UChar *c, unsigned int len); 00126 static unsigned int hash(const char *s); 00127 }; 00128 00129 class ExecState; 00130 class UString; 00135 template <class FuncImp> 00136 inline Value lookupOrCreateFunction(ExecState *exec, const Identifier &propertyName, 00137 const ObjectImp *thisObj, int token, int params, int attr) 00138 { 00139 // Look for cached value in dynamic map of properties (in ObjectImp) 00140 ValueImp * cachedVal = thisObj->ObjectImp::getDirect(propertyName); 00141 /*if (cachedVal) 00142 fprintf(stderr, "lookupOrCreateFunction: Function -> looked up in ObjectImp, found type=%d\n", cachedVal->type());*/ 00143 if (cachedVal) 00144 return Value(cachedVal); 00145 00146 ObjectImp* func = new FuncImp( exec, token, params ); 00147 Value val( func ); 00148 func->setFunctionName( propertyName ); 00149 ObjectImp *thatObj = const_cast<ObjectImp *>(thisObj); 00150 thatObj->ObjectImp::put(exec, propertyName, val, attr); 00151 return val; 00152 } 00153 00174 template <class FuncImp, class ThisImp, class ParentImp> 00175 inline Value lookupGet(ExecState *exec, const Identifier &propertyName, 00176 const HashTable* table, const ThisImp* thisObj) 00177 { 00178 const HashEntry* entry = Lookup::findEntry(table, propertyName); 00179 00180 if (!entry) // not found, forward to parent 00181 return thisObj->ParentImp::get(exec, propertyName); 00182 00183 //fprintf(stderr, "lookupGet: found value=%d attr=%d\n", entry->value, entry->attr); 00184 if (entry->attr & Function) 00185 return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr); 00186 return thisObj->getValueProperty(exec, entry->value); 00187 } 00188 00193 template <class FuncImp, class ParentImp> 00194 inline Value lookupGetFunction(ExecState *exec, const Identifier &propertyName, 00195 const HashTable* table, const ObjectImp* thisObj) 00196 { 00197 const HashEntry* entry = Lookup::findEntry(table, propertyName); 00198 00199 if (!entry) // not found, forward to parent 00200 return static_cast<const ParentImp *>(thisObj)->ParentImp::get(exec, propertyName); 00201 00202 if (entry->attr & Function) 00203 return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr); 00204 00205 fprintf(stderr, "Function bit not set! Shouldn't happen in lookupGetFunction!\n" ); 00206 return Undefined(); 00207 } 00208 00213 template <class ThisImp, class ParentImp> 00214 inline Value lookupGetValue(ExecState *exec, const Identifier &propertyName, 00215 const HashTable* table, const ThisImp* thisObj) 00216 { 00217 const HashEntry* entry = Lookup::findEntry(table, propertyName); 00218 00219 if (!entry) // not found, forward to parent 00220 return thisObj->ParentImp::get(exec, propertyName); 00221 00222 if (entry->attr & Function) 00223 fprintf(stderr, "Function bit set! Shouldn't happen in lookupGetValue! propertyName was %s\n", propertyName.ascii() ); 00224 return thisObj->getValueProperty(exec, entry->value); 00225 } 00226 00231 template <class ThisImp, class ParentImp> 00232 inline void lookupPut(ExecState *exec, const Identifier &propertyName, 00233 const Value& value, int attr, 00234 const HashTable* table, ThisImp* thisObj) 00235 { 00236 const HashEntry* entry = Lookup::findEntry(table, propertyName); 00237 00238 if (!entry) // not found: forward to parent 00239 thisObj->ParentImp::put(exec, propertyName, value, attr); 00240 else if (entry->attr & Function) // function: put as override property 00241 thisObj->ObjectImp::put(exec, propertyName, value, attr); 00242 else if (entry->attr & ReadOnly) // readonly! Can't put! 00243 #ifdef KJS_VERBOSE 00244 fprintf(stderr,"WARNING: Attempt to change value of readonly property '%s'\n",propertyName.ascii()); 00245 #else 00246 ; // do nothing 00247 #endif 00248 else 00249 thisObj->putValueProperty(exec, entry->value, value, attr); 00250 } 00251 00252 00260 template <class ClassCtor> 00261 inline KJS::Object cacheGlobalObject(ExecState *exec, const Identifier &propertyName) 00262 { 00263 ValueImp *obj = static_cast<KJS::ObjectImp*>(exec->interpreter()->globalObject().imp())->getDirect(propertyName); 00264 if (obj) 00265 return KJS::Object::dynamicCast(Value(obj)); 00266 else 00267 { 00268 KJS::Object newObject(new ClassCtor(exec)); 00269 exec->interpreter()->globalObject().put(exec, propertyName, newObject, Internal); 00270 return newObject; 00271 } 00272 } 00273 00274 00291 #define DEFINE_PROTOTYPE(ClassName,ClassProto) \ 00292 namespace KJS { \ 00293 class ClassProto : public KJS::ObjectImp { \ 00294 friend KJS::Object cacheGlobalObject<ClassProto>(KJS::ExecState *exec, const KJS::Identifier &propertyName); \ 00295 public: \ 00296 static KJS::Object self(KJS::ExecState *exec) \ 00297 { \ 00298 return cacheGlobalObject<ClassProto>( exec, "[[" ClassName ".prototype]]" ); \ 00299 } \ 00300 protected: \ 00301 ClassProto( KJS::ExecState *exec ) \ 00302 : KJS::ObjectImp( exec->interpreter()->builtinObjectPrototype() ) {} \ 00303 \ 00304 public: \ 00305 virtual const KJS::ClassInfo *classInfo() const { return &info; } \ 00306 static const KJS::ClassInfo info; \ 00307 KJS::Value get(KJS::ExecState *exec, const KJS::Identifier &propertyName) const; \ 00308 bool hasProperty(KJS::ExecState *exec, const KJS::Identifier &propertyName) const; \ 00309 }; \ 00310 const KJS::ClassInfo ClassProto::info = { ClassName, 0, &ClassProto##Table, 0 }; \ 00311 } 00312 00313 #define IMPLEMENT_PROTOTYPE(ClassProto,ClassFunc) \ 00314 KJS::Value KJS::ClassProto::get(KJS::ExecState *exec, const KJS::Identifier &propertyName) const \ 00315 { \ 00316 /*fprintf( stderr, "%sProto::get(%s) [in macro, no parent]\n", info.className, propertyName.ascii());*/ \ 00317 return lookupGetFunction<ClassFunc,KJS::ObjectImp>(exec, propertyName, &ClassProto##Table, this ); \ 00318 } \ 00319 bool KJS::ClassProto::hasProperty(KJS::ExecState *exec, const KJS::Identifier &propertyName) const \ 00320 { /*stupid but we need this to have a common macro for the declaration*/ \ 00321 return KJS::ObjectImp::hasProperty(exec, propertyName); \ 00322 } 00323 00324 #define IMPLEMENT_PROTOTYPE_WITH_PARENT(ClassProto,ClassFunc,ParentProto) \ 00325 KJS::Value KJS::ClassProto::get(KJS::ExecState *exec, const KJS::Identifier &propertyName) const \ 00326 { \ 00327 /*fprintf( stderr, "%sProto::get(%s) [in macro]\n", info.className, propertyName.ascii());*/ \ 00328 KJS::Value val = lookupGetFunction<ClassFunc,KJS::ObjectImp>(exec, propertyName, &ClassProto##Table, this ); \ 00329 if ( val.type() != UndefinedType ) return val; \ 00330 /* Not found -> forward request to "parent" prototype */ \ 00331 return ParentProto::self(exec).get( exec, propertyName ); \ 00332 } \ 00333 bool KJS::ClassProto::hasProperty(KJS::ExecState *exec, const KJS::Identifier &propertyName) const \ 00334 { \ 00335 if (KJS::ObjectImp::hasProperty(exec, propertyName)) \ 00336 return true; \ 00337 return ParentProto::self(exec).hasProperty(exec, propertyName); \ 00338 } 00339 00340 #define IMPLEMENT_PROTOFUNC(ClassFunc) \ 00341 namespace KJS { \ 00342 class ClassFunc : public ObjectImp { \ 00343 public: \ 00344 ClassFunc(KJS::ExecState *exec, int i, int len) \ 00345 : ObjectImp( /*proto? */ ), id(i) { \ 00346 KJS::Value protect(this); \ 00347 put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum); \ 00348 } \ 00349 virtual bool implementsCall() const { return true; } \ 00350 \ 00351 virtual KJS::Value call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args); \ 00352 private: \ 00353 int id; \ 00354 }; \ 00355 } 00356 00357 // To be used in all call() implementations, before casting the type of thisObj 00358 #define KJS_CHECK_THIS( ClassName, theObj ) \ 00359 if (!theObj.isValid() || !theObj.inherits(&ClassName::info)) { \ 00360 KJS::UString errMsg = "Attempt at calling a function that expects a "; \ 00361 errMsg += ClassName::info.className; \ 00362 errMsg += " on a "; \ 00363 errMsg += thisObj.className(); \ 00364 KJS::Object err = KJS::Error::create(exec, KJS::TypeError, errMsg.ascii()); \ 00365 exec->setException(err); \ 00366 return err; \ 00367 } 00368 00369 /* 00370 * List of things to do when porting an objectimp to the 'static hashtable' mechanism: 00371 * - write the hashtable source, between @begin and @end 00372 * - add a rule to build the .lut.h 00373 * - include the .lut.h 00374 * - mention the table in the classinfo (add a classinfo if necessary) 00375 * - write/update the class enum (for the tokens) 00376 * - turn get() into getValueProperty(), put() into putValueProperty(), using a switch and removing funcs 00377 * - write get() and/or put() using a template method 00378 * - cleanup old stuff (e.g. hasProperty) 00379 * - compile, test, commit ;) 00380 */ 00381 } // namespace 00382 00383 #endif
KDE Logo
This file is part of the documentation for kjs Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 16 17:22:14 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003