]>
Dogcows Code - chaz/yoink/blob - src/moof/script.hh
85973dd0402f1823434ced4b2da57305b046146d
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
10 **************************************************************************/
12 #ifndef _MOOF_SCRIPT_HH_
13 #define _MOOF_SCRIPT_HH_
17 * A thin wrapper over Lua. This is not meant as a complicated binding
18 * package between C++ and Lua. It is not meant to obscure the division
19 * between C++ and Lua but rather to clarify it and make it more
20 * manageable. It does not hide the concept of the Lua stack, but rather
21 * provides that mechanism with a certain level of abstraction while also
22 * providing a cleaner, more consistent API.
31 #include <boost/bind.hpp>
32 #include <boost/function.hpp>
33 #include <boost/shared_ptr.hpp>
41 typedef boost::shared_ptr
<script
> script_ptr
;
48 typedef boost::function
<int(script
&)> function
;
54 runtime_error
= LUA_ERRRUN
,
55 syntax_error
= LUA_ERRSYNTAX
,
56 memory_error
= LUA_ERRMEM
,
57 handler_error
= LUA_ERRERR
,
58 file_error
= LUA_ERRFILE
63 registry_index
= LUA_REGISTRYINDEX
,
64 environment_index
= LUA_ENVIRONINDEX
,
65 globals_index
= LUA_GLOBALSINDEX
69 * This is the most prominent abstraction on top of the standard Lua
70 * API. A slot object represents a value on the stack. More
71 * specifically, it represents a position on the stack. The
72 * distinction is only important when objects are moved around on the
73 * stack or if the slot represents a negative index on the stack (the
74 * value of which will change as things are pushed onto and popped from
81 * You have direct access to the index of the value on the stack
92 boolean
= LUA_TBOOLEAN
,
93 light_data
= LUA_TLIGHTUSERDATA
,
97 function
= LUA_TFUNCTION
,
103 slot(const class script
& s
, int i
= 0) :
105 script_(const_cast<class script
&>(s
)) {}
108 * A copied value presently points to the same value, except the
109 * real index is used. That means that if a value that refers to a
110 * frame referenced from the top of the stack will have its
111 * normalized index copied into the new value object.
114 //slot(const slot& copy) :
115 //index(copy.positiveIndex()),
116 //script_(copy.script_) {}
119 // check the type of the value
120 bool is_boolean() const
121 { return (bool)lua_isboolean(script_
.state_
, index
); }
122 bool is_imported_function() const
123 { return (bool)lua_iscfunction(script_
.state_
, index
); }
124 bool is_function() const
125 { return (bool)lua_isfunction(script_
.state_
, index
); }
127 { return (bool)lua_isnil(script_
.state_
, index
); }
129 { return (bool)lua_isnone(script_
.state_
, index
); }
130 bool is_none_or_nil() const
131 { return (bool)lua_isnoneornil(script_
.state_
, index
); }
132 bool is_number() const
133 { return (bool)lua_isnumber(script_
.state_
, index
); }
134 bool is_string() const
135 { return (bool)lua_isstring(script_
.state_
, index
); }
136 bool is_table() const
137 { return (bool)lua_istable(script_
.state_
, index
); }
138 bool is_thread() const
139 { return (bool)lua_isthread(script_
.state_
, index
); }
141 { return (bool)lua_isuserdata(script_
.state_
, index
); }
142 bool is_light_data() const
143 { return (bool)lua_islightuserdata(script_
.state_
, index
); }
146 * Check the value and throw an error if its the wrong type.
147 * There's a little caveat: This method never returns because it
148 * does a long jump. Consequently, constructed C++ objects which
149 * exist on the stack between the current frame and some lua
150 * function will not be destructed. That's not a problem for
151 * objects that only exist on the stack, but any objects that
152 * allocate memory on the heap (such as containers or strings) will
153 * leak. Therefore, you should only call this method after
154 * cleaning up such objects. The best thing to do for defining
155 * functions is to simply check all the parameters at the get-go
156 * before any C++ objects are even constructed.
159 void require_type(type t
) const
163 luaL_typerror(script_
.state_
, index
,
164 lua_typename(script_
.state_
, t
));
168 void raise(const char* error
)
170 luaL_argerror(script_
.state_
, index
, error
);
174 slot
& require_boolean()
178 luaL_typerror(script_
.state_
, index
, "boolean");
182 slot
& require_number()
186 luaL_typerror(script_
.state_
, index
, "number");
190 slot
& require_string()
194 luaL_typerror(script_
.state_
, index
, "string");
198 slot
& require_table()
202 luaL_typerror(script_
.state_
, index
, "table");
206 slot
& require_function()
210 luaL_typerror(script_
.state_
, index
, "function");
218 luaL_typerror(script_
.state_
, index
, "data");
226 luaL_typerror(script_
.state_
, index
, "nil");
230 slot
& require_thread()
234 luaL_typerror(script_
.state_
, index
, "thread");
241 * Get the type of the value.
244 enum type
type() const
246 return (enum type
)lua_type(script_
.state_
, index
);
250 * Get the name of the type of the value as a string.
253 std::string
type_name() const
255 return std::string(luaL_typename(script_
.state_
, index
));
260 * Get the length of the value according to the definition given by
264 size_t length() const
266 return lua_objlen(script_
.state_
, index
);
269 int positiveIndex() const
271 if (index
< 0) return index
+ lua_gettop(script_
.state_
) + 1;
277 * Get a pointer value (for userdata, tables, threads, and
281 const void* id() const
283 return lua_topointer(script_
.state_
, index
);
286 bool is_identical(const slot
& rhs
) const
288 return &script_
== &(rhs
.script_
) && index
== rhs
.index
;
291 operator bool () const
297 bool operator == (const slot
& rhs
) const
299 return (bool)lua_equal(script_
.state_
, index
, rhs
.index
);
301 bool operator != (const slot
& rhs
) const
303 return !(*this == rhs
);
306 bool operator < (const slot
& rhs
) const
308 return (bool)lua_lessthan(script_
.state_
, index
, rhs
.index
);
310 bool operator <= (const slot
& rhs
) const
312 return *this < rhs
|| *this == rhs
;
314 bool operator > (const slot
& rhs
) const
316 return !(*this <= rhs
);
318 bool operator >= (const slot
& rhs
) const
320 return !(*this < rhs
);
325 * Convert the underlying value to a C++ type.
329 bool get(T
& value
) const
333 value
= (T
)lua_tointeger(script_
.state_
, index
);
339 bool get(float& value
) const
343 value
= (float)lua_tonumber(script_
.state_
, index
);
348 bool get(double& value
) const
352 value
= (double)lua_tonumber(script_
.state_
, index
);
358 bool get(bool& value
) const
362 value
= (bool)lua_toboolean(script_
.state_
, index
);
368 bool get(const char*& value
, size_t& size
) const
372 value
= lua_tolstring(script_
.state_
, index
, &size
);
378 bool get(std::string
& value
) const
384 value
.assign(str
, size
);
390 bool get(void*& value
) const
394 value
= lua_touserdata(script_
.state_
, index
);
401 bool get(std::vector
<T
>& array
) const
403 if (!is_table()) return false;
407 slot value
= script_
[-1];
408 int realIndex
= positiveIndex();
411 for (int i
= 1; !done
; ++i
)
413 lua_rawgeti(script_
.state_
, realIndex
, i
);
416 if (value
.get(v
)) array
.push_back(v
);
426 bool get(std::map
<std::string
,T
>& dictionary
) const
428 if (!is_table()) return false;
432 slot key
= script_
[-2];
433 slot value
= script_
[-1];
434 int realIndex
= positiveIndex();
437 while (lua_next(script_
.state_
, realIndex
) != 0)
440 if (!key
.is_number() && key
.get(k
))
443 if (value
.get(v
)) dictionary
[k
] = v
;
453 * Get the value of a field from the table.
456 template <class T
, class V
>
457 bool get(T
& value
, V field
) const
459 bool ret
= push_field(field
).get(value
);
465 template <class T
, class V
>
466 void set_field(T field
, V value
)
475 lua_settable(script_
.state_
, index
);
480 void set_field(const std::string
& field
, T value
)
482 set_field(field
.c_str(), value
);
485 void set_field(const char* field
, T value
)
488 lua_setfield(script_
.state_
, index
, field
);
493 * This set method, as opposed to the others, sets the value of the
494 * actual slot. The others set table values.
510 * Replace this value with the value at the top of the stack.
515 lua_replace(script_
.state_
, index
);
520 lua_remove(script_
.state_
, index
);
525 // removes this slot, taking with it everything above it
526 script_
.pop(script_
.stack_size() - index
+ 1);
530 * Inserts the top-most value on the stack at position index,
531 * shifting other values as needed.
534 void insert_top_here()
536 lua_insert(script_
.state_
, index
);
541 * Copy the value and push the copy to the stack.
544 slot
push_copy() const
546 lua_pushvalue(script_
.state_
, index
);
547 return script_
.top();
550 slot
push_metatable() const
552 lua_getmetatable(script_
.state_
, index
);
553 return script_
.top();
556 slot
push_environment() const
558 lua_getfenv(script_
.state_
, index
);
559 return script_
.top();
563 slot
push_field() const
565 lua_gettable(script_
.state_
, index
);
566 return script_
.top();
570 slot
push_field(T index
) const
576 slot
push_field(const std::string
& name
) const
578 return push_field(name
.c_str());
580 slot
push_field(const char* name
) const
582 lua_getfield(script_
.state_
, index
, name
);
583 return script_
.top();
587 class script
& script()
592 const class script
& script() const
600 class script
& script_
;
616 static script_ptr
alloc()
618 return script_ptr(new script
);
623 if (state_
) destroy();
624 state_
= luaL_newstate();
625 registry().set_field("Script_hh_Object", (void*)this);
629 void import_standard_libraries()
631 luaL_openlibs(state_
);
634 void import_base_library()
636 lua_pushcfunction(state_
, luaopen_base
);
641 void import_package_library()
643 lua_pushcfunction(state_
, luaopen_package
);
644 push(LUA_LOADLIBNAME
);
648 void import_string_library()
650 lua_pushcfunction(state_
, luaopen_string
);
651 push(LUA_STRLIBNAME
);
655 void import_table_library()
657 lua_pushcfunction(state_
, luaopen_table
);
658 push(LUA_TABLIBNAME
);
662 void import_math_library()
664 lua_pushcfunction(state_
, luaopen_math
);
665 push(LUA_MATHLIBNAME
);
669 void import_io_library()
671 lua_pushcfunction(state_
, luaopen_io
);
676 void import_os_library()
678 lua_pushcfunction(state_
, luaopen_os
);
683 void import_debug_library()
685 lua_pushcfunction(state_
, luaopen_debug
);
691 void import_function(const std::string
& name
, const function
& function
)
694 lua_setglobal(state_
, name
.c_str());
697 status
do_string(const std::string
& commands
)
699 return status(luaL_dostring(state_
, commands
.c_str()));
702 status
do_file(const std::string
& file
)
704 return status(luaL_dofile(state_
, file
.c_str()));
709 * Thread-handling methods.
712 script
push_new_thread()
714 return script(state_
);
719 lua_pushthread(state_
);
722 status
resume(int nargs
)
724 return status(lua_resume(state_
, nargs
));
727 status
getStatus() const
729 return status(lua_status(state_
));
732 int yield(int results
)
734 return lua_yield(state_
, results
);
737 bool is_main_thread() const
739 return is_main_thread_
;
744 * Throw an error with the value at the top of the stack. This method
745 * never returns because it does a long jump. Consequently,
746 * constructed C++ objects which exist on the stack between the
747 * current frame and some lua function will not be destructed. That's
748 * not a problem for objects that only exist on the stack, but any
749 * objects that allocate memory on the heap (such as containers or
750 * strings) will leak. Therefore, you should only call this method
751 * after cleaning up such objects.
761 * Get significant values.
766 return slot(*this, globals_index
);
769 slot
registry() const
771 return slot(*this, registry_index
);
774 slot
environment() const
776 return slot(*this, environment_index
);
781 return slot(*this, stack_size());
786 * Set the size of the stack.
787 * \param size The stack size.
789 void stack_size(int size
)
791 lua_settop(state_
, size
);
795 * Get the size of the stack; this is also the index of the top-most
797 * \return The stack size.
799 int stack_size() const
801 return lua_gettop(state_
);
805 * Clear the stack, setting its size to zero.
814 * Makes sure there is at least extra more places on the stack.
815 * Returns false if space couldn't be created. Just like with the
816 * regular Lua API, you are responsible to make sure the stack is big
817 * enough to hold whatever you want to push on it. This is usually
818 * only an issue if you're pushing stuff in a loop.
820 bool checkStack(int extra
)
822 return (bool)lua_checkstack(state_
, extra
);
827 * Concatenates the top-most n slots on the stack.
829 void concatenate(int n
= 2)
831 lua_concat(state_
, n
);
836 * Push some values onto the stack.
841 lua_pushinteger(state_
, lua_Integer(value
));
845 slot
push(bool value
)
847 lua_pushboolean(state_
, int(value
));
851 slot
push(float value
)
853 lua_pushnumber(state_
, (lua_Number
)value
);
856 slot
push(double value
)
858 lua_pushnumber(state_
, (lua_Number
)value
);
862 slot
push(const std::string
& value
)
864 lua_pushlstring(state_
, value
.c_str(), value
.length());
867 slot
push(const char* value
)
869 lua_pushstring(state_
, value
);
872 slot
push(const char* value
, size_t length
)
874 lua_pushlstring(state_
, value
, length
);
878 slot
push(const function
& function
)
880 functions_
.push_back(function
);
881 lua_pushlightuserdata(state_
, (void*)&functions_
.back());
882 lua_pushcclosure(state_
, dispatch_call
, 1);
886 slot
push(void* data
)
888 lua_pushlightuserdata(state_
, data
);
898 slot
push_from_thread(script
& thread
, int n
)
900 lua_xmove(thread
.state_
, state_
, n
);
904 slot
push_code(const std::string
& file
, status
& result
)
906 result
= status(luaL_loadfile(state_
, file
.c_str()));
910 slot
push_code(const std::string
& name
,
915 result
= status(luaL_loadbuffer(state_
,
916 buffer
, size
, name
.c_str()));
920 slot
push_new_data(void*& data
, size_t size
)
922 data
= lua_newuserdata(state_
, size
);
926 slot
push_new_table(int narr
= 0, int nrec
= 0)
928 lua_createtable(state_
, narr
, nrec
);
934 * Call a function on the stack. The correct procedure is to push a
935 * function onto the stack followed by nargs arguments. This method
936 * will pop them off upon return, leaving up to nresults return values
937 * (default is any number of return values, depending on the callee).
940 status
call(int nargs
= 0, int nresults
= LUA_MULTRET
)
942 return status(lua_pcall(state_
, nargs
, nresults
, 0));
947 * Pops n values from the top of the stack.
957 * Index into the stack to get a slot.
960 slot
operator [] (int index
) const
962 return slot(*this, index
);
967 * Control over the garbage collection process.
972 lua_gc(state_
, LUA_GCCOLLECT
, 0);
975 void stop_collector()
977 lua_gc(state_
, LUA_GCSTOP
, 0);
980 void restart_collector()
982 lua_gc(state_
, LUA_GCRESTART
, 0);
985 int memory_used() const
988 return lua_gc(state_
, LUA_GCCOUNT
, 0);
991 void collect(int step
)
993 lua_gc(state_
, LUA_GCSTEP
, step
);
996 void tune_collector(int pause
, int step
)
998 lua_gc(state_
, LUA_GCSETPAUSE
, pause
);
999 lua_gc(state_
, LUA_GCSETSTEPMUL
, step
);
1005 script(lua_State
* state
) :
1006 state_(lua_newthread(state
)),
1007 is_main_thread_(false) {}
1009 static int dispatch_call(lua_State
* state
)
1011 const function
* function
= (const script::function
*)lua_touserdata(state
,
1012 lua_upvalueindex(1));
1014 lua_getfield(state
, LUA_REGISTRYINDEX
, "Script_hh_Object");
1015 script
* script
= (moof::script
*)lua_touserdata(state
, -1);
1018 return (*function
)(*script
);
1023 if (is_main_thread_
) lua_close(state_
);
1027 bool is_main_thread_
;
1028 std::list
<function
> functions_
;
1032 inline std::ostream
& operator << (std::ostream
& stream
,
1033 const script::slot
& slot
)
1042 else if (slot
.get(boolean
))
1044 if (boolean
) stream
<< "true";
1045 else stream
<< "false";
1047 else if (slot
.is_nil())
1053 stream
<< slot
.type_name() << " (" << slot
.id() << ")";
1062 #endif // _MOOF_SCRIPT_HH_
This page took 0.088805 seconds and 4 git commands to generate.