]>
Dogcows Code - chaz/yoink/blob - src/Moof/Script.hh
2 /*******************************************************************************
4 Copyright (c) 2009, Charles McGarvey
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *******************************************************************************/
29 #ifndef _MOOF_SCRIPT_HH_
30 #define _MOOF_SCRIPT_HH_
34 * A thin wrapper over Lua. This is not meant as a complicated binding package
35 * between C++ and Lua. It does not try to make the boundary invisible. It
36 * does not hide the concept of the Lua stack, but rather provides that
37 * mechanism with a certain level of abstraction while also providing a cleaner,
38 * more consistent API.
44 #include <boost/bind.hpp>
45 #include <boost/function.hpp>
46 #include <boost/shared_ptr.hpp>
50 #include <Moof/Exception.hh>
57 typedef boost::shared_ptr
<Script
> ScriptP
;
62 typedef boost::function
<int(Script
&)> Function
;
68 BOOLEAN
= LUA_TBOOLEAN
,
69 LIGHTUSERDATA
= LUA_TLIGHTUSERDATA
,
73 FUNCTION
= LUA_TFUNCTION
,
74 USERDATA
= LUA_TUSERDATA
,
82 RUNTIME_ERROR
= LUA_ERRRUN
,
83 SYNTAX_ERROR
= LUA_ERRSYNTAX
,
84 MEMORY_ERROR
= LUA_ERRMEM
,
85 HANDLER_ERROR
= LUA_ERRERR
,
86 FILE_ERROR
= LUA_ERRFILE
91 REGISTRY
= LUA_REGISTRYINDEX
,
92 ENVIRONMENT
= LUA_ENVIRONINDEX
,
93 GLOBALS
= LUA_GLOBALSINDEX
97 * This is the most noticeable abstraction on top of the standard Lua API.
98 * A Value object represents a value on the stack. More specifically, it
99 * represents a position on the stack. The distinction is only important
100 * when values are moved around on the stack or if the Value represents a
101 * negative index on the stack (the value of which will change as things are
102 * pushed onto and popped from the stack).
108 * You have direct access to the index of the value on the stack being
116 * A default-constructed Value is invalid until a valid Value is
117 * assigned to it. The only method that should be called on such a
118 * Value is isValid(), otherwise chaos may ensue. In this case, the
119 * Value will be invalid even if index is manually changed to a valid
120 * index. You have to index the script itself to get a valid Value.
126 Value(lua_State
* s
, int i
) :
130 // check the type of the value
131 bool isBoolean() const { return (bool)lua_isboolean(state
, index
); }
132 bool isFunction() const { return (bool)lua_isfunction(state
, index
); }
133 bool isNil() const { return (bool)lua_isnil(state
, index
); }
134 bool isNone() const { return (bool)lua_isnone(state
, index
); }
135 bool isValid() const { return state
!= 0 && !isNone(); }
136 bool isNoneOrNil() const { return (bool)lua_isnoneornil(state
, index
); }
137 bool isNumber() const { return (bool)lua_isnumber(state
, index
); }
138 bool isString() const { return (bool)lua_isstring(state
, index
); }
139 bool isTable() const { return (bool)lua_istable(state
, index
); }
140 bool isThread() const { return (bool)lua_isthread(state
, index
); }
141 bool isData() const { return (bool)lua_isuserdata(state
, index
); }
142 bool isLightData() const { return (bool)lua_islightuserdata(state
, index
); }
145 * Get the type of the value.
150 return (TYPE
)lua_type(state
, index
);
154 * Get the name of the type of the value as a string.
157 std::string
getTypeName() const
159 return std::string(lua_typename(state
, (int)getType()));
163 * Get a pointer value (for userdata, tables, threads, and functions).
166 const void* getIdentifier() const
168 return lua_topointer(state
, index
);
172 bool operator == (const Value
& rhs
) const
174 return (bool)lua_equal(state
, index
, rhs
.index
);
176 bool operator != (const Value
& rhs
) const
178 return !(*this == rhs
);
180 bool operator < (const Value
& rhs
) const
182 return (bool)lua_lessthan(state
, index
, rhs
.index
);
184 bool operator <= (const Value
& rhs
) const
186 return *this < rhs
|| *this == rhs
;
188 bool operator > (const Value
& rhs
) const
190 return !(*this <= rhs
);
192 bool operator >= (const Value
& rhs
) const
194 return !(*this < rhs
);
196 operator bool () const
198 return (bool)lua_toboolean(state
, index
);
201 Value
& operator = (const Value
& rhs
)
210 * Get the length of the value according to the definition given by Lua.
213 size_t getLength() const
215 return lua_objlen(state
, index
);
220 * Convert the underlying value to a C++ type.
223 template <typename T
>
224 void get(T
& value
) const
226 value
= (T
)lua_tointeger(state
, index
);
229 void get(bool& value
) const
231 value
= (bool)lua_toboolean(state
, index
);
234 void get(float& value
) const
236 value
= (float)lua_tonumber(state
, index
);
238 void get(double& value
) const
240 value
= (double)lua_tonumber(state
, index
);
243 void get(std::string
& value
) const
246 const char* str
= lua_tolstring(state
, index
, &size
);
247 value
.assign(str
, size
);
251 void set(std::string
& value
)
255 //template <typename T>
256 //void get(const std::string& field, T& value) const
258 ////lua_getfield(state_, field.c_str());
261 //lua_pop(state_, 1);
266 * Copy the value and push the copy to the stack.
269 void pushCopy() const
271 lua_pushvalue(state
, index
);
275 * Replace this value with the value at the top of the stack.
278 void replaceWithTop()
280 lua_replace(state
, index
);
285 lua_remove(state
, index
);
289 * Inserts the top-most value on the stack at position index, shifting other
295 lua_insert(state
, index
);
299 void pushMetatable() const
301 lua_getmetatable(state
, index
);
304 void pushField() const
306 lua_gettable(state
, index
);
309 void pushField(const std::string
& name
) const
311 lua_getfield(state
, index
, name
.c_str());
322 state_(luaL_newstate())
324 lua_pushlightuserdata(state_
, this);
325 lua_setfield(state_
, LUA_REGISTRYINDEX
, "_script_obj");
330 if (isMainThread_
) lua_close(state_
);
334 static ScriptP
alloc()
336 return ScriptP(new Script
);
340 void importStandardLibraries()
342 luaL_openlibs(state_
);
345 void importFunction(const std::string
& name
, const Function
& function
)
348 lua_setglobal(state_
, name
.c_str());
352 STATUS
doString(const std::string
& commands
)
354 return (STATUS
)luaL_dostring(state_
, commands
.c_str());
357 STATUS
doFile(const std::string
& file
)
359 return (STATUS
)luaL_dofile(state_
, file
.c_str());
364 * Thread-handling methods.
367 Script
pushNewThread()
369 return Script(state_
);
374 lua_pushthread(state_
);
377 STATUS
resume(int nargs
)
379 return (STATUS
)lua_resume(state_
, nargs
);
382 STATUS
getStatus() const
384 return (STATUS
)lua_status(state_
);
387 int yield(int results
)
389 return lua_yield(state_
, results
);
392 bool isMainThread() const
394 return isMainThread_
;
399 * Get significant values.
402 Value
getGlobalTable() const
404 return Value(state_
, GLOBALS
);
407 Value
getRegistryTable() const
409 return Value(state_
, REGISTRY
);
412 Value
getEnvironmentTable() const
414 return Value(state_
, ENVIRONMENT
);
419 return Value(state_
, lua_gettop(state_
));
423 * Get the size of the stack; this is also the index of the top-most value.
428 return lua_gettop(state_
);
431 void setSize(int size
)
433 lua_settop(state_
, size
);
443 * Makes sure there is at least extra more places on the stack. Returns
444 * false if space couldn't be created. Just like with the regular Lua API,
445 * you are responsible to make sure the stack is big enough to hold whatever
446 * you want to push on it. This is usually only an issue if you're pushing
450 bool checkStack(int extra
)
452 return (bool)lua_checkstack(state_
, extra
);
457 * Concatenates the top-most n values on the stack.
462 lua_concat(state_
, n
);
467 * Push some values onto the stack.
470 template <typename T
>
473 lua_pushinteger(state_
, lua_Integer(value
));
476 void push(bool value
)
478 lua_pushboolean(state_
, int(value
));
481 void push(float value
)
483 lua_pushnumber(state_
, (lua_Number
)value
);
485 void push(double value
)
487 lua_pushnumber(state_
, (lua_Number
)value
);
490 void push(const std::string
& value
)
492 lua_pushlstring(state_
, value
.c_str(), value
.length());
494 void push(const char* value
, size_t length
)
496 lua_pushlstring(state_
, value
, length
);
499 void push(const Function
& function
)
501 functions_
.push_back(function
);
503 lua_pushlightuserdata(state_
, (void*)&functions_
.back());
504 lua_pushcclosure(state_
, dispatchCall
, 1);
507 void push(void* data
)
509 lua_pushlightuserdata(state_
, data
);
517 void pushFromThread(Script
& thread
, int n
)
519 lua_xmove(thread
.state_
, state_
, n
);
522 STATUS
pushCode(const std::string
& filename
)
524 return (STATUS
)luaL_loadfile(state_
, filename
.c_str());
527 STATUS
pushCode(const std::string
& name
, const char* buffer
, size_t size
)
529 return (STATUS
)luaL_loadbuffer(state_
, buffer
, size
, name
.c_str());
532 void* pushNewData(size_t size
)
534 return lua_newuserdata(state_
, size
);
539 lua_newtable(state_
);
544 * Call a function on the stack. The correct procedure is to push a
545 * function onto the stack followed by nargs arguments. This method will
546 * pop them off upon return, leaving up to nresults return values (default
547 * is any number of return values, depending on the callee).
550 STATUS
call(int nargs
, int nresults
= LUA_MULTRET
)
552 return (STATUS
)lua_pcall(state_
, nargs
, nresults
, 0);
557 * Pops n values from the top of the stack.
567 * Index into the stack to get a Value.
570 Value
operator [] (int index
) const
572 return Value(state_
, index
);
577 * Getting and setting fields of a table.
580 void get(const std::string
& field
, int index
= GLOBALS
) const
582 lua_getfield(state_
, index
, field
.c_str());
585 void set(const std::string
& field
, int index
= GLOBALS
)
587 lua_setfield(state_
, index
, field
.c_str());
592 * Control over the garbage collection process.
597 lua_gc(state_
, LUA_GCCOLLECT
, 0);
602 lua_gc(state_
, LUA_GCSTOP
, 0);
605 void restartCollector()
607 lua_gc(state_
, LUA_GCRESTART
, 0);
610 int getUsedMemory() const
613 return lua_gc(state_
, LUA_GCCOUNT
, 0);
616 void collectStep(int step
)
618 lua_gc(state_
, LUA_GCSTEP
, step
);
621 void tuneCollector(int pause
, int step
)
623 lua_gc(state_
, LUA_GCSETPAUSE
, pause
);
624 lua_gc(state_
, LUA_GCSETSTEPMUL
, step
);
629 struct Exception
: public Mf::Exception
631 explicit Exception(unsigned error
) :
632 Mf::Exception(error
) {}
643 Script(lua_State
* state
) :
644 state_(lua_newthread(state
)),
645 isMainThread_(false) {}
647 static int dispatchCall(lua_State
* state
)
649 const Function
* function
= (const Function
*)lua_touserdata(state
,
650 lua_upvalueindex(1));
652 lua_getfield(state
, LUA_REGISTRYINDEX
, "_script_obj");
653 Script
* script
= (Script
*)lua_touserdata(state
, -1);
656 return (*function
)(*script
);
661 std::list
<Function
> functions_
;
667 #endif // _MOOF_SCRIPT_HH_
669 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.064011 seconds and 4 git commands to generate.