| # kjs Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# 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

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