|
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@64
|
38 |
|
|
dvander@60
|
39 |
/* |
|
dvander@60
|
40 |
* A Handle is a safe pointer that holds an object reference, such that it |
|
dvander@60
|
41 |
* can be scanned and potentially moved by the garbage collector. |
|
dvander@60
|
42 |
*/ |
|
dvander@60
|
43 |
template <typename T> |
|
dvander@60
|
44 |
class Handle |
|
dvander@60
|
45 |
{ |
|
dvander@195
|
46 |
template <typename S> friend class Root; |
|
dvander@60
|
47 |
protected: |
|
dvander@60
|
48 |
template <typename S> void typeCheck() { |
|
dvander@60
|
49 |
while (false) { |
|
dvander@60
|
50 |
T *v1 = NULL; |
|
dvander@60
|
51 |
S *v2 = NULL; |
|
dvander@60
|
52 |
v1 = v2; |
|
dvander@60
|
53 |
(void)v1; |
|
dvander@60
|
54 |
} |
|
dvander@60
|
55 |
} |
|
dvander@60
|
56 |
|
|
dvander@60
|
57 |
public: |
|
dvander@60
|
58 |
Handle() |
|
dvander@60
|
59 |
: obj_(NULL) |
|
dvander@60
|
60 |
{ |
|
dvander@60
|
61 |
} |
|
dvander@60
|
62 |
|
|
dvander@60
|
63 |
template <typename S> Handle(Handle<S> other) |
|
dvander@60
|
64 |
: obj_(reinterpret_cast<S *>(*other)) |
|
dvander@60
|
65 |
{ |
|
dvander@60
|
66 |
typeCheck<S>(); |
|
dvander@60
|
67 |
} |
|
dvander@60
|
68 |
|
|
dvander@60
|
69 |
explicit Handle(T *obj) |
|
dvander@60
|
70 |
: obj_(obj) |
|
dvander@60
|
71 |
{ |
|
dvander@60
|
72 |
} |
|
dvander@60
|
73 |
|
|
dvander@60
|
74 |
T *operator ->() const { |
|
dvander@60
|
75 |
return obj_; |
|
dvander@60
|
76 |
} |
|
dvander@60
|
77 |
T *operator *() const { |
|
dvander@60
|
78 |
return obj_; |
|
dvander@60
|
79 |
} |
|
dvander@60
|
80 |
operator bool () const { |
|
dvander@60
|
81 |
return !!obj_; |
|
dvander@60
|
82 |
} |
|
dvander@60
|
83 |
|
|
dvander@65
|
84 |
protected: |
|
dvander@60
|
85 |
T *obj_; |
|
dvander@60
|
86 |
}; |
|
dvander@60
|
87 |
|
|
dvander@60
|
88 |
/* |
|
dvander@60
|
89 |
* A local variable that roots an object. Locals are owned by the nearest |
|
dvander@60
|
90 |
* HandleScope, and as soon as that HandleScope dies, all its Locals are |
|
dvander@60
|
91 |
* no longer available. |
|
dvander@60
|
92 |
*/ |
|
dvander@60
|
93 |
template <typename T> |
|
dvander@60
|
94 |
class Local : public Handle<T> |
|
dvander@60
|
95 |
{ |
|
dvander@60
|
96 |
public: |
|
dvander@60
|
97 |
Local() |
|
dvander@60
|
98 |
: Handle<T>() |
|
dvander@60
|
99 |
{ |
|
dvander@60
|
100 |
} |
|
dvander@60
|
101 |
|
|
dvander@60
|
102 |
template <typename S> Local(Local<S> other) |
|
dvander@60
|
103 |
: Handle<T>(reinterpret_cast<T *>(*other)) |
|
dvander@60
|
104 |
{ |
|
danderson@91
|
105 |
this->template typeCheck<S>(); |
|
dvander@60
|
106 |
} |
|
dvander@60
|
107 |
|
|
dvander@60
|
108 |
template <typename S> Local(S *other) |
|
dvander@60
|
109 |
: Handle<T>(other) |
|
dvander@60
|
110 |
{ |
|
dvander@60
|
111 |
} |
|
dvander@60
|
112 |
}; |
|
dvander@60
|
113 |
|
|
dvander@60
|
114 |
/* |
|
dvander@195
|
115 |
* A non-local variable that outlives HandleScopes. Unlike Local, a Root |
|
dvander@195
|
116 |
* actually represents a rooted location. Roots must be allocated and |
|
dvander@195
|
117 |
* disposed, and assignment to a root changes its contained object, not |
|
dvander@195
|
118 |
* the location of the object. |
|
dvander@60
|
119 |
*/ |
|
dvander@60
|
120 |
template <typename T> |
|
dvander@195
|
121 |
class Root |
|
dvander@60
|
122 |
{ |
|
dvander@60
|
123 |
public: |
|
dvander@195
|
124 |
Root() |
|
dvander@195
|
125 |
: root_(NULL) |
|
dvander@60
|
126 |
{ |
|
dvander@60
|
127 |
} |
|
dvander@60
|
128 |
|
|
dvander@195
|
129 |
Root(Handle<T> other) |
|
dvander@195
|
130 |
: root_(NULL) |
|
dvander@60
|
131 |
{ |
|
dvander@195
|
132 |
set(other); |
|
dvander@60
|
133 |
} |
|
dvander@60
|
134 |
|
|
dvander@195
|
135 |
inline ~Root(); |
|
dvander@195
|
136 |
|
|
dvander@195
|
137 |
operator const Handle<T>() const { |
|
dvander@195
|
138 |
return obj_; |
|
dvander@60
|
139 |
} |
|
dvander@60
|
140 |
|
|
dvander@195
|
141 |
bool operator ==(Handle<T> other) { |
|
dvander@195
|
142 |
return Handle<T>(*this) == other; |
|
dvander@60
|
143 |
} |
|
dvander@195
|
144 |
Root<T> &operator =(Handle<T> other) { |
|
dvander@195
|
145 |
set(other); |
|
dvander@60
|
146 |
return *this; |
|
dvander@60
|
147 |
} |
|
dvander@60
|
148 |
|
|
dvander@60
|
149 |
private: |
|
dvander@195
|
150 |
void set(Handle<T> other); |
|
dvander@195
|
151 |
|
|
dvander@195
|
152 |
ke::HeapRoot *root_; |
|
dvander@195
|
153 |
Handle<T> obj_; |
|
dvander@60
|
154 |
}; |
|
dvander@60
|
155 |
|
|
dvander@60
|
156 |
/* |
|
dvander@60
|
157 |
* A HandleScope is where Local roots are allcoated. When the HandleScope |
|
dvander@60
|
158 |
* is destroyed, all Handles created under it are also destroyed. HandleScopes |
|
dvander@60
|
159 |
* may only be allocated on the stack, in LIFO order. |
|
dvander@60
|
160 |
*/ |
|
dvander@60
|
161 |
class HandleScope |
|
dvander@60
|
162 |
{ |
|
dvander@60
|
163 |
protected: |
|
dvander@60
|
164 |
ke::Zone *zone_; |
|
dvander@60
|
165 |
ke::Object **position_; |
|
dvander@60
|
166 |
HandleScope *prev_; |
|
dvander@60
|
167 |
|
|
dvander@60
|
168 |
HandleScope(ke::Zone *zone, ke::Object **position, HandleScope *prev) |
|
dvander@60
|
169 |
: zone_(zone), |
|
dvander@60
|
170 |
position_(position), |
|
dvander@60
|
171 |
prev_(prev) |
|
dvander@60
|
172 |
{ |
|
dvander@60
|
173 |
} |
|
dvander@60
|
174 |
|
|
dvander@60
|
175 |
public: |
|
dvander@60
|
176 |
HandleScope(); |
|
dvander@60
|
177 |
~HandleScope(); |
|
dvander@60
|
178 |
|
|
dvander@60
|
179 |
static ke::Object **CreateHandle(ke::Object *obj); |
|
dvander@60
|
180 |
|
|
dvander@60
|
181 |
private: |
|
dvander@60
|
182 |
// Disallow silly stuff. |
|
dvander@60
|
183 |
HandleScope(const HandleScope &); |
|
dvander@60
|
184 |
void operator =(const HandleScope &); |
|
dvander@60
|
185 |
void *operator new (size_t size); |
|
dvander@60
|
186 |
void operator delete(void *, size_t); |
|
dvander@60
|
187 |
}; |
|
dvander@60
|
188 |
|
|
dvander@65
|
189 |
class Parameter; |
|
dvander@65
|
190 |
|
|
dvander@69
|
191 |
// Error messages are pumped through this interface. |
|
dvander@69
|
192 |
class IMessageReporter |
|
dvander@69
|
193 |
{ |
|
dvander@69
|
194 |
public: |
|
dvander@69
|
195 |
virtual void onOutOfMemory() { |
|
dvander@69
|
196 |
} |
|
dvander@69
|
197 |
virtual void onUncaughtException(const char *message) { |
|
dvander@69
|
198 |
} |
|
dvander@69
|
199 |
virtual void beginCompilationErrors(const char *file) { |
|
dvander@69
|
200 |
} |
|
dvander@69
|
201 |
virtual void reportCompilationError(const char *message, unsigned line, unsigned col) { |
|
dvander@69
|
202 |
} |
|
dvander@69
|
203 |
virtual void endCompilationErrors() { |
|
dvander@69
|
204 |
} |
|
dvander@69
|
205 |
}; |
|
dvander@69
|
206 |
|
|
dvander@69
|
207 |
// For the purposes of error reporting, very basic information can be queried |
|
dvander@69
|
208 |
// about the stack frame. This structure may be used to retrieve such |
|
dvander@69
|
209 |
// information. During iteration, it is illegal to re-enter any scripted code |
|
dvander@69
|
210 |
// or call any Keima functions that may cause garbage collection. |
|
dvander@69
|
211 |
class IStackFrameIterator |
|
dvander@69
|
212 |
{ |
|
dvander@69
|
213 |
public: |
|
dvander@195
|
214 |
virtual ~IStackFrameIterator() { |
|
dvander@195
|
215 |
} |
|
dvander@69
|
216 |
|
|
dvander@69
|
217 |
// Returns true if there are more frames, false otherwise. |
|
dvander@69
|
218 |
virtual bool done() = 0; |
|
dvander@69
|
219 |
|
|
dvander@69
|
220 |
// Returns the name of the current function. This may be NULL if the |
|
dvander@69
|
221 |
// function is anonymous. |
|
dvander@69
|
222 |
virtual const char *function() = 0; |
|
dvander@69
|
223 |
|
|
dvander@69
|
224 |
// Returns the file of the current function. This will return an invalid |
|
dvander@69
|
225 |
// path for C++ functions (for example, "<native>"). |
|
dvander@69
|
226 |
virtual const char *source() = 0; |
|
dvander@69
|
227 |
|
|
dvander@69
|
228 |
// Returns the line number currently executing on this frame. For C++ |
|
dvander@69
|
229 |
// functions, this is always 0. |
|
dvander@69
|
230 |
virtual unsigned lineNumber() = 0; |
|
dvander@69
|
231 |
|
|
dvander@69
|
232 |
// Advance to the previous frame in the call stack. |
|
dvander@69
|
233 |
virtual void prev() = 0; |
|
dvander@69
|
234 |
}; |
|
dvander@69
|
235 |
|
|
dvander@195
|
236 |
// Listener interface for when public functions are registered or unregisted. |
|
dvander@195
|
237 |
class IPublicFunctionListener |
|
dvander@195
|
238 |
{ |
|
dvander@195
|
239 |
public: |
|
dvander@195
|
240 |
virtual ~IPublicFunctionListener() { |
|
dvander@195
|
241 |
} |
|
dvander@195
|
242 |
|
|
dvander@195
|
243 |
// Called when a public function becomes available to the runtime. |
|
dvander@195
|
244 |
virtual void registerPublic(Handle<Function> fun) = 0; |
|
dvander@195
|
245 |
|
|
dvander@195
|
246 |
// Called when a public is no longer available to the runtime. |
|
dvander@195
|
247 |
virtual void unregisterPublic(Handle<Function> fun) = 0; |
|
dvander@195
|
248 |
}; |
|
dvander@195
|
249 |
|
|
dvander@64
|
250 |
// A string is an immutable UTF8 buffer. |
|
dvander@64
|
251 |
class KE_EXPORT String |
|
dvander@64
|
252 |
{ |
|
dvander@64
|
253 |
public: |
|
dvander@64
|
254 |
// Returns the length of the string, in bytes. |
|
dvander@64
|
255 |
unsigned length(); |
|
dvander@64
|
256 |
|
|
dvander@64
|
257 |
// Returns the character buffer of the string, or NULL on failure. If the |
|
dvander@64
|
258 |
// string is interned, chars() is guaranteed to succeed. |
|
dvander@64
|
259 |
const char *chars(); |
|
dvander@64
|
260 |
}; |
|
dvander@64
|
261 |
|
|
dvander@64
|
262 |
// A function is an executable unit of code. |
|
dvander@64
|
263 |
class KE_EXPORT Function |
|
dvander@64
|
264 |
{ |
|
dvander@64
|
265 |
public: |
|
dvander@64
|
266 |
// Returns the name of a function, which may be NULL. If not NULL, the |
|
dvander@68
|
267 |
// string is guaranteed to be interned. |
|
dvander@64
|
268 |
Local<String> name(); |
|
dvander@64
|
269 |
}; |
|
dvander@64
|
270 |
|
|
dvander@170
|
271 |
// A pubvar is an ISourcePawnEngine-compatible structure that holds information |
|
dvander@170
|
272 |
// about public variables. |
|
dvander@170
|
273 |
class KE_EXPORT Pubvar |
|
dvander@170
|
274 |
{ |
|
dvander@170
|
275 |
public: |
|
dvander@170
|
276 |
// Returns the name of a pubvar, which is never NULL. The string is |
|
dvander@170
|
277 |
// guaranteed to be interned. |
|
dvander@170
|
278 |
Local<String> name(); |
|
dvander@170
|
279 |
}; |
|
dvander@170
|
280 |
|
|
dvander@62
|
281 |
// A module represents a single compiled file, and contains functions and |
|
dvander@62
|
282 |
// global variables for that file (as well as exported types). |
|
dvander@64
|
283 |
class KE_EXPORT Module |
|
dvander@62
|
284 |
{ |
|
dvander@62
|
285 |
public: |
|
dvander@68
|
286 |
// Sets the native identity pointer, which is passed as the first argument |
|
dvander@68
|
287 |
// to natives. |
|
dvander@68
|
288 |
void setNativeIdentity(void *ptr); |
|
dvander@62
|
289 |
}; |
|
dvander@62
|
290 |
|
|
dvander@62
|
291 |
class Keima |
|
dvander@62
|
292 |
{ |
|
dvander@62
|
293 |
public: |
|
dvander@62
|
294 |
/* |
|
dvander@62
|
295 |
* Initializes the Keima engine. This must be called exactly once before any |
|
dvander@62
|
296 |
* other Keima functions are called. After this, it is safe to use Keima |
|
dvander@62
|
297 |
* on the calling thread. |
|
dvander@62
|
298 |
*/ |
|
dvander@62
|
299 |
static bool Initialize(); |
|
dvander@60
|
300 |
|
|
dvander@62
|
301 |
/* |
|
dvander@62
|
302 |
* Shuts down the Keima engine and frees data structures on all threads. |
|
dvander@62
|
303 |
*/ |
|
dvander@62
|
304 |
static void Shutdown(); |
|
dvander@60
|
305 |
|
|
dvander@62
|
306 |
/* |
|
dvander@62
|
307 |
* Searches the call stack and returns true if the given module has any |
|
dvander@62
|
308 |
* active code running. This is an O(n) algorithm. |
|
dvander@62
|
309 |
*/ |
|
dvander@62
|
310 |
static bool IsInCallStack(Handle<Module> module); |
|
dvander@62
|
311 |
|
|
dvander@62
|
312 |
/* |
|
dvander@62
|
313 |
* Reclaim as much memory as possible. This pauses the calling thread |
|
dvander@62
|
314 |
* until garbage collection completes. |
|
dvander@62
|
315 |
*/ |
|
dvander@62
|
316 |
static void CollectGarbage(); |
|
dvander@64
|
317 |
|
|
dvander@64
|
318 |
/* |
|
dvander@64
|
319 |
* Clear any pending exception. |
|
dvander@64
|
320 |
*/ |
|
dvander@64
|
321 |
static void ClearPendingException(); |
|
dvander@65
|
322 |
|
|
dvander@65
|
323 |
/* |
|
dvander@65
|
324 |
* Executes a function with the given parameters. This interface is |
|
dvander@65
|
325 |
* intended for compatibility with SourceMod's ISourcePawnEngine2 and |
|
dvander@65
|
326 |
* should not be used otherwise, since it is intended to support only |
|
dvander@65
|
327 |
* a small subset of the core language. |
|
dvander@65
|
328 |
*/ |
|
dvander@129
|
329 |
static bool Invoke(Handle<Function> fun, const Parameter *params, unsigned nparams, |
|
dvander@129
|
330 |
bool checkTypes, int *result); |
|
dvander@69
|
331 |
|
|
dvander@69
|
332 |
/* |
|
dvander@69
|
333 |
* Sets the global message handler through which errors will be reported |
|
dvander@69
|
334 |
*/ |
|
dvander@69
|
335 |
static void InstallMessageReporter(IMessageReporter *reporter); |
|
dvander@69
|
336 |
|
|
dvander@195
|
337 |
/* Returns a new stack frame iterator object. */ |
|
dvander@69
|
338 |
static IStackFrameIterator *NewStackFrameIterator(); |
|
dvander@195
|
339 |
|
|
dvander@195
|
340 |
/* |
|
dvander@195
|
341 |
* Binds a native, by name, to an address. Natives are an ISPE1 concept |
|
dvander@195
|
342 |
* (originally from Pawn/Small's AMX API). In SourceMod 1, natives were |
|
dvander@195
|
343 |
* registered globally, but bound to plugins individually. We roughly |
|
dvander@195
|
344 |
* preserve that functionality here, by allowing host applications to |
|
dvander@195
|
345 |
* give us the name -> address mappings. |
|
dvander@195
|
346 |
* |
|
dvander@195
|
347 |
* Natives can be rebound or unbound any number of times. This function |
|
dvander@195
|
348 |
* fails if there is not enough memory. |
|
dvander@195
|
349 |
*/ |
|
dvander@195
|
350 |
static bool BindNative(const char *name, void *address); |
|
dvander@195
|
351 |
|
|
dvander@195
|
352 |
/* Sets the object that will listen for public functions. */ |
|
dvander@195
|
353 |
static void SetPublicFunctionListener(IPublicFunctionListener *listener); |
|
dvander@62
|
354 |
}; |
|
dvander@60
|
355 |
|
|
dvander@60
|
356 |
/* |
|
dvander@64
|
357 |
* Suppresses exceptions. This is useful for calling API functions. When this |
|
dvander@64
|
358 |
* in scope, errors will be reported, but the exception will be cleared after. |
|
dvander@64
|
359 |
*/ |
|
dvander@64
|
360 |
class AutoClearExceptions |
|
dvander@64
|
361 |
{ |
|
dvander@64
|
362 |
public: |
|
dvander@64
|
363 |
~AutoClearExceptions() |
|
dvander@64
|
364 |
{ |
|
dvander@64
|
365 |
Keima::ClearPendingException(); |
|
dvander@64
|
366 |
} |
|
dvander@64
|
367 |
}; |
|
dvander@64
|
368 |
|
|
dvander@65
|
369 |
// Argument-passing interface for Invoke(). |
|
dvander@65
|
370 |
class Parameter |
|
dvander@65
|
371 |
{ |
|
dvander@65
|
372 |
public: |
|
dvander@65
|
373 |
enum Type { |
|
dvander@65
|
374 |
Int, |
|
dvander@65
|
375 |
Float, |
|
dvander@65
|
376 |
IntRef, |
|
dvander@65
|
377 |
FloatRef, |
|
dvander@65
|
378 |
Array, |
|
dvander@65
|
379 |
CharArray |
|
dvander@65
|
380 |
}; |
|
dvander@65
|
381 |
|
|
dvander@65
|
382 |
Parameter() |
|
dvander@65
|
383 |
{ |
|
dvander@65
|
384 |
} |
|
dvander@65
|
385 |
|
|
dvander@65
|
386 |
Parameter(int i) |
|
dvander@65
|
387 |
: type_(Int) |
|
dvander@65
|
388 |
{ |
|
dvander@65
|
389 |
u.i = i; |
|
dvander@65
|
390 |
} |
|
dvander@65
|
391 |
|
|
dvander@65
|
392 |
Parameter(int *i, bool writeback) |
|
dvander@65
|
393 |
: type_(IntRef), |
|
dvander@65
|
394 |
writeback_(writeback) |
|
dvander@65
|
395 |
{ |
|
dvander@65
|
396 |
u.ip = i; |
|
dvander@65
|
397 |
} |
|
dvander@65
|
398 |
|
|
dvander@65
|
399 |
Parameter(float f) |
|
dvander@65
|
400 |
: type_(Float) |
|
dvander@65
|
401 |
{ |
|
dvander@65
|
402 |
u.f = f; |
|
dvander@65
|
403 |
} |
|
dvander@65
|
404 |
|
|
dvander@65
|
405 |
Parameter(float *f, bool writeback) |
|
dvander@65
|
406 |
: type_(FloatRef), |
|
dvander@65
|
407 |
writeback_(writeback) |
|
dvander@65
|
408 |
{ |
|
dvander@65
|
409 |
u.fp = f; |
|
dvander@65
|
410 |
} |
|
dvander@65
|
411 |
|
|
dvander@65
|
412 |
Parameter(Type type, void *buffer, size_t length, bool writeback) |
|
dvander@65
|
413 |
: type_(type), |
|
dvander@65
|
414 |
writeback_(writeback), |
|
dvander@65
|
415 |
length_(length) |
|
dvander@65
|
416 |
{ |
|
dvander@65
|
417 |
assert(type == Array || type == CharArray); |
|
dvander@65
|
418 |
u.buffer = buffer; |
|
dvander@65
|
419 |
} |
|
dvander@65
|
420 |
|
|
dvander@65
|
421 |
Type type() const { |
|
dvander@65
|
422 |
return type_; |
|
dvander@65
|
423 |
} |
|
dvander@65
|
424 |
|
|
dvander@65
|
425 |
int i32() const { |
|
dvander@65
|
426 |
assert(type() == Int); |
|
dvander@65
|
427 |
return u.i; |
|
dvander@65
|
428 |
} |
|
dvander@65
|
429 |
float f() const { |
|
dvander@65
|
430 |
assert(type() == Float); |
|
dvander@65
|
431 |
return u.f; |
|
dvander@65
|
432 |
} |
|
dvander@65
|
433 |
int *i32p() const { |
|
dvander@65
|
434 |
assert(type() == IntRef); |
|
dvander@65
|
435 |
return u.ip; |
|
dvander@65
|
436 |
} |
|
dvander@65
|
437 |
float *fp() const { |
|
dvander@65
|
438 |
assert(type() == FloatRef); |
|
dvander@65
|
439 |
return u.fp; |
|
dvander@65
|
440 |
} |
|
dvander@65
|
441 |
bool writeback() const { |
|
dvander@65
|
442 |
assert(type() >= IntRef && type() <= CharArray); |
|
dvander@65
|
443 |
return writeback_; |
|
dvander@65
|
444 |
} |
|
dvander@65
|
445 |
size_t length() const { |
|
dvander@65
|
446 |
return length_; |
|
dvander@65
|
447 |
} |
|
dvander@65
|
448 |
void *buffer() const { |
|
dvander@65
|
449 |
assert(type() == Array || type() == CharArray); |
|
dvander@65
|
450 |
return u.buffer; |
|
dvander@65
|
451 |
} |
|
dvander@65
|
452 |
|
|
dvander@65
|
453 |
private: |
|
dvander@65
|
454 |
Type type_; |
|
dvander@65
|
455 |
bool writeback_; |
|
dvander@65
|
456 |
size_t length_; |
|
dvander@65
|
457 |
|
|
dvander@65
|
458 |
union { |
|
dvander@65
|
459 |
int i; |
|
dvander@65
|
460 |
float f; |
|
dvander@65
|
461 |
int *ip; |
|
dvander@65
|
462 |
float *fp; |
|
dvander@65
|
463 |
void *buffer; |
|
dvander@65
|
464 |
} u; |
|
dvander@65
|
465 |
}; |
|
dvander@64
|
466 |
|
|
dvander@64
|
467 |
/* |
|
dvander@60
|
468 |
* Compiles a file and returns a Module. |
|
dvander@60
|
469 |
*/ |
|
dvander@232
|
470 |
extern bool Compile(const char *path); |
|
dvander@60
|
471 |
|
|
dvander@61
|
472 |
class Internals |
|
dvander@61
|
473 |
{ |
|
dvander@61
|
474 |
template <typename T> friend class Root; |
|
dvander@61
|
475 |
|
|
dvander@61
|
476 |
private: |
|
dvander@195
|
477 |
static ke::HeapRoot *NewHeapRoot(); |
|
dvander@195
|
478 |
static void Destroy(ke::HeapRoot *root); |
|
dvander@61
|
479 |
}; |
|
dvander@61
|
480 |
|
|
dvander@61
|
481 |
template <typename T> void |
|
dvander@195
|
482 |
Root<T>::set(Handle<T> other) |
|
dvander@61
|
483 |
{ |
|
dvander@195
|
484 |
if (!other) { |
|
dvander@195
|
485 |
obj_ = other; |
|
dvander@61
|
486 |
return; |
|
dvander@195
|
487 |
} |
|
dvander@195
|
488 |
|
|
dvander@195
|
489 |
ke::Object **ptr = reinterpret_cast<ke::Object **>(*other); |
|
dvander@195
|
490 |
if (!root_) { |
|
dvander@195
|
491 |
root_ = Internals::NewHeapRoot(); |
|
dvander@195
|
492 |
if (!root_) |
|
dvander@195
|
493 |
return; |
|
dvander@195
|
494 |
} |
|
dvander@195
|
495 |
|
|
dvander@195
|
496 |
*reinterpret_cast<ke::Object **>(root_) = *ptr; |
|
dvander@195
|
497 |
obj_.obj_ = reinterpret_cast<T *>(root_); |
|
dvander@61
|
498 |
} |
|
dvander@61
|
499 |
|
|
dvander@195
|
500 |
template <typename T> |
|
dvander@195
|
501 |
Root<T>::~Root() |
|
dvander@61
|
502 |
{ |
|
dvander@195
|
503 |
if (!root_) |
|
dvander@61
|
504 |
return; |
|
dvander@195
|
505 |
Internals::Destroy(root_); |
|
dvander@61
|
506 |
} |
|
dvander@61
|
507 |
|
|
dvander@195
|
508 |
|
|
dvander@60
|
509 |
} |
|
dvander@60
|
510 |
|
|
danderson@96
|
511 |
#endif // _include_sourcepawn2_api_h_ |