include/keima.h
author David Anderson <dvander@alliedmods.net>
Sun Jul 08 17:57:44 2012 -0700 (2012-07-08)
changeset 64 11c81eb30246
parent 62 e04c5be84792
child 65 7c942b5adebc
permissions -rw-r--r--
Added API for looking at module public functions.
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@60
    21
#include <stddef.h>
dvander@64
    22
#include "../include/keima_util.h"
dvander@60
    23
dvander@60
    24
namespace ke {
dvander@60
    25
dvander@60
    26
class Zone;
dvander@60
    27
class Object;
dvander@60
    28
class HandleScope;
dvander@60
    29
class HeapRoot;
dvander@60
    30
dvander@60
    31
}
dvander@60
    32
dvander@60
    33
namespace Ke {
dvander@60
    34
dvander@64
    35
class Function;
dvander@64
    36
dvander@60
    37
/*
dvander@60
    38
 * A Handle is a safe pointer that holds an object reference, such that it
dvander@60
    39
 * can be scanned and potentially moved by the garbage collector.
dvander@60
    40
 */
dvander@60
    41
template <typename T>
dvander@60
    42
class Handle
dvander@60
    43
{
dvander@60
    44
  protected:
dvander@60
    45
    template <typename S> void typeCheck() {
dvander@60
    46
        while (false) {
dvander@60
    47
            T *v1 = NULL;
dvander@60
    48
            S *v2 = NULL;
dvander@60
    49
            v1 = v2;
dvander@60
    50
            (void)v1;
dvander@60
    51
        }
dvander@60
    52
    }
dvander@60
    53
dvander@60
    54
  public:
dvander@60
    55
    Handle()
dvander@60
    56
      : obj_(NULL)
dvander@60
    57
    {
dvander@60
    58
    }
dvander@60
    59
dvander@60
    60
    template <typename S> Handle(Handle<S> other)
dvander@60
    61
      : obj_(reinterpret_cast<S *>(*other))
dvander@60
    62
    {
dvander@60
    63
        typeCheck<S>();
dvander@60
    64
    }
dvander@60
    65
 
dvander@60
    66
    explicit Handle(T *obj)
dvander@60
    67
      : obj_(obj)
dvander@60
    68
    {
dvander@60
    69
    }
dvander@60
    70
dvander@60
    71
    T *operator ->() const {
dvander@60
    72
        return obj_;
dvander@60
    73
    }
dvander@60
    74
    T *operator *() const {
dvander@60
    75
        return obj_;
dvander@60
    76
    }
dvander@60
    77
    operator bool () const {
dvander@60
    78
        return !!obj_;
dvander@60
    79
    }
dvander@60
    80
dvander@60
    81
  private:
dvander@60
    82
    T *obj_;
dvander@60
    83
};
dvander@60
    84
dvander@60
    85
/*
dvander@60
    86
 * A local variable that roots an object. Locals are owned by the nearest
dvander@60
    87
 * HandleScope, and as soon as that HandleScope dies, all its Locals are
dvander@60
    88
 * no longer available.
dvander@60
    89
 */
dvander@60
    90
template <typename T>
dvander@60
    91
class Local : public Handle<T>
dvander@60
    92
{
dvander@60
    93
  public:
dvander@60
    94
    Local()
dvander@60
    95
      : Handle<T>()
dvander@60
    96
    {
dvander@60
    97
    }
dvander@60
    98
dvander@60
    99
    template <typename S> Local(Local<S> other)
dvander@60
   100
      : Handle<T>(reinterpret_cast<T *>(*other))
dvander@60
   101
    {
dvander@60
   102
        typeCheck<S>();
dvander@60
   103
    }
dvander@60
   104
dvander@60
   105
    template <typename S> Local(S *other)
dvander@60
   106
      : Handle<T>(other)
dvander@60
   107
    {
dvander@60
   108
    }
dvander@60
   109
};
dvander@60
   110
dvander@60
   111
/*
dvander@60
   112
 * A non-local variable that outlives HandleScopes. A Root is reference-
dvander@60
   113
 * counted. When its reference count reaches 0, the Root is removed.
dvander@60
   114
 */
dvander@60
   115
template <typename T>
dvander@60
   116
class Root : public Handle<T>
dvander@60
   117
{
dvander@60
   118
  public:
dvander@60
   119
    Root()
dvander@60
   120
      : Handle<T>()
dvander@60
   121
    {
dvander@60
   122
    }
dvander@60
   123
dvander@60
   124
    template <typename S> Root(const Root<S> &other)
dvander@60
   125
      : Handle<T>(reinterpret_cast<T *>(*other))
dvander@60
   126
    {
dvander@60
   127
        typeCheck<S>();
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@60
   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@60
   143
    template <typename S>
dvander@60
   144
    Root<T> &operator =(Root<S> other) {
dvander@60
   145
        decref();
dvander@60
   146
        new (this) Root<T>(other);
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@64
   188
// A string is an immutable UTF8 buffer.
dvander@64
   189
class KE_EXPORT String
dvander@64
   190
{
dvander@64
   191
  public:
dvander@64
   192
    // Returns the length of the string, in bytes.
dvander@64
   193
    unsigned length();
dvander@64
   194
dvander@64
   195
    // Returns the character buffer of the string, or NULL on failure. If the
dvander@64
   196
    // string is interned, chars() is guaranteed to succeed.
dvander@64
   197
    const char *chars();
dvander@64
   198
};
dvander@64
   199
dvander@64
   200
// A function is an executable unit of code.
dvander@64
   201
class KE_EXPORT Function
dvander@64
   202
{
dvander@64
   203
  public:
dvander@64
   204
    // Returns the name of a function, which may be NULL. If not NULL, the
dvander@64
   205
    // string is guaranteed to be interned/
dvander@64
   206
    Local<String> name();
dvander@64
   207
};
dvander@64
   208
dvander@62
   209
// A module represents a single compiled file, and contains functions and
dvander@62
   210
// global variables for that file (as well as exported types).
dvander@64
   211
class KE_EXPORT Module
dvander@62
   212
{
dvander@62
   213
  public:
dvander@64
   214
    // Returns publics that are based on forwards.
dvander@64
   215
    unsigned numPublics();
dvander@64
   216
    Local<Function> getPublic(unsigned index);
dvander@62
   217
};
dvander@62
   218
dvander@62
   219
class Keima
dvander@62
   220
{
dvander@62
   221
  public:
dvander@62
   222
    /*
dvander@62
   223
     * Initializes the Keima engine. This must be called exactly once before any
dvander@62
   224
     * other Keima functions are called. After this, it is safe to use Keima
dvander@62
   225
     * on the calling thread.
dvander@62
   226
     */
dvander@62
   227
    static bool Initialize();
dvander@60
   228
dvander@62
   229
    /*
dvander@62
   230
     * Shuts down the Keima engine and frees data structures on all threads.
dvander@62
   231
     */
dvander@62
   232
    static void Shutdown();
dvander@60
   233
dvander@62
   234
    /*
dvander@62
   235
     * Searches the call stack and returns true if the given module has any
dvander@62
   236
     * active code running. This is an O(n) algorithm.
dvander@62
   237
     */
dvander@62
   238
    static bool IsInCallStack(Handle<Module> module);
dvander@62
   239
dvander@62
   240
    /*
dvander@62
   241
     * Reclaim as much memory as possible. This pauses the calling thread
dvander@62
   242
     * until garbage collection completes.
dvander@62
   243
     */
dvander@62
   244
    static void CollectGarbage();
dvander@64
   245
dvander@64
   246
    /*
dvander@64
   247
     * Clear any pending exception.
dvander@64
   248
     */
dvander@64
   249
    static void ClearPendingException();
dvander@62
   250
};
dvander@60
   251
dvander@60
   252
/*
dvander@64
   253
 * Suppresses exceptions. This is useful for calling API functions. When this
dvander@64
   254
 * in scope, errors will be reported, but the exception will be cleared after.
dvander@64
   255
 */
dvander@64
   256
class AutoClearExceptions
dvander@64
   257
{
dvander@64
   258
  public:
dvander@64
   259
    ~AutoClearExceptions()
dvander@64
   260
    {
dvander@64
   261
        Keima::ClearPendingException();
dvander@64
   262
    }
dvander@64
   263
};
dvander@64
   264
dvander@64
   265
dvander@64
   266
/*
dvander@60
   267
 * Compiles a file and returns a Module.
dvander@60
   268
 */
dvander@60
   269
extern Local<Module> Compile(const char *path);
dvander@60
   270
dvander@61
   271
class Internals
dvander@61
   272
{
dvander@61
   273
    template <typename T> friend class Root;
dvander@61
   274
dvander@61
   275
  private:
dvander@61
   276
    static ke::HeapRoot *NewHeapRoot(ke::Object **objp);
dvander@61
   277
    static void IncRef(ke::HeapRoot *root);
dvander@61
   278
    static void DecRef(ke::HeapRoot *root);
dvander@61
   279
};
dvander@61
   280
dvander@61
   281
template <typename T> Root<T>
dvander@61
   282
Root<T>::New(Handle<T> other)
dvander@61
   283
{
dvander@61
   284
    if (!other)
dvander@61
   285
        return Root<T>(NULL);
dvander@61
   286
    ke::Object **ptr = reinterpret_cast<ke::Object **>(*other);
dvander@61
   287
    return Root<T>(Internals::NewHeapRoot(ptr));
dvander@61
   288
}
dvander@61
   289
dvander@61
   290
template <typename T> void
dvander@61
   291
Root<T>::incref()
dvander@61
   292
{
dvander@61
   293
    if (!*this)
dvander@61
   294
        return;
dvander@61
   295
    ke::HeapRoot *ptr = reinterpret_cast<ke::HeapRoot *>(**this);
dvander@61
   296
    Internals::IncRef(ptr);
dvander@61
   297
}
dvander@61
   298
dvander@61
   299
template <typename T> void
dvander@61
   300
Root<T>::decref()
dvander@61
   301
{
dvander@61
   302
    if (!*this)
dvander@61
   303
        return;
dvander@61
   304
    ke::HeapRoot *ptr = reinterpret_cast<ke::HeapRoot *>(**this);
dvander@61
   305
    Internals::DecRef(ptr);
dvander@61
   306
}
dvander@61
   307
dvander@60
   308
}
dvander@60
   309
dvander@60
   310
#endif // _include_sourcepawn3_api_h_