Example #1
0
int unpersist_l(lua_State *L) {
	LoadInfo li;
	/* perms? str? ...? */
	lua_settop(L, 2);
	/* perms? str? */
	li.buf = luaL_checklstring(L, 2, &li.size);
	/* perms? str */
	lua_pop(L, 1);
	/* It is conceivable that the buffer might now be collectable,
	 * which would cause problems in the reader. I can't think of
	 * any situation where there would be no other reference to the
	 * buffer, so for now I'll leave it alone, but this is a potential
	 * bug. */
	/* perms? */
	luaL_checktype(L, 1, LUA_TTABLE);
	/* perms */
	pluto_unpersist(L, bufreader, &li);
	/* perms rootobj */
	return 1;
}
Example #2
0
bool LuaScriptEngine::unpersist(InputPersistenceBlock &reader) {
	// Empty the Lua stack. pluto_persist() xepects that the stack is empty except for its parameters
	lua_settop(_state, 0);

	// Permanents table is placed on the stack. This has already happened at this point, because
	// to create the table all permanents must be accessible. This is the case only for the
	// beginning of the function, because the global table is emptied below
	pushPermanentsTable(_state, PTT_UNPERSIST);

	// All items from global table of _G and __METATABLES are removed.
	// After a garbage collection is performed, and thus all managed objects deleted

	// __METATABLES is not immediately removed becausen the Metatables are needed
	// for the finalisers of objects.
	static const char *clearExceptionsFirstPass[] = {
		"_G",
		"__METATABLES",
		0
	};
	clearGlobalTable(_state, clearExceptionsFirstPass);

	// In the second pass, the Metatables are removed
	static const char *clearExceptionsSecondPass[] = {
		"_G",
		0
	};
	clearGlobalTable(_state, clearExceptionsSecondPass);

	// Persisted Lua data
	Common::Array<byte> chunkData;
	reader.readByteArray(chunkData);

	// Chunk-Reader initialisation. It is used with pluto_unpersist to restore read data
	ChunkreaderData cd;
	cd.BufferPtr = &chunkData[0];
	cd.Size = chunkData.size();
	cd.BufferReturned = false;

	pluto_unpersist(_state, chunkreader, &cd);

	// Permanents-Table is removed from stack
	lua_remove(_state, -2);

	// The read elements in the global table about
	lua_pushnil(_state);
	while (lua_next(_state, -2) != 0) {
		// The referenec to the global table (_G) must not be overwritten, or ticks from Lua total
		bool isGlobalReference = lua_isstring(_state, -2) && strcmp(lua_tostring(_state, -2), "_G") == 0;
		if (!isGlobalReference) {
			lua_pushvalue(_state, -2);
			lua_pushvalue(_state, -2);

			lua_settable(_state, LUA_GLOBALSINDEX);
		}

		// Pop value from the stack. The index is then ready for the next call to lua_next()
		lua_pop(_state, 1);
	}

	// The table with the loaded data is popped from the stack
	lua_pop(_state, 1);

	// Force garbage collection
	lua_gc(_state, LUA_GCCOLLECT, 0);

	return true;
}