]>
Dogcows Code - chaz/yoink/blob - Script.hh
553e31a0717be1b242a5e0f8a2377212f4492157
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.
46 #include <boost/bind.hpp>
47 #include <boost/function.hpp>
48 #include <boost/shared_ptr.hpp>
52 #include <Moof/Exception.hh>
53 #include <Moof/Log.hh>
60 typedef boost::shared_ptr
<Script
> ScriptP
;
65 typedef boost::function
<int(Script
&)> Function
;
71 BOOLEAN
= LUA_TBOOLEAN
,
72 LIGHTUSERDATA
= LUA_TLIGHTUSERDATA
,
76 FUNCTION
= LUA_TFUNCTION
,
77 USERDATA
= LUA_TUSERDATA
,
85 RUNTIME_ERROR
= LUA_ERRRUN
,
86 SYNTAX_ERROR
= LUA_ERRSYNTAX
,
87 MEMORY_ERROR
= LUA_ERRMEM
,
88 HANDLER_ERROR
= LUA_ERRERR
,
89 FILE_ERROR
= LUA_ERRFILE
94 REGISTRY
= LUA_REGISTRYINDEX
,
95 ENVIRONMENT
= LUA_ENVIRONINDEX
,
96 GLOBALS
= LUA_GLOBALSINDEX
100 * This is the most noticeable abstraction on top of the standard Lua API.
101 * A Value object represents a value on the stack. More specifically, it
102 * represents a position on the stack. The distinction is only important
103 * when values are moved around on the stack or if the Value represents a
104 * negative index on the stack (the value of which will change as things are
105 * pushed onto and popped from the stack).
111 * You have direct access to the index of the value on the stack being
119 * A default-constructed Value is invalid until a valid Value is
120 * assigned to it. The only method that should be called on such a
121 * Value is isValid(), otherwise chaos may ensue. In this case, the
122 * Value will be invalid even if index is manually changed to a valid
123 * index. You have to index the script itself to get a valid Value.
125 Value(lua_State
* s
= 0, int i
= 0) :
129 // check the type of the value
130 bool isBoolean() const { return (bool)lua_isboolean(state
, index
); }
131 bool isFunction() const { return (bool)lua_isfunction(state
, index
); }
132 bool isNil() const { return (bool)lua_isnil(state
, index
); }
133 bool isNone() const { return (bool)lua_isnone(state
, index
); }
134 bool isValid() const { return state
!= 0 && !isNone(); }
135 bool isNoneOrNil() const { return (bool)lua_isnoneornil(state
, index
); }
136 bool isNumber() const { return (bool)lua_isnumber(state
, index
); }
137 bool isString() const { return (bool)lua_isstring(state
, index
); }
138 bool isTable() const { return (bool)lua_istable(state
, index
); }
139 bool isThread() const { return (bool)lua_isthread(state
, index
); }
140 bool isData() const { return (bool)lua_isuserdata(state
, index
); }
141 bool isLightData() const { return (bool)lua_islightuserdata(state
, index
); }
144 * Check the value and throw and error if its the wrong type. This
145 * method never returns because it does a long jump. Consequently,
146 * constructed C++ objects which exist on the stack between the current
147 * frame and some lua function will not be destructed. That's not a
148 * problem for objects that only exist on the stack, but any objects
149 * that allocate memory on the heap (such as containers or strings) will
150 * leak. Therefore, you should only call this method after cleaning up
154 void requireType(TYPE type
) const
156 if (type
!= getType())
158 luaL_typerror(state
, index
, lua_typename(state
, type
));
162 void throwError(const char* error
)
164 luaL_argerror(state
, index
, error
);
168 Value
& requireBoolean()
170 if (!isBoolean()) luaL_typerror(state
, index
, "boolean");
173 Value
& requireNumber()
175 if (!isNumber()) luaL_typerror(state
, index
, "number");
178 Value
& requireString()
180 if (!isString()) luaL_typerror(state
, index
, "string");
183 Value
& requireTable()
185 if (!isTable()) luaL_typerror(state
, index
, "table");
188 Value
& requireFunction()
190 if (!isFunction()) luaL_typerror(state
, index
, "function");
195 if (!isData()) luaL_typerror(state
, index
, "data");
200 if (!isNil()) luaL_typerror(state
, index
, "nil");
203 Value
& requireThread()
205 if (!isThread()) luaL_typerror(state
, index
, "thread");
211 * Get the type of the value.
216 return (TYPE
)lua_type(state
, index
);
220 * Get the name of the type of the value as a string.
223 std::string
getTypeName() const
225 return std::string(luaL_typename(state
, index
));
230 * Get the length of the value according to the definition given by Lua.
233 size_t getLength() const
235 return lua_objlen(state
, index
);
238 int getRealIndex() const
240 if (index
< 0) return lua_gettop(state
) + 1 + index
;
246 * Get a pointer value (for userdata, tables, threads, and functions).
249 const void* getIdentifier() const
251 return lua_topointer(state
, index
);
255 bool operator == (const Value
& rhs
) const
257 return (bool)lua_equal(state
, index
, rhs
.index
);
259 bool operator != (const Value
& rhs
) const
261 return !(*this == rhs
);
263 bool operator < (const Value
& rhs
) const
265 return (bool)lua_lessthan(state
, index
, rhs
.index
);
267 bool operator <= (const Value
& rhs
) const
269 return *this < rhs
|| *this == rhs
;
271 bool operator > (const Value
& rhs
) const
273 return !(*this <= rhs
);
275 bool operator >= (const Value
& rhs
) const
277 return !(*this < rhs
);
279 operator bool () const
281 return (bool)lua_toboolean(state
, index
);
284 Value
& operator = (const Value
& rhs
)
293 * Convert the underlying value to a C++ type.
296 template <typename T
>
297 bool get(T
& value
) const
301 value
= (T
)lua_tointeger(state
, index
);
307 bool get(float& value
) const
311 value
= (float)lua_tonumber(state
, index
);
316 bool get(double& value
) const
320 value
= (double)lua_tonumber(state
, index
);
326 bool get(bool& value
) const
330 value
= (bool)lua_toboolean(state
, index
);
336 bool get(std::string
& value
) const
341 const char* str
= lua_tolstring(state
, index
, &size
);
342 value
.assign(str
, size
);
348 template <typename T
>
349 bool get(std::vector
<T
>& array
) const
351 if (!isTable()) return false;
355 Value
value(state
, -1);
356 int realIndex
= getRealIndex();
359 for (int i
= 1; !done
; ++i
)
361 lua_rawgeti(state
, realIndex
, i
);
364 if (value
.get(v
)) array
.push_back(v
);
373 template <typename T
>
374 bool get(std::map
<std::string
,T
>& dictionary
) const
376 if (!isTable()) return false;
380 Value
key(state
, -2);
381 Value
value(state
, -1);
382 int realIndex
= getRealIndex();
385 while (lua_next(state
, realIndex
) != 0)
388 if (!key
.isNumber() && key
.get(k
))
391 if (value
.get(v
)) dictionary
[k
] = v
;
403 * Copy the value and push the copy to the stack.
406 void pushCopy() const
408 lua_pushvalue(state
, index
);
412 * Replace this value with the value at the top of the stack.
415 void replaceWithTop()
417 lua_replace(state
, index
);
422 lua_remove(state
, index
);
426 * Inserts the top-most value on the stack at position index, shifting other
432 lua_insert(state
, index
);
436 void pushMetatable() const
438 lua_getmetatable(state
, index
);
441 void pushField() const
443 lua_gettable(state
, index
);
446 void pushField(const std::string
& name
) const
448 lua_getfield(state
, index
, name
.c_str());
459 state_(luaL_newstate())
461 lua_pushlightuserdata(state_
, this);
462 lua_setfield(state_
, LUA_REGISTRYINDEX
, "_script_obj");
467 if (isMainThread_
) lua_close(state_
);
471 static ScriptP
alloc()
473 return ScriptP(new Script
);
477 void importStandardLibraries()
479 luaL_openlibs(state_
);
482 void importFunction(const std::string
& name
, const Function
& function
)
485 lua_setglobal(state_
, name
.c_str());
489 STATUS
doString(const std::string
& commands
)
491 return (STATUS
)luaL_dostring(state_
, commands
.c_str());
494 STATUS
doFile(const std::string
& file
)
496 return (STATUS
)luaL_dofile(state_
, file
.c_str());
501 * Thread-handling methods.
504 Script
pushNewThread()
506 return Script(state_
);
511 lua_pushthread(state_
);
514 STATUS
resume(int nargs
)
516 return (STATUS
)lua_resume(state_
, nargs
);
519 STATUS
getStatus() const
521 return (STATUS
)lua_status(state_
);
524 int yield(int results
)
526 return lua_yield(state_
, results
);
529 bool isMainThread() const
531 return isMainThread_
;
536 * Throw an error with the value at the top of the stack. This method never
537 * returns because it does a long jump. Consequently, constructed C++
538 * objects which exist on the stack between the current frame and some lua
539 * function will not be destructed. That's not a problem for objects that
540 * only exist on the stack, but any objects that allocate memory on the heap
541 * (such as containers or strings) will leak. Therefore, you should only
542 * call this method after cleaning up such objects.
552 * Get significant values.
555 Value
getGlobalTable() const
557 return Value(state_
, GLOBALS
);
560 Value
getRegistryTable() const
562 return Value(state_
, REGISTRY
);
565 Value
getEnvironmentTable() const
567 return Value(state_
, ENVIRONMENT
);
572 return Value(state_
, lua_gettop(state_
));
576 * Get the size of the stack; this is also the index of the top-most value.
581 return lua_gettop(state_
);
584 void setSize(int size
)
586 lua_settop(state_
, size
);
596 * Makes sure there is at least extra more places on the stack. Returns
597 * false if space couldn't be created. Just like with the regular Lua API,
598 * you are responsible to make sure the stack is big enough to hold whatever
599 * you want to push on it. This is usually only an issue if you're pushing
603 bool checkStack(int extra
)
605 return (bool)lua_checkstack(state_
, extra
);
610 * Concatenates the top-most n values on the stack.
615 lua_concat(state_
, n
);
620 * Push some values onto the stack.
623 template <typename T
>
626 lua_pushinteger(state_
, lua_Integer(value
));
629 void push(bool value
)
631 lua_pushboolean(state_
, int(value
));
634 void push(float value
)
636 lua_pushnumber(state_
, (lua_Number
)value
);
638 void push(double value
)
640 lua_pushnumber(state_
, (lua_Number
)value
);
643 void push(const std::string
& value
)
645 lua_pushlstring(state_
, value
.c_str(), value
.length());
647 void push(const char* value
)
649 lua_pushstring(state_
, value
);
651 void push(const char* value
, size_t length
)
653 lua_pushlstring(state_
, value
, length
);
656 void push(const Function
& function
)
658 functions_
.push_back(function
);
660 lua_pushlightuserdata(state_
, (void*)&functions_
.back());
661 lua_pushcclosure(state_
, dispatchCall
, 1);
664 void push(void* data
)
666 lua_pushlightuserdata(state_
, data
);
674 void pushFromThread(Script
& thread
, int n
)
676 lua_xmove(thread
.state_
, state_
, n
);
679 STATUS
pushCode(const std::string
& filename
)
681 return (STATUS
)luaL_loadfile(state_
, filename
.c_str());
684 STATUS
pushCode(const std::string
& name
, const char* buffer
, size_t size
)
686 return (STATUS
)luaL_loadbuffer(state_
, buffer
, size
, name
.c_str());
689 void* pushNewData(size_t size
)
691 return lua_newuserdata(state_
, size
);
696 lua_newtable(state_
);
701 * Call a function on the stack. The correct procedure is to push a
702 * function onto the stack followed by nargs arguments. This method will
703 * pop them off upon return, leaving up to nresults return values (default
704 * is any number of return values, depending on the callee).
707 STATUS
call(int nargs
, int nresults
= LUA_MULTRET
)
709 return (STATUS
)lua_pcall(state_
, nargs
, nresults
, 0);
714 * Pops n values from the top of the stack.
724 * Index into the stack to get a Value.
727 Value
operator [] (int index
) const
729 return Value(state_
, index
);
734 * Getting and setting fields of a table.
737 void get(const std::string
& field
, int index
= GLOBALS
) const
739 lua_getfield(state_
, index
, field
.c_str());
742 void set(const std::string
& field
, int index
= GLOBALS
)
744 lua_setfield(state_
, index
, field
.c_str());
749 * Control over the garbage collection process.
754 lua_gc(state_
, LUA_GCCOLLECT
, 0);
759 lua_gc(state_
, LUA_GCSTOP
, 0);
762 void restartCollector()
764 lua_gc(state_
, LUA_GCRESTART
, 0);
767 int getUsedMemory() const
770 return lua_gc(state_
, LUA_GCCOUNT
, 0);
773 void collectStep(int step
)
775 lua_gc(state_
, LUA_GCSTEP
, step
);
778 void tuneCollector(int pause
, int step
)
780 lua_gc(state_
, LUA_GCSETPAUSE
, pause
);
781 lua_gc(state_
, LUA_GCSETSTEPMUL
, step
);
786 struct Exception
: public Mf::Exception
788 explicit Exception(unsigned error
) :
789 Mf::Exception(error
) {}
800 Script(lua_State
* state
) :
801 state_(lua_newthread(state
)),
802 isMainThread_(false) {}
804 static int dispatchCall(lua_State
* state
)
806 const Function
* function
= (const Function
*)lua_touserdata(state
,
807 lua_upvalueindex(1));
809 lua_getfield(state
, LUA_REGISTRYINDEX
, "_script_obj");
810 Script
* script
= (Script
*)lua_touserdata(state
, -1);
813 return (*function
)(*script
);
818 std::list
<Function
> functions_
;
824 #endif // _MOOF_SCRIPT_HH_
826 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.067976 seconds and 3 git commands to generate.