include/keima.h
author David Anderson <dvander@alliedmods.net>
Tue Jul 10 02:11:13 2012 -0700 (2012-07-10)
changeset 68 b40b0e18a918
parent 65 7c942b5adebc
child 69 dfce0539a77d
permissions -rw-r--r--
Added support for ISourcePawnEngine natives.
     1 /*
     2  * Copyright (C) 2004-2012 David Anderson
     3  *
     4  * This file is part of SourcePawn.
     5  *
     6  * SourcePawn is free software: you can redistribute it and/or modify it under
     7  * the terms of the GNU General Public License as published by the Free
     8  * Software Foundation, either version 3 of the License, or (at your option)
     9  * any later version.
    10  * 
    11  * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along with
    16  * SourcePawn. If not, see http://www.gnu.org/licenses/.
    17  */
    18 #ifndef _include_sourcepawn3_api_h_
    19 #define _include_sourcepawn3_api_h_
    20 
    21 #include <assert.h>
    22 #include <stddef.h>
    23 #include "../include/keima_util.h"
    24 
    25 namespace ke {
    26 
    27 class Zone;
    28 class Object;
    29 class HandleScope;
    30 class HeapRoot;
    31 
    32 }
    33 
    34 namespace Ke {
    35 
    36 class Function;
    37 
    38 /*
    39  * A Handle is a safe pointer that holds an object reference, such that it
    40  * can be scanned and potentially moved by the garbage collector.
    41  */
    42 template <typename T>
    43 class Handle
    44 {
    45   protected:
    46     template <typename S> void typeCheck() {
    47         while (false) {
    48             T *v1 = NULL;
    49             S *v2 = NULL;
    50             v1 = v2;
    51             (void)v1;
    52         }
    53     }
    54 
    55   public:
    56     Handle()
    57       : obj_(NULL)
    58     {
    59     }
    60 
    61     template <typename S> Handle(Handle<S> other)
    62       : obj_(reinterpret_cast<S *>(*other))
    63     {
    64         typeCheck<S>();
    65     }
    66  
    67     explicit Handle(T *obj)
    68       : obj_(obj)
    69     {
    70     }
    71 
    72     T *operator ->() const {
    73         return obj_;
    74     }
    75     T *operator *() const {
    76         return obj_;
    77     }
    78     operator bool () const {
    79         return !!obj_;
    80     }
    81 
    82   protected:
    83     T *obj_;
    84 };
    85 
    86 /*
    87  * A local variable that roots an object. Locals are owned by the nearest
    88  * HandleScope, and as soon as that HandleScope dies, all its Locals are
    89  * no longer available.
    90  */
    91 template <typename T>
    92 class Local : public Handle<T>
    93 {
    94   public:
    95     Local()
    96       : Handle<T>()
    97     {
    98     }
    99 
   100     template <typename S> Local(Local<S> other)
   101       : Handle<T>(reinterpret_cast<T *>(*other))
   102     {
   103         typeCheck<S>();
   104     }
   105 
   106     template <typename S> Local(S *other)
   107       : Handle<T>(other)
   108     {
   109     }
   110 };
   111 
   112 /*
   113  * A non-local variable that outlives HandleScopes. A Root is reference-
   114  * counted. When its reference count reaches 0, the Root is removed.
   115  */
   116 template <typename T>
   117 class Root : public Handle<T>
   118 {
   119   public:
   120     Root<T>()
   121       : Handle<T>()
   122     {
   123     }
   124 
   125     Root<T>(const Root<T> &other)
   126       : Handle<T>(reinterpret_cast<T *>(*other))
   127     {
   128         incref();
   129     }
   130 
   131     explicit Root(ke::HeapRoot *obj)
   132       : Handle<T>(reinterpret_cast<T *>(obj))
   133     {
   134 		incref();
   135     }
   136 
   137     static inline Root<T> New(Handle<T> other);
   138 
   139     ~Root() {
   140         decref();
   141     }
   142 
   143     Root<T> &operator =(const Root<T> &other) {
   144         decref();
   145         obj_ = other.obj_;
   146 		incref();
   147         return *this;
   148     }
   149 
   150   private:
   151     void incref();
   152     void decref();
   153 };
   154 
   155 /*
   156  * A HandleScope is where Local roots are allcoated. When the HandleScope
   157  * is destroyed, all Handles created under it are also destroyed. HandleScopes
   158  * may only be allocated on the stack, in LIFO order.
   159  */
   160 class HandleScope
   161 {
   162   protected:
   163     ke::Zone *zone_;
   164     ke::Object **position_;
   165     HandleScope *prev_;
   166 
   167     HandleScope(ke::Zone *zone, ke::Object **position, HandleScope *prev)
   168       : zone_(zone),
   169         position_(position),
   170         prev_(prev)
   171     {
   172     }
   173 
   174   public:
   175     HandleScope();
   176     ~HandleScope();
   177 
   178     static ke::Object **CreateHandle(ke::Object *obj);
   179 
   180   private:
   181     // Disallow silly stuff.
   182     HandleScope(const HandleScope &);
   183     void operator =(const HandleScope &);
   184     void *operator new (size_t size);
   185     void operator delete(void *, size_t);
   186 };
   187 
   188 class Parameter;
   189 
   190 // A string is an immutable UTF8 buffer.
   191 class KE_EXPORT String
   192 {
   193   public:
   194     // Returns the length of the string, in bytes.
   195     unsigned length();
   196 
   197     // Returns the character buffer of the string, or NULL on failure. If the
   198     // string is interned, chars() is guaranteed to succeed.
   199     const char *chars();
   200 };
   201 
   202 // A function is an executable unit of code.
   203 class KE_EXPORT Function
   204 {
   205   public:
   206     // Returns the name of a function, which may be NULL. If not NULL, the
   207     // string is guaranteed to be interned.
   208     Local<String> name();
   209 };
   210 
   211 // A native is an ISourcePawnEngine-compatible function provided by C++.
   212 class KE_EXPORT Native
   213 {
   214   public:
   215     // Returns the name of a native, which is never NULL. The string is
   216     // guaranteed to be interned.
   217     Local<String> name();
   218 
   219     // Returns the function pointer of the native.
   220     void *function();
   221 
   222     // Sets the function pointer of the native.
   223     void bind(void *function);
   224 };
   225 
   226 // A module represents a single compiled file, and contains functions and
   227 // global variables for that file (as well as exported types).
   228 class KE_EXPORT Module
   229 {
   230   public:
   231     // Returns publics that are based on forwards.
   232     unsigned numPublics();
   233     Local<Function> getPublic(unsigned index);
   234 
   235     // Returns natives.
   236     unsigned numNatives();
   237     Local<Native> getNative(unsigned index);
   238 
   239     // Sets the native identity pointer, which is passed as the first argument
   240     // to natives.
   241     void setNativeIdentity(void *ptr);
   242 };
   243 
   244 class Keima
   245 {
   246   public:
   247     /*
   248      * Initializes the Keima engine. This must be called exactly once before any
   249      * other Keima functions are called. After this, it is safe to use Keima
   250      * on the calling thread.
   251      */
   252     static bool Initialize();
   253 
   254     /*
   255      * Shuts down the Keima engine and frees data structures on all threads.
   256      */
   257     static void Shutdown();
   258 
   259     /*
   260      * Searches the call stack and returns true if the given module has any
   261      * active code running. This is an O(n) algorithm.
   262      */
   263     static bool IsInCallStack(Handle<Module> module);
   264 
   265     /*
   266      * Reclaim as much memory as possible. This pauses the calling thread
   267      * until garbage collection completes.
   268      */
   269     static void CollectGarbage();
   270 
   271     /*
   272      * Clear any pending exception.
   273      */
   274     static void ClearPendingException();
   275 
   276     /*
   277      * Type checks a function against given parameters.
   278      */
   279     static bool CheckInvokeTypes(Handle<Function> fun, const Parameter *params, unsigned nparams);
   280 
   281     /*
   282      * Executes a function with the given parameters. This interface is
   283      * intended for compatibility with SourceMod's ISourcePawnEngine2 and
   284      * should not be used otherwise, since it is intended to support only
   285      * a small subset of the core language.
   286      */
   287     static bool Invoke(Handle<Function> fun, const Parameter *params, unsigned nparams, int *result);
   288 };
   289 
   290 /*
   291  * Suppresses exceptions. This is useful for calling API functions. When this
   292  * in scope, errors will be reported, but the exception will be cleared after.
   293  */
   294 class AutoClearExceptions
   295 {
   296   public:
   297     ~AutoClearExceptions()
   298     {
   299         Keima::ClearPendingException();
   300     }
   301 };
   302 
   303 // Argument-passing interface for Invoke().
   304 class Parameter
   305 {
   306   public:
   307     enum Type {
   308         Int,
   309         Float,
   310         IntRef,
   311         FloatRef,
   312         Array,
   313         CharArray
   314     };
   315 
   316     Parameter()
   317     {
   318     }
   319 
   320     Parameter(int i)
   321       : type_(Int)
   322     {
   323         u.i = i;
   324     }
   325 
   326     Parameter(int *i, bool writeback)
   327       : type_(IntRef),
   328         writeback_(writeback)
   329     {
   330         u.ip = i;
   331     }
   332 
   333     Parameter(float f)
   334       : type_(Float)
   335     {
   336         u.f = f;
   337     }
   338 
   339     Parameter(float *f, bool writeback)
   340       : type_(FloatRef),
   341         writeback_(writeback)
   342     {
   343         u.fp = f;
   344     }
   345 
   346     Parameter(Type type, void *buffer, size_t length, bool writeback)
   347       : type_(type),
   348         writeback_(writeback),
   349         length_(length)
   350     {
   351         assert(type == Array || type == CharArray);
   352         u.buffer = buffer;
   353     }
   354 
   355     Type type() const {
   356         return type_;
   357     }
   358 
   359     int i32() const {
   360         assert(type() == Int);
   361         return u.i;
   362     }
   363     float f() const {
   364         assert(type() == Float);
   365         return u.f;
   366     }
   367     int *i32p() const {
   368         assert(type() == IntRef);
   369         return u.ip;
   370     }
   371     float *fp() const {
   372         assert(type() == FloatRef);
   373         return u.fp;
   374     }
   375     bool writeback() const {
   376         assert(type() >= IntRef && type() <= CharArray);
   377         return writeback_;
   378     }
   379     size_t length() const {
   380         return length_;
   381     }
   382     void *buffer() const {
   383         assert(type() == Array || type() == CharArray);
   384         return u.buffer;
   385     }
   386 
   387   private:
   388     Type type_;
   389     bool writeback_;
   390     size_t length_;
   391 
   392     union {
   393         int i;
   394         float f;
   395         int *ip;
   396         float *fp;
   397         void *buffer;
   398     } u;
   399 };
   400 
   401 /*
   402  * Compiles a file and returns a Module.
   403  */
   404 extern Local<Module> Compile(const char *path);
   405 
   406 class Internals
   407 {
   408     template <typename T> friend class Root;
   409 
   410   private:
   411     static ke::HeapRoot *NewHeapRoot(ke::Object **objp);
   412     static void IncRef(ke::HeapRoot *root);
   413     static void DecRef(ke::HeapRoot *root);
   414 };
   415 
   416 template <typename T> Root<T>
   417 Root<T>::New(Handle<T> other)
   418 {
   419     if (!other)
   420         return Root<T>();
   421     ke::Object **ptr = reinterpret_cast<ke::Object **>(*other);
   422     return Root<T>(Internals::NewHeapRoot(ptr));
   423 }
   424 
   425 template <typename T> void
   426 Root<T>::incref()
   427 {
   428     if (!*this)
   429         return;
   430     ke::HeapRoot *ptr = reinterpret_cast<ke::HeapRoot *>(**this);
   431     Internals::IncRef(ptr);
   432 }
   433 
   434 template <typename T> void
   435 Root<T>::decref()
   436 {
   437     if (!*this)
   438         return;
   439     ke::HeapRoot *ptr = reinterpret_cast<ke::HeapRoot *>(**this);
   440     Internals::DecRef(ptr);
   441 }
   442 
   443 }
   444 
   445 #endif // _include_sourcepawn3_api_h_