File: scripthelper.cpp

package info (click to toggle)
scummvm 2.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 450,580 kB
  • sloc: cpp: 4,299,825; asm: 28,322; python: 12,901; sh: 11,302; java: 9,289; xml: 7,895; perl: 2,639; ansic: 2,465; yacc: 1,670; javascript: 1,020; makefile: 933; lex: 578; awk: 275; objc: 82; sed: 11; php: 1
file content (76 lines) | stat: -rw-r--r-- 2,625 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "scripthelper.h"

#include "hpl1/std/set.h"
#include "common/str.h"

using namespace std;

BEGIN_AS_NAMESPACE

int ExecuteString(asIScriptEngine *engine, const char *code, asIScriptModule *mod, asIScriptContext *ctx) {
	return ExecuteString(engine, code, 0, asTYPEID_VOID, mod, ctx);
}

int ExecuteString(asIScriptEngine *engine, const char *code, void *ref, int refTypeId, asIScriptModule *mod, asIScriptContext *ctx) {
	// Wrap the code in a function so that it can be compiled and executed
	Common::String funcCode = " ExecuteString() {\n";
	funcCode += code;
	funcCode += "\n;}";

	// Determine the return type based on the type of the ref arg
	funcCode = engine->GetTypeDeclaration(refTypeId, true) + funcCode;

	// GetModule will free unused types, so to be on the safe side we'll hold on to a reference to the type
	asITypeInfo *type = 0;
	if (refTypeId & asTYPEID_MASK_OBJECT) {
		type = engine->GetTypeInfoById(refTypeId);
		if (type)
			type->AddRef();
	}

	// If no module was provided, get a dummy from the engine
	asIScriptModule *execMod = mod ? mod : engine->GetModule("ExecuteString", asGM_ALWAYS_CREATE);

	// Now it's ok to release the type
	if (type)
		type->Release();

	// Compile the function that can be executed
	asIScriptFunction *func = 0;
	int r = execMod->CompileFunction("ExecuteString", funcCode.c_str(), -1, 0, &func);
	if (r < 0)
		return r;

	// If no context was provided, request a new one from the engine
	asIScriptContext *execCtx = ctx ? ctx : engine->RequestContext();
	r = execCtx->Prepare(func);
	if (r >= 0) {
		// Execute the function
		r = execCtx->Execute();

		// Unless the provided type was void retrieve it's value
		if (ref != 0 && refTypeId != asTYPEID_VOID) {
			if (refTypeId & asTYPEID_OBJHANDLE) {
				// Expect the pointer to be null to start with
				assert(*reinterpret_cast<void **>(ref) == 0);
				*reinterpret_cast<void **>(ref) = *reinterpret_cast<void **>(execCtx->GetAddressOfReturnValue());
				engine->AddRefScriptObject(*reinterpret_cast<void **>(ref), engine->GetTypeInfoById(refTypeId));
			} else if (refTypeId & asTYPEID_MASK_OBJECT) {
				// Use the registered assignment operator to do a value assign.
				// This assumes that the ref is pointing to a valid object instance.
				engine->AssignScriptObject(ref, execCtx->GetAddressOfReturnValue(), engine->GetTypeInfoById(refTypeId));
			} else {
				// Copy the primitive value
				memcpy(ref, execCtx->GetAddressOfReturnValue(), engine->GetSizeOfPrimitiveType(refTypeId));
			}
		}
	}

	// Clean up
	func->Release();
	if (!ctx) engine->ReturnContext(execCtx);

	return r;
}

END_AS_NAMESPACE