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  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Lesser General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Lesser General Public
00017  *  License along with this library; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  *  $Id: lookup.h,v 1.28.2.3 2003/07/15 10:42:18 mueller Exp $
00021  */
00022 
00023 #ifndef _KJSLOOKUP_H_
00024 #define _KJSLOOKUP_H_
00025 
00026 #include "ustring.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     const char *s;
00045     int value;
00049     short int attr;
00054     short int params;
00058     const HashEntry *next;
00059   };
00060 
00072   struct HashTable {
00076     int type;
00082     int size;
00087     const HashEntry *entries;
00091     int hashSize;
00092   };
00093 
00097   class Lookup {
00098   public:
00102     static int find(const struct HashTable *table, const UString &s);
00103     static int find(const struct HashTable *table,
00104                     const UChar *c, unsigned int len);
00105 
00111     static const HashEntry* findEntry(const struct HashTable *table,
00112                                       const UString &s);
00113     static const HashEntry* findEntry(const struct HashTable *table,
00114                                       const UChar *c, unsigned int len);
00115 
00119     static unsigned int hash(const UString &key);
00120     static unsigned int hash(const UChar *c, unsigned int len);
00121     static unsigned int hash(const char *s);
00122   };
00123 
00124   class ExecState;
00125   class UString;
00130   template <class FuncImp>
00131   inline Value lookupOrCreateFunction(ExecState *exec, const UString &propertyName,
00132                                       const ObjectImp *thisObj, int token, int params, int attr)
00133   {
00134       // Look for cached value in dynamic map of properties (in ObjectImp)
00135       ValueImp * cachedVal = thisObj->ObjectImp::getDirect(propertyName);
00136       /*if (cachedVal)
00137         fprintf(stderr, "lookupOrCreateFunction: Function -> looked up in ObjectImp, found type=%d\n", cachedVal->type());*/
00138       if (cachedVal)
00139         return Value(cachedVal);
00140 
00141       Value val = Value(new FuncImp(exec,token, params));
00142       ObjectImp *thatObj = const_cast<ObjectImp *>(thisObj);
00143       thatObj->ObjectImp::put(exec, propertyName, val, attr);
00144       return val;
00145   }
00146 
00167   template <class FuncImp, class ThisImp, class ParentImp>
00168   inline Value lookupGet(ExecState *exec, const UString &propertyName,
00169                          const HashTable* table, const ThisImp* thisObj)
00170   {
00171     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00172 
00173     if (!entry) // not found, forward to parent
00174       return thisObj->ParentImp::get(exec, propertyName);
00175 
00176     //fprintf(stderr, "lookupGet: found value=%d attr=%d\n", entry->value, entry->attr);
00177     if (entry->attr & Function)
00178       return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
00179     return thisObj->getValueProperty(exec, entry->value);
00180   }
00181 
00186   template <class FuncImp, class ParentImp>
00187   inline Value lookupGetFunction(ExecState *exec, const UString &propertyName,
00188                          const HashTable* table, const ObjectImp* thisObj)
00189   {
00190     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00191 
00192     if (!entry) // not found, forward to parent
00193       return static_cast<const ParentImp *>(thisObj)->ParentImp::get(exec, propertyName);
00194 
00195     if (entry->attr & Function)
00196       return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
00197 
00198     fprintf(stderr, "Function bit not set! Shouldn't happen in lookupGetFunction!\n" );
00199     return Undefined();
00200   }
00201 
00206   template <class ThisImp, class ParentImp>
00207   inline Value lookupGetValue(ExecState *exec, const UString &propertyName,
00208                            const HashTable* table, const ThisImp* thisObj)
00209   {
00210     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00211 
00212     if (!entry) // not found, forward to parent
00213       return thisObj->ParentImp::get(exec, propertyName);
00214 
00215     if (entry->attr & Function)
00216       fprintf(stderr, "Function bit set! Shouldn't happen in lookupGetValue! propertyName was %s\n", propertyName.ascii() );
00217     return thisObj->getValueProperty(exec, entry->value);
00218   }
00219 
00224   template <class ThisImp, class ParentImp>
00225   inline void lookupPut(ExecState *exec, const UString &propertyName,
00226                         const Value& value, int attr,
00227                         const HashTable* table, ThisImp* thisObj)
00228   {
00229     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00230 
00231     if (!entry) // not found: forward to parent
00232       thisObj->ParentImp::put(exec, propertyName, value, attr);
00233     else if (entry->attr & Function) // function: put as override property
00234       thisObj->ObjectImp::put(exec, propertyName, value, attr);
00235     else if (entry->attr & ReadOnly) // readonly! Can't put!
00236 #ifdef KJS_VERBOSE
00237       fprintf(stderr,"WARNING: Attempt to change value of readonly property '%s'\n",propertyName.ascii());
00238 #else
00239       ; // do nothing
00240 #endif
00241     else
00242       thisObj->putValueProperty(exec, entry->value, value, attr);
00243   }
00244 
00245 
00253   template <class ClassCtor>
00254   inline KJS::Object cacheGlobalObject(ExecState *exec, const UString &propertyName)
00255   {
00256     ValueImp *obj = static_cast<KJS::ObjectImp*>(exec->interpreter()->globalObject().imp())->getDirect(propertyName);
00257     if (obj)
00258       return KJS::Object::dynamicCast(Value(obj));
00259     else
00260     {
00261       KJS::Object newObject(new ClassCtor(exec));
00262       exec->interpreter()->globalObject().put(exec, propertyName, newObject, Internal);
00263       return newObject;
00264     }
00265   }
00266 
00267 
00284 #define DEFINE_PROTOTYPE(ClassName,ClassProto) \
00285   namespace KJS { \
00286   class ClassProto : public KJS::ObjectImp { \
00287     friend KJS::Object cacheGlobalObject<ClassProto>(KJS::ExecState *exec, const KJS::UString &propertyName); \
00288   public: \
00289     static KJS::Object self(KJS::ExecState *exec) \
00290     { \
00291       return cacheGlobalObject<ClassProto>( exec, "[[" ClassName ".prototype]]" ); \
00292     } \
00293   protected: \
00294     ClassProto( KJS::ExecState *exec ) \
00295       : KJS::ObjectImp( exec->interpreter()->builtinObjectPrototype() ) {} \
00296     \
00297   public: \
00298     virtual const KJS::ClassInfo *classInfo() const { return &info; } \
00299     static const KJS::ClassInfo info; \
00300     KJS::Value get(KJS::ExecState *exec, const KJS::UString &propertyName) const; \
00301     bool hasProperty(KJS::ExecState *exec, const KJS::UString &propertyName) const; \
00302   }; \
00303   const KJS::ClassInfo ClassProto::info = { ClassName, 0, &ClassProto##Table, 0 }; \
00304   }
00305 
00306 #define IMPLEMENT_PROTOTYPE(ClassProto,ClassFunc) \
00307     KJS::Value KJS::ClassProto::get(KJS::ExecState *exec, const KJS::UString &propertyName) const \
00308     { \
00309       /*fprintf( stderr, "%sProto::get(%s) [in macro, no parent]\n", info.className, propertyName.ascii());*/ \
00310       return lookupGetFunction<ClassFunc,KJS::ObjectImp>(exec, propertyName, &ClassProto##Table, this ); \
00311     } \
00312     bool KJS::ClassProto::hasProperty(KJS::ExecState *exec, const KJS::UString &propertyName) const \
00313     { /*stupid but we need this to have a common macro for the declaration*/ \
00314       return KJS::ObjectImp::hasProperty(exec, propertyName); \
00315     }
00316 
00317 #define IMPLEMENT_PROTOTYPE_WITH_PARENT(ClassProto,ClassFunc,ParentProto)  \
00318     KJS::Value KJS::ClassProto::get(KJS::ExecState *exec, const KJS::UString &propertyName) const \
00319     { \
00320       /*fprintf( stderr, "%sProto::get(%s) [in macro]\n", info.className, propertyName.ascii());*/ \
00321       KJS::Value val = lookupGetFunction<ClassFunc,KJS::ObjectImp>(exec, propertyName, &ClassProto##Table, this ); \
00322       if ( val.type() != UndefinedType ) return val; \
00323       /* Not found -> forward request to "parent" prototype */ \
00324       return ParentProto::self(exec).get( exec, propertyName ); \
00325     } \
00326     bool KJS::ClassProto::hasProperty(KJS::ExecState *exec, const KJS::UString &propertyName) const \
00327     { \
00328       if (KJS::ObjectImp::hasProperty(exec, propertyName)) \
00329         return true; \
00330       return ParentProto::self(exec).hasProperty(exec, propertyName); \
00331     }
00332 
00333 #define IMPLEMENT_PROTOFUNC(ClassFunc) \
00334   namespace KJS { \
00335   class ClassFunc : public ObjectImp { \
00336   public: \
00337     ClassFunc(KJS::ExecState *exec, int i, int len) \
00338        : ObjectImp( /*proto? */ ), id(i) { \
00339        KJS::Value protect(this); \
00340        put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum); \
00341     } \
00342     virtual bool implementsCall() const { return true; } \
00343  \
00344     virtual KJS::Value call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args); \
00345   private: \
00346     int id; \
00347   }; \
00348   }
00349 
00350   // To be used in all call() implementations, before casting the type of thisObj
00351 #define KJS_CHECK_THIS( ClassName, theObj ) \
00352   if (theObj.isNull() || !theObj.inherits(&ClassName::info)) { \
00353     KJS::UString errMsg = "Attempt at calling a function that expects a "; \
00354     errMsg += ClassName::info.className; \
00355     errMsg += " on a "; \
00356     errMsg += thisObj.className(); \
00357     KJS::Object err = KJS::Error::create(exec, KJS::TypeError, errMsg.ascii()); \
00358     exec->setException(err); \
00359     return err; \
00360   }
00361 
00362   /*
00363    * List of things to do when porting an objectimp to the 'static hashtable' mechanism:
00364    * - write the hashtable source, between @begin and @end
00365    * - add a rule to build the .lut.h
00366    * - include the .lut.h
00367    * - mention the table in the classinfo (add a classinfo if necessary)
00368    * - write/update the class enum (for the tokens)
00369    * - turn get() into getValueProperty(), put() into putValueProperty(), using a switch and removing funcs
00370    * - write get() and/or put() using a template method
00371    * - cleanup old stuff (e.g. hasProperty)
00372    * - compile, test, commit ;)
00373    */
00374 } // namespace
00375 
00376 #endif
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:08:29 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001