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