# kjs Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | 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  *  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 KJS_EXPORT 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

This file is part of the documentation for kjs Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:23:06 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003