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 2002/10/24 17:03:16 faure Exp $
00021  */
00022 
00023 #ifndef _KJSLOOKUP_H_
00024 #define _KJSLOOKUP_H_
00025 
00026 #include "ustring.h"
00027 #include "value.h"
00028 #include <stdio.h>
00029 
00030 namespace KJS {
00031 
00035   struct HashEntry {
00039     const char *s;
00043     int value;
00047     short int attr;
00052     short int params;
00056     const HashEntry *next;
00057   };
00058 
00070   struct HashTable {
00074     int type;
00080     int size;
00085     const HashEntry *entries;
00089     int hashSize;
00090   };
00091 
00095   class Lookup {
00096   public:
00100     static int find(const struct HashTable *table, const UString &s);
00101     static int find(const struct HashTable *table,
00102             const UChar *c, unsigned int len);
00103 
00109     static const HashEntry* findEntry(const struct HashTable *table,
00110                                       const UString &s);
00111     static const HashEntry* findEntry(const struct HashTable *table,
00112                                       const UChar *c, unsigned int len);
00113 
00117     static unsigned int hash(const UString &key);
00118     static unsigned int hash(const UChar *c, unsigned int len);
00119     static unsigned int hash(const char *s);
00120   };
00121 
00122   class ExecState;
00123   class UString;
00128   template <class FuncImp>
00129   inline Value lookupOrCreateFunction(ExecState *exec, const UString &propertyName,
00130                                       const ObjectImp *thisObj, int token, int params, int attr)
00131   {
00132       // Look for cached value in dynamic map of properties (in ObjectImp)
00133       ValueImp * cachedVal = thisObj->ObjectImp::getDirect(propertyName);
00134       /*if (cachedVal)
00135         fprintf(stderr, "lookupOrCreateFunction: Function -> looked up in ObjectImp, found type=%d\n", cachedVal->type());*/
00136       if (cachedVal)
00137         return Value(cachedVal);
00138 
00139       Value val = Value(new FuncImp(exec,token, params));
00140       ObjectImp *thatObj = const_cast<ObjectImp *>(thisObj);
00141       thatObj->ObjectImp::put(exec, propertyName, val, attr);
00142       return val;
00143   }
00144 
00165   template <class FuncImp, class ThisImp, class ParentImp>
00166   inline Value lookupGet(ExecState *exec, const UString &propertyName,
00167                          const HashTable* table, const ThisImp* thisObj)
00168   {
00169     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00170 
00171     if (!entry) // not found, forward to parent
00172       return thisObj->ParentImp::get(exec, propertyName);
00173 
00174     //fprintf(stderr, "lookupGet: found value=%d attr=%d\n", entry->value, entry->attr);
00175     if (entry->attr & Function)
00176       return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
00177     return thisObj->getValueProperty(exec, entry->value);
00178   }
00179 
00184   template <class FuncImp, class ParentImp>
00185   inline Value lookupGetFunction(ExecState *exec, const UString &propertyName,
00186                          const HashTable* table, const ObjectImp* thisObj)
00187   {
00188     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00189 
00190     if (!entry) // not found, forward to parent
00191       return static_cast<const ParentImp *>(thisObj)->ParentImp::get(exec, propertyName);
00192 
00193     if (entry->attr & Function)
00194       return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
00195 
00196     fprintf(stderr, "Function bit not set! Shouldn't happen in lookupGetFunction!\n" );
00197     return Undefined();
00198   }
00199 
00204   template <class ThisImp, class ParentImp>
00205   inline Value lookupGetValue(ExecState *exec, const UString &propertyName,
00206                            const HashTable* table, const ThisImp* thisObj)
00207   {
00208     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00209 
00210     if (!entry) // not found, forward to parent
00211       return thisObj->ParentImp::get(exec, propertyName);
00212 
00213     if (entry->attr & Function)
00214       fprintf(stderr, "Function bit set! Shouldn't happen in lookupGetValue! propertyName was %s\n", propertyName.ascii() );
00215     return thisObj->getValueProperty(exec, entry->value);
00216   }
00217 
00222   template <class ThisImp, class ParentImp>
00223   inline void lookupPut(ExecState *exec, const UString &propertyName,
00224                         const Value& value, int attr,
00225                         const HashTable* table, ThisImp* thisObj)
00226   {
00227     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00228 
00229     if (!entry) // not found: forward to parent
00230       thisObj->ParentImp::put(exec, propertyName, value, attr);
00231     else if (entry->attr & Function) // function: put as override property
00232       thisObj->ObjectImp::put(exec, propertyName, value, attr);
00233     else if (entry->attr & ReadOnly) // readonly! Can't put!
00234 #ifdef KJS_VERBOSE
00235       fprintf(stderr,"WARNING: Attempt to change value of readonly property '%s'\n",propertyName.ascii());
00236 #else
00237       ; // do nothing
00238 #endif
00239     else
00240       thisObj->putValueProperty(exec, entry->value, value, attr);
00241   }
00242 
00243 
00251   template <class ClassCtor>
00252   inline KJS::Object cacheGlobalObject(ExecState *exec, const UString &propertyName)
00253   {
00254     ValueImp *obj = static_cast<KJS::ObjectImp*>(exec->interpreter()->globalObject().imp())->getDirect(propertyName);
00255     if (obj)
00256       return KJS::Object::dynamicCast(Value(obj));
00257     else
00258     {
00259       KJS::Object newObject(new ClassCtor(exec));
00260       exec->interpreter()->globalObject().put(exec, propertyName, newObject, Internal);
00261       return newObject;
00262     }
00263   }
00264 
00265 
00282 #define DEFINE_PROTOTYPE(ClassName,ClassProto) \
00283   namespace KJS { \
00284   class ClassProto : public KJS::ObjectImp { \
00285     friend KJS::Object cacheGlobalObject<ClassProto>(KJS::ExecState *exec, const KJS::UString &propertyName); \
00286   public: \
00287     static KJS::Object self(KJS::ExecState *exec) \
00288     { \
00289       return cacheGlobalObject<ClassProto>( exec, "[[" ClassName ".prototype]]" ); \
00290     } \
00291   protected: \
00292     ClassProto( KJS::ExecState *exec ) \
00293       : KJS::ObjectImp( exec->interpreter()->builtinObjectPrototype() ) {} \
00294     \
00295   public: \
00296     virtual const KJS::ClassInfo *classInfo() const { return &info; } \
00297     static const KJS::ClassInfo info; \
00298     KJS::Value get(KJS::ExecState *exec, const KJS::UString &propertyName) const; \
00299     bool hasProperty(KJS::ExecState *exec, const KJS::UString &propertyName) const; \
00300   }; \
00301   const KJS::ClassInfo ClassProto::info = { ClassName, 0, &ClassProto##Table, 0 }; \
00302   };
00303 
00304 #define IMPLEMENT_PROTOTYPE(ClassProto,ClassFunc) \
00305     KJS::Value KJS::ClassProto::get(KJS::ExecState *exec, const KJS::UString &propertyName) const \
00306     { \
00307       /*fprintf( stderr, "%sProto::get(%s) [in macro, no parent]\n", info.className, propertyName.ascii());*/ \
00308       return lookupGetFunction<ClassFunc,KJS::ObjectImp>(exec, propertyName, &ClassProto##Table, this ); \
00309     } \
00310     bool KJS::ClassProto::hasProperty(KJS::ExecState *exec, const KJS::UString &propertyName) const \
00311     { /*stupid but we need this to have a common macro for the declaration*/ \
00312       return KJS::ObjectImp::hasProperty(exec, propertyName); \
00313     }
00314 
00315 #define IMPLEMENT_PROTOTYPE_WITH_PARENT(ClassProto,ClassFunc,ParentProto)  \
00316     KJS::Value KJS::ClassProto::get(KJS::ExecState *exec, const KJS::UString &propertyName) const \
00317     { \
00318       /*fprintf( stderr, "%sProto::get(%s) [in macro]\n", info.className, propertyName.ascii());*/ \
00319       KJS::Value val = lookupGetFunction<ClassFunc,KJS::ObjectImp>(exec, propertyName, &ClassProto##Table, this ); \
00320       if ( val.type() != UndefinedType ) return val; \
00321       /* Not found -> forward request to "parent" prototype */ \
00322       return ParentProto::self(exec).get( exec, propertyName ); \
00323     } \
00324     bool KJS::ClassProto::hasProperty(KJS::ExecState *exec, const KJS::UString &propertyName) const \
00325     { \
00326       if (KJS::ObjectImp::hasProperty(exec, propertyName)) \
00327         return true; \
00328       return ParentProto::self(exec).hasProperty(exec, propertyName); \
00329     }
00330 
00331 #define IMPLEMENT_PROTOFUNC(ClassFunc) \
00332   namespace KJS { \
00333   class ClassFunc : public ObjectImp { \
00334   public: \
00335     ClassFunc(KJS::ExecState *exec, int i, int len) \
00336        : ObjectImp( /*proto? */ ), id(i) { \
00337        KJS::Value protect(this); \
00338        put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum); \
00339     } \
00340     virtual bool implementsCall() const { return true; } \
00341  \
00342     virtual KJS::Value call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args); \
00343   private: \
00344     int id; \
00345   }; \
00346   };
00347 
00348   // To be used in all call() implementations, before casting the type of thisObj
00349 #define KJS_CHECK_THIS( ClassName, theObj ) \
00350   if (theObj.isNull() || !theObj.inherits(&ClassName::info)) { \
00351     KJS::UString errMsg = "Attempt at calling a function that expects a "; \
00352     errMsg += ClassName::info.className; \
00353     errMsg += " on a "; \
00354     errMsg += thisObj.className(); \
00355     KJS::Object err = KJS::Error::create(exec, KJS::TypeError, errMsg.ascii()); \
00356     exec->setException(err); \
00357     return err; \
00358   }
00359 
00360   /*
00361    * List of things to do when porting an objectimp to the 'static hashtable' mechanism:
00362    * - write the hashtable source, between @begin and @end
00363    * - add a rule to build the .lut.h
00364    * - include the .lut.h
00365    * - mention the table in the classinfo (add a classinfo if necessary)
00366    * - write/update the class enum (for the tokens)
00367    * - turn get() into getValueProperty(), put() into putValueProperty(), using a switch and removing funcs
00368    * - write get() and/or put() using a template method
00369    * - cleanup old stuff (e.g. hasProperty)
00370    * - compile, test, commit ;)
00371    */
00372 }; // namespace
00373 
00374 #endif
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:21:15 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001