include/keima.h
author David Anderson <dvander@alliedmods.net>
Tue Jan 01 20:06:25 2013 -0800 (2013-01-01)
changeset 253 544c478362c2
parent 251 ca99a81745fe
permissions -rw-r--r--
Add WIN32 define for MSVC builds.
danderson@91
     1
/* vim: set ts=4 sw=4 tw=99 et:
danderson@91
     2
 *
dvander@60
     3
 * Copyright (C) 2004-2012 David Anderson
dvander@60
     4
 *
dvander@60
     5
 * This file is part of SourcePawn.
dvander@60
     6
 *
dvander@60
     7
 * SourcePawn is free software: you can redistribute it and/or modify it under
dvander@60
     8
 * the terms of the GNU General Public License as published by the Free
dvander@60
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@60
    10
 * any later version.
dvander@60
    11
 * 
dvander@60
    12
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@60
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@60
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@60
    15
 *
dvander@60
    16
 * You should have received a copy of the GNU General Public License along with
dvander@60
    17
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
dvander@60
    18
 */
danderson@96
    19
#ifndef _include_sourcepawn2_api_h_
danderson@96
    20
#define _include_sourcepawn2_api_h_
dvander@60
    21
dvander@65
    22
#include <assert.h>
dvander@60
    23
#include <stddef.h>
dvander@64
    24
#include "../include/keima_util.h"
dvander@60
    25
dvander@60
    26
namespace ke {
dvander@60
    27
dvander@60
    28
class Zone;
dvander@60
    29
class Object;
dvander@60
    30
class HandleScope;
dvander@60
    31
class HeapRoot;
dvander@60
    32
dvander@60
    33
}
dvander@60
    34
dvander@60
    35
namespace Ke {
dvander@60
    36
dvander@64
    37
class Function;
dvander@251
    38
class Package;
dvander@64
    39
dvander@60
    40
/*
dvander@60
    41
 * A Handle is a safe pointer that holds an object reference, such that it
dvander@60
    42
 * can be scanned and potentially moved by the garbage collector.
dvander@60
    43
 */
dvander@60
    44
template <typename T>
dvander@60
    45
class Handle
dvander@60
    46
{
dvander@195
    47
    template <typename S> friend class Root;
dvander@60
    48
  protected:
dvander@60
    49
    template <typename S> void typeCheck() {
dvander@60
    50
        while (false) {
dvander@60
    51
            T *v1 = NULL;
dvander@60
    52
            S *v2 = NULL;
dvander@60
    53
            v1 = v2;
dvander@60
    54
            (void)v1;
dvander@60
    55
        }
dvander@60
    56
    }
dvander@60
    57
dvander@60
    58
  public:
dvander@60
    59
    Handle()
dvander@60
    60
      : obj_(NULL)
dvander@60
    61
    {
dvander@60
    62
    }
dvander@60
    63
dvander@60
    64
    template <typename S> Handle(Handle<S> other)
dvander@60
    65
      : obj_(reinterpret_cast<S *>(*other))
dvander@60
    66
    {
dvander@60
    67
        typeCheck<S>();
dvander@60
    68
    }
dvander@60
    69
 
dvander@60
    70
    explicit Handle(T *obj)
dvander@60
    71
      : obj_(obj)
dvander@60
    72
    {
dvander@60
    73
    }
dvander@60
    74
dvander@60
    75
    T *operator ->() const {
dvander@60
    76
        return obj_;
dvander@60
    77
    }
dvander@60
    78
    T *operator *() const {
dvander@60
    79
        return obj_;
dvander@60
    80
    }
dvander@60
    81
    operator bool () const {
dvander@60
    82
        return !!obj_;
dvander@60
    83
    }
dvander@60
    84
dvander@65
    85
  protected:
dvander@60
    86
    T *obj_;
dvander@60
    87
};
dvander@60
    88
dvander@60
    89
/*
dvander@60
    90
 * A local variable that roots an object. Locals are owned by the nearest
dvander@60
    91
 * HandleScope, and as soon as that HandleScope dies, all its Locals are
dvander@60
    92
 * no longer available.
dvander@60
    93
 */
dvander@60
    94
template <typename T>
dvander@60
    95
class Local : public Handle<T>
dvander@60
    96
{
dvander@60
    97
  public:
dvander@60
    98
    Local()
dvander@60
    99
      : Handle<T>()
dvander@60
   100
    {
dvander@60
   101
    }
dvander@60
   102
dvander@60
   103
    template <typename S> Local(Local<S> other)
dvander@60
   104
      : Handle<T>(reinterpret_cast<T *>(*other))
dvander@60
   105
    {
danderson@91
   106
        this->template typeCheck<S>();
dvander@60
   107
    }
dvander@60
   108
dvander@60
   109
    template <typename S> Local(S *other)
dvander@60
   110
      : Handle<T>(other)
dvander@60
   111
    {
dvander@60
   112
    }
dvander@60
   113
};
dvander@60
   114
dvander@60
   115
/*
dvander@195
   116
 * A non-local variable that outlives HandleScopes. Unlike Local, a Root
dvander@195
   117
 * actually represents a rooted location. Roots must be allocated and
dvander@195
   118
 * disposed, and assignment to a root changes its contained object, not
dvander@195
   119
 * the location of the object.
dvander@60
   120
 */
dvander@60
   121
template <typename T>
dvander@195
   122
class Root
dvander@60
   123
{
dvander@60
   124
  public:
dvander@195
   125
    Root()
dvander@195
   126
      : root_(NULL)
dvander@60
   127
    {
dvander@60
   128
    }
dvander@60
   129
dvander@195
   130
    Root(Handle<T> other)
dvander@195
   131
      : root_(NULL)
dvander@60
   132
    {
dvander@195
   133
        set(other);
dvander@60
   134
    }
dvander@60
   135
dvander@195
   136
    inline ~Root();
dvander@195
   137
dvander@195
   138
    operator const Handle<T>() const {
dvander@195
   139
        return obj_;
dvander@60
   140
    }
dvander@60
   141
dvander@195
   142
    bool operator ==(Handle<T> other) {
dvander@195
   143
        return Handle<T>(*this) == other;
dvander@60
   144
    }
dvander@195
   145
    Root<T> &operator =(Handle<T> other) {
dvander@195
   146
        set(other);
dvander@60
   147
        return *this;
dvander@60
   148
    }
dvander@60
   149
dvander@60
   150
  private:
dvander@195
   151
    void set(Handle<T> other);
dvander@195
   152
dvander@195
   153
    ke::HeapRoot *root_;
dvander@195
   154
    Handle<T> obj_;
dvander@60
   155
};
dvander@60
   156
dvander@60
   157
/*
dvander@60
   158
 * A HandleScope is where Local roots are allcoated. When the HandleScope
dvander@60
   159
 * is destroyed, all Handles created under it are also destroyed. HandleScopes
dvander@60
   160
 * may only be allocated on the stack, in LIFO order.
dvander@60
   161
 */
dvander@60
   162
class HandleScope
dvander@60
   163
{
dvander@60
   164
  protected:
dvander@60
   165
    ke::Zone *zone_;
dvander@60
   166
    ke::Object **position_;
dvander@60
   167
    HandleScope *prev_;
dvander@60
   168
dvander@60
   169
    HandleScope(ke::Zone *zone, ke::Object **position, HandleScope *prev)
dvander@60
   170
      : zone_(zone),
dvander@60
   171
        position_(position),
dvander@60
   172
        prev_(prev)
dvander@60
   173
    {
dvander@60
   174
    }
dvander@60
   175
dvander@60
   176
  public:
dvander@60
   177
    HandleScope();
dvander@60
   178
    ~HandleScope();
dvander@60
   179
dvander@60
   180
    static ke::Object **CreateHandle(ke::Object *obj);
dvander@60
   181
dvander@60
   182
  private:
dvander@60
   183
    // Disallow silly stuff.
dvander@60
   184
    HandleScope(const HandleScope &);
dvander@60
   185
    void operator =(const HandleScope &);
dvander@60
   186
    void *operator new (size_t size);
dvander@60
   187
    void operator delete(void *, size_t);
dvander@60
   188
};
dvander@60
   189
dvander@65
   190
class Parameter;
dvander@65
   191
dvander@69
   192
// Error messages are pumped through this interface.
dvander@69
   193
class IMessageReporter
dvander@69
   194
{
dvander@69
   195
  public:
dvander@69
   196
    virtual void onOutOfMemory() {
dvander@69
   197
    }
dvander@69
   198
    virtual void onUncaughtException(const char *message) {
dvander@69
   199
    }
dvander@69
   200
    virtual void beginCompilationErrors(const char *file) {
dvander@69
   201
    }
dvander@69
   202
    virtual void reportCompilationError(const char *message, unsigned line, unsigned col) {
dvander@69
   203
    }
dvander@69
   204
    virtual void endCompilationErrors() {
dvander@69
   205
    }
dvander@69
   206
};
dvander@69
   207
dvander@69
   208
// For the purposes of error reporting, very basic information can be queried
dvander@69
   209
// about the stack frame. This structure may be used to retrieve such
dvander@69
   210
// information. During iteration, it is illegal to re-enter any scripted code
dvander@69
   211
// or call any Keima functions that may cause garbage collection.
dvander@69
   212
class IStackFrameIterator
dvander@69
   213
{
dvander@69
   214
  public:
dvander@195
   215
    virtual ~IStackFrameIterator() {
dvander@195
   216
    }
dvander@69
   217
dvander@69
   218
    // Returns true if there are more frames, false otherwise.
dvander@69
   219
    virtual bool done() = 0;
dvander@69
   220
dvander@69
   221
    // Returns the name of the current function. This may be NULL if the
dvander@69
   222
    // function is anonymous.
dvander@69
   223
    virtual const char *function() = 0;
dvander@69
   224
dvander@69
   225
    // Returns the file of the current function. This will return an invalid
dvander@69
   226
    // path for C++ functions (for example, "<native>").
dvander@69
   227
    virtual const char *source() = 0;
dvander@69
   228
dvander@69
   229
    // Returns the line number currently executing on this frame. For C++
dvander@69
   230
    // functions, this is always 0.
dvander@69
   231
    virtual unsigned lineNumber() = 0;
dvander@69
   232
dvander@69
   233
    // Advance to the previous frame in the call stack.
dvander@69
   234
    virtual void prev() = 0;
dvander@69
   235
};
dvander@69
   236
dvander@195
   237
// Listener interface for when public functions are registered or unregisted.
dvander@195
   238
class IPublicFunctionListener
dvander@195
   239
{
dvander@195
   240
  public:
dvander@195
   241
    virtual ~IPublicFunctionListener() {
dvander@195
   242
    }
dvander@195
   243
dvander@195
   244
    // Called when a public function becomes available to the runtime.
dvander@195
   245
    virtual void registerPublic(Handle<Function> fun) = 0;
dvander@195
   246
dvander@195
   247
    // Called when a public is no longer available to the runtime.
dvander@195
   248
    virtual void unregisterPublic(Handle<Function> fun) = 0;
dvander@195
   249
};
dvander@195
   250
dvander@64
   251
// A string is an immutable UTF8 buffer.
dvander@64
   252
class KE_EXPORT String
dvander@64
   253
{
dvander@64
   254
  public:
dvander@251
   255
    static Local<String> NewAscii(const char *str);
dvander@251
   256
dvander@64
   257
    // Returns the length of the string, in bytes.
dvander@64
   258
    unsigned length();
dvander@64
   259
dvander@64
   260
    // Returns the character buffer of the string, or NULL on failure. If the
dvander@64
   261
    // string is interned, chars() is guaranteed to succeed.
dvander@64
   262
    const char *chars();
dvander@64
   263
};
dvander@64
   264
dvander@64
   265
// A function is an executable unit of code.
dvander@64
   266
class KE_EXPORT Function
dvander@64
   267
{
dvander@64
   268
  public:
dvander@64
   269
    // Returns the name of a function, which may be NULL. If not NULL, the
dvander@68
   270
    // string is guaranteed to be interned.
dvander@64
   271
    Local<String> name();
dvander@251
   272
dvander@251
   273
    // Returns the package the function was created in.
dvander@251
   274
    Local<Package> package();
dvander@64
   275
};
dvander@64
   276
dvander@170
   277
// A pubvar is an ISourcePawnEngine-compatible structure that holds information
dvander@170
   278
// about public variables.
dvander@170
   279
class KE_EXPORT Pubvar
dvander@170
   280
{
dvander@170
   281
  public:
dvander@170
   282
    // Returns the name of a pubvar, which is never NULL. The string is
dvander@170
   283
    // guaranteed to be interned.
dvander@170
   284
    Local<String> name();
dvander@170
   285
};
dvander@170
   286
dvander@251
   287
// A package is a collection of compiled files and possibly sub-packages.
dvander@251
   288
// Internally, packages are used to implement the "import" statement. However,
dvander@251
   289
// the host application can also create packages to organize related files,
dvander@251
   290
// restrict import visibility, or implement hot swapping of loaded modules.
dvander@251
   291
class KE_EXPORT Package
dvander@62
   292
{
dvander@62
   293
  public:
dvander@251
   294
    enum {
dvander@251
   295
        Normal = 0,
dvander@251
   296
dvander@251
   297
        // The package cannot be accessed from any import statement.
dvander@251
   298
        Hidden = (1 << 0),
dvander@251
   299
dvander@251
   300
        // Source files compiled in this package cannot import names in the
dvander@251
   301
        // package.
dvander@251
   302
        Jailed = (1 << 1)
dvander@251
   303
    };
dvander@251
   304
dvander@251
   305
    // Creates a package. The parent package may be NULL. The name can be NULL
dvander@251
   306
    // as well. |path| must be a filesystem path, which will be normalized 
dvander@251
   307
    // according to OS-specific rules.
dvander@251
   308
    static Local<Package> New(Handle<Package> parent,
dvander@251
   309
                              Handle<String> name,
dvander@251
   310
                              const char *path,
dvander@251
   311
                              unsigned flags);
dvander@251
   312
dvander@251
   313
    // Returns the name of the package, which may be NULL. The string is
dvander@251
   314
    // guaranteed to be interned.
dvander@251
   315
    Local<String> name();
dvander@251
   316
dvander@251
   317
    // Returns the full path of the package. The string is guaranteed to be
dvander@251
   318
    // interned.
dvander@251
   319
    Local<String> path();
dvander@251
   320
dvander@251
   321
    // Sets the package's native identity. This is a host-application defined
dvander@251
   322
    // value that is passed to native callbacks.  Packages created under this
dvander@251
   323
    // one will automatically inherit this native identity.
dvander@251
   324
    void setNativeIdentity(void *identity);
dvander@251
   325
dvander@251
   326
    // Returns the package's native identity, or NULL if none was set.
dvander@251
   327
    void *getNativeIdentity();
dvander@62
   328
};
dvander@62
   329
dvander@62
   330
class Keima
dvander@62
   331
{
dvander@62
   332
  public:
dvander@62
   333
    /*
dvander@62
   334
     * Initializes the Keima engine. This must be called exactly once before any
dvander@62
   335
     * other Keima functions are called. After this, it is safe to use Keima
dvander@251
   336
     * on the calling thread only. It is not safe to race on calling this.
dvander@62
   337
     */
dvander@62
   338
    static bool Initialize();
dvander@60
   339
dvander@62
   340
    /*
dvander@62
   341
     * Shuts down the Keima engine and frees data structures on all threads.
dvander@62
   342
     */
dvander@62
   343
    static void Shutdown();
dvander@60
   344
dvander@62
   345
    /*
dvander@251
   346
     * Searches the call stack and returns true if the given package has any
dvander@62
   347
     * active code running. This is an O(n) algorithm.
dvander@62
   348
     */
dvander@251
   349
    static bool IsInCallStack(Handle<Package> package);
dvander@62
   350
dvander@62
   351
    /*
dvander@62
   352
     * Reclaim as much memory as possible. This pauses the calling thread
dvander@62
   353
     * until garbage collection completes.
dvander@62
   354
     */
dvander@62
   355
    static void CollectGarbage();
dvander@64
   356
dvander@64
   357
    /*
dvander@64
   358
     * Clear any pending exception.
dvander@64
   359
     */
dvander@64
   360
    static void ClearPendingException();
dvander@65
   361
dvander@65
   362
    /*
dvander@65
   363
     * Executes a function with the given parameters. This interface is
dvander@65
   364
     * intended for compatibility with SourceMod's ISourcePawnEngine2 and
dvander@65
   365
     * should not be used otherwise, since it is intended to support only
dvander@65
   366
     * a small subset of the core language.
dvander@65
   367
     */
dvander@129
   368
    static bool Invoke(Handle<Function> fun, const Parameter *params, unsigned nparams,
dvander@129
   369
                       bool checkTypes, int *result);
dvander@69
   370
dvander@69
   371
    /*
dvander@69
   372
     * Sets the global message handler through which errors will be reported
dvander@69
   373
     */
dvander@69
   374
    static void InstallMessageReporter(IMessageReporter *reporter);
dvander@69
   375
dvander@195
   376
    /* Returns a new stack frame iterator object. */
dvander@69
   377
    static IStackFrameIterator *NewStackFrameIterator();
dvander@195
   378
dvander@195
   379
    /*
dvander@195
   380
     * Binds a native, by name, to an address. Natives are an ISPE1 concept
dvander@195
   381
     * (originally from Pawn/Small's AMX API). In SourceMod 1, natives were
dvander@195
   382
     * registered globally, but bound to plugins individually. We roughly
dvander@195
   383
     * preserve that functionality here, by allowing host applications to
dvander@195
   384
     * give us the name -> address mappings.
dvander@195
   385
     *
dvander@195
   386
     * Natives can be rebound or unbound any number of times. This function
dvander@195
   387
     * fails if there is not enough memory.
dvander@195
   388
     */
dvander@195
   389
    static bool BindNative(const char *name, void *address);
dvander@195
   390
dvander@195
   391
    /* Sets the object that will listen for public functions. */
dvander@195
   392
    static void SetPublicFunctionListener(IPublicFunctionListener *listener);
dvander@251
   393
dvander@251
   394
    /*
dvander@251
   395
     * Installs a system root folder. When an attempt to import locally fails,
dvander@251
   396
     * the list of system roots are searched in the order they were installed.
dvander@251
   397
     *
dvander@251
   398
     * The given path must be absolute. It may contain a trailing slash.
dvander@251
   399
     *
dvander@251
   400
     * The name is an arbitrary, optional identifier that can be used to
dvander@251
   401
     * build fully-qualified package identifiers.
dvander@251
   402
     */
dvander@251
   403
    static bool InstallSystemRoot(const char *path, const char *name);
dvander@251
   404
dvander@251
   405
    /*
dvander@251
   406
     * Compiles a source file into a package and runs any initializers it has.
dvander@251
   407
     * The file name must be a file name only, rather than a path. It may
dvander@251
   408
     * optionally end in ".sp". If no ".sp" is provided, it is added
dvander@251
   409
     * automatically.
dvander@251
   410
     *
dvander@251
   411
     * Note that if the file name (sans ".sp" extension) does not match the
dvander@251
   412
     * regular expression /^[A-Za-z_][A-Za-z0-9_]+$/ then it will not be
dvander@251
   413
     * importable from other files.
dvander@251
   414
     */
dvander@251
   415
    static bool Compile(Handle<Package> package, const char *name);
dvander@62
   416
};
dvander@60
   417
dvander@60
   418
/*
dvander@64
   419
 * Suppresses exceptions. This is useful for calling API functions. When this
dvander@64
   420
 * in scope, errors will be reported, but the exception will be cleared after.
dvander@64
   421
 */
dvander@64
   422
class AutoClearExceptions
dvander@64
   423
{
dvander@64
   424
  public:
dvander@64
   425
    ~AutoClearExceptions()
dvander@64
   426
    {
dvander@64
   427
        Keima::ClearPendingException();
dvander@64
   428
    }
dvander@64
   429
};
dvander@64
   430
dvander@65
   431
// Argument-passing interface for Invoke().
dvander@65
   432
class Parameter
dvander@65
   433
{
dvander@65
   434
  public:
dvander@65
   435
    enum Type {
dvander@65
   436
        Int,
dvander@65
   437
        Float,
dvander@65
   438
        IntRef,
dvander@65
   439
        FloatRef,
dvander@65
   440
        Array,
dvander@65
   441
        CharArray
dvander@65
   442
    };
dvander@65
   443
dvander@65
   444
    Parameter()
dvander@65
   445
    {
dvander@65
   446
    }
dvander@65
   447
dvander@65
   448
    Parameter(int i)
dvander@65
   449
      : type_(Int)
dvander@65
   450
    {
dvander@65
   451
        u.i = i;
dvander@65
   452
    }
dvander@65
   453
dvander@65
   454
    Parameter(int *i, bool writeback)
dvander@65
   455
      : type_(IntRef),
dvander@65
   456
        writeback_(writeback)
dvander@65
   457
    {
dvander@65
   458
        u.ip = i;
dvander@65
   459
    }
dvander@65
   460
dvander@65
   461
    Parameter(float f)
dvander@65
   462
      : type_(Float)
dvander@65
   463
    {
dvander@65
   464
        u.f = f;
dvander@65
   465
    }
dvander@65
   466
dvander@65
   467
    Parameter(float *f, bool writeback)
dvander@65
   468
      : type_(FloatRef),
dvander@65
   469
        writeback_(writeback)
dvander@65
   470
    {
dvander@65
   471
        u.fp = f;
dvander@65
   472
    }
dvander@65
   473
dvander@65
   474
    Parameter(Type type, void *buffer, size_t length, bool writeback)
dvander@65
   475
      : type_(type),
dvander@65
   476
        writeback_(writeback),
dvander@65
   477
        length_(length)
dvander@65
   478
    {
dvander@65
   479
        assert(type == Array || type == CharArray);
dvander@65
   480
        u.buffer = buffer;
dvander@65
   481
    }
dvander@65
   482
dvander@65
   483
    Type type() const {
dvander@65
   484
        return type_;
dvander@65
   485
    }
dvander@65
   486
dvander@65
   487
    int i32() const {
dvander@65
   488
        assert(type() == Int);
dvander@65
   489
        return u.i;
dvander@65
   490
    }
dvander@65
   491
    float f() const {
dvander@65
   492
        assert(type() == Float);
dvander@65
   493
        return u.f;
dvander@65
   494
    }
dvander@65
   495
    int *i32p() const {
dvander@65
   496
        assert(type() == IntRef);
dvander@65
   497
        return u.ip;
dvander@65
   498
    }
dvander@65
   499
    float *fp() const {
dvander@65
   500
        assert(type() == FloatRef);
dvander@65
   501
        return u.fp;
dvander@65
   502
    }
dvander@65
   503
    bool writeback() const {
dvander@65
   504
        assert(type() >= IntRef && type() <= CharArray);
dvander@65
   505
        return writeback_;
dvander@65
   506
    }
dvander@65
   507
    size_t length() const {
dvander@65
   508
        return length_;
dvander@65
   509
    }
dvander@65
   510
    void *buffer() const {
dvander@65
   511
        assert(type() == Array || type() == CharArray);
dvander@65
   512
        return u.buffer;
dvander@65
   513
    }
dvander@65
   514
dvander@65
   515
  private:
dvander@65
   516
    Type type_;
dvander@65
   517
    bool writeback_;
dvander@65
   518
    size_t length_;
dvander@65
   519
dvander@65
   520
    union {
dvander@65
   521
        int i;
dvander@65
   522
        float f;
dvander@65
   523
        int *ip;
dvander@65
   524
        float *fp;
dvander@65
   525
        void *buffer;
dvander@65
   526
    } u;
dvander@65
   527
};
dvander@64
   528
dvander@61
   529
class Internals
dvander@61
   530
{
dvander@61
   531
    template <typename T> friend class Root;
dvander@61
   532
dvander@61
   533
  private:
dvander@195
   534
    static ke::HeapRoot *NewHeapRoot();
dvander@195
   535
    static void Destroy(ke::HeapRoot *root);
dvander@61
   536
};
dvander@61
   537
dvander@61
   538
template <typename T> void
dvander@195
   539
Root<T>::set(Handle<T> other)
dvander@61
   540
{
dvander@195
   541
    if (!other) {
dvander@195
   542
        obj_ = other;
dvander@61
   543
        return;
dvander@195
   544
    }
dvander@195
   545
dvander@195
   546
    ke::Object **ptr = reinterpret_cast<ke::Object **>(*other);
dvander@195
   547
    if (!root_) {
dvander@195
   548
        root_ = Internals::NewHeapRoot();
dvander@195
   549
        if (!root_)
dvander@195
   550
            return;
dvander@195
   551
    }
dvander@195
   552
dvander@195
   553
    *reinterpret_cast<ke::Object **>(root_) = *ptr;
dvander@195
   554
    obj_.obj_ = reinterpret_cast<T *>(root_);
dvander@61
   555
}
dvander@61
   556
dvander@195
   557
template <typename T>
dvander@195
   558
Root<T>::~Root()
dvander@61
   559
{
dvander@195
   560
    if (!root_)
dvander@61
   561
        return;
dvander@195
   562
    Internals::Destroy(root_);
dvander@61
   563
}
dvander@61
   564
dvander@195
   565
dvander@60
   566
}
dvander@60
   567
danderson@96
   568
#endif // _include_sourcepawn2_api_h_