]>
Dogcows Code - chaz/yoink/blob - src/Moof/Script.hh
f954e583488a786e2740c7042a4ab89782697577
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 * Get the type of the value.
149 return (TYPE
)lua_type(state
, index
);
153 * Get the name of the type of the value as a string.
156 std::string
getTypeName() const
158 return std::string(lua_typename(state
, (int)getType()));
163 * Get the length of the value according to the definition given by Lua.
166 size_t getLength() const
168 return lua_objlen(state
, index
);
171 int getRealIndex() const
173 if (index
< 0) return lua_gettop(state
) + 1 + index
;
179 * Get a pointer value (for userdata, tables, threads, and functions).
182 const void* getIdentifier() const
184 return lua_topointer(state
, index
);
188 bool operator == (const Value
& rhs
) const
190 return (bool)lua_equal(state
, index
, rhs
.index
);
192 bool operator != (const Value
& rhs
) const
194 return !(*this == rhs
);
196 bool operator < (const Value
& rhs
) const
198 return (bool)lua_lessthan(state
, index
, rhs
.index
);
200 bool operator <= (const Value
& rhs
) const
202 return *this < rhs
|| *this == rhs
;
204 bool operator > (const Value
& rhs
) const
206 return !(*this <= rhs
);
208 bool operator >= (const Value
& rhs
) const
210 return !(*this < rhs
);
212 operator bool () const
214 return (bool)lua_toboolean(state
, index
);
217 Value
& operator = (const Value
& rhs
)
226 * Convert the underlying value to a C++ type.
229 template <typename T
>
230 bool get(T
& value
) const
234 value
= (T
)lua_tointeger(state
, index
);
240 bool get(float& value
) const
244 value
= (float)lua_tonumber(state
, index
);
249 bool get(double& value
) const
253 value
= (double)lua_tonumber(state
, index
);
259 bool get(bool& value
) const
263 value
= (bool)lua_toboolean(state
, index
);
269 bool get(std::string
& value
) const
274 const char* str
= lua_tolstring(state
, index
, &size
);
275 value
.assign(str
, size
);
281 template <typename T
>
282 bool get(std::vector
<T
>& array
) const
284 if (!isTable()) return false;
288 Value
value(state
, -1);
289 int realIndex
= getRealIndex();
292 for (int i
= 1; !done
; ++i
)
294 lua_rawgeti(state
, realIndex
, i
);
297 if (value
.get(v
)) array
.push_back(v
);
306 template <typename T
>
307 bool get(std::map
<std::string
,T
>& dictionary
) const
309 if (!isTable()) return false;
313 Value
key(state
, -2);
314 Value
value(state
, -1);
315 int realIndex
= getRealIndex();
318 while (lua_next(state
, realIndex
) != 0)
321 if (!key
.isNumber() && key
.get(k
))
324 if (value
.get(v
)) dictionary
[k
] = v
;
336 * Copy the value and push the copy to the stack.
339 void pushCopy() const
341 lua_pushvalue(state
, index
);
345 * Replace this value with the value at the top of the stack.
348 void replaceWithTop()
350 lua_replace(state
, index
);
355 lua_remove(state
, index
);
359 * Inserts the top-most value on the stack at position index, shifting other
365 lua_insert(state
, index
);
369 void pushMetatable() const
371 lua_getmetatable(state
, index
);
374 void pushField() const
376 lua_gettable(state
, index
);
379 void pushField(const std::string
& name
) const
381 lua_getfield(state
, index
, name
.c_str());
392 state_(luaL_newstate())
394 lua_pushlightuserdata(state_
, this);
395 lua_setfield(state_
, LUA_REGISTRYINDEX
, "_script_obj");
400 if (isMainThread_
) lua_close(state_
);
404 static ScriptP
alloc()
406 return ScriptP(new Script
);
410 void importStandardLibraries()
412 luaL_openlibs(state_
);
415 void importFunction(const std::string
& name
, const Function
& function
)
418 lua_setglobal(state_
, name
.c_str());
422 STATUS
doString(const std::string
& commands
)
424 return (STATUS
)luaL_dostring(state_
, commands
.c_str());
427 STATUS
doFile(const std::string
& file
)
429 return (STATUS
)luaL_dofile(state_
, file
.c_str());
434 * Thread-handling methods.
437 Script
pushNewThread()
439 return Script(state_
);
444 lua_pushthread(state_
);
447 STATUS
resume(int nargs
)
449 return (STATUS
)lua_resume(state_
, nargs
);
452 STATUS
getStatus() const
454 return (STATUS
)lua_status(state_
);
457 int yield(int results
)
459 return lua_yield(state_
, results
);
462 bool isMainThread() const
464 return isMainThread_
;
469 * Get significant values.
472 Value
getGlobalTable() const
474 return Value(state_
, GLOBALS
);
477 Value
getRegistryTable() const
479 return Value(state_
, REGISTRY
);
482 Value
getEnvironmentTable() const
484 return Value(state_
, ENVIRONMENT
);
489 return Value(state_
, lua_gettop(state_
));
493 * Get the size of the stack; this is also the index of the top-most value.
498 return lua_gettop(state_
);
501 void setSize(int size
)
503 lua_settop(state_
, size
);
513 * Makes sure there is at least extra more places on the stack. Returns
514 * false if space couldn't be created. Just like with the regular Lua API,
515 * you are responsible to make sure the stack is big enough to hold whatever
516 * you want to push on it. This is usually only an issue if you're pushing
520 bool checkStack(int extra
)
522 return (bool)lua_checkstack(state_
, extra
);
527 * Concatenates the top-most n values on the stack.
532 lua_concat(state_
, n
);
537 * Push some values onto the stack.
540 template <typename T
>
543 lua_pushinteger(state_
, lua_Integer(value
));
546 void push(bool value
)
548 lua_pushboolean(state_
, int(value
));
551 void push(float value
)
553 lua_pushnumber(state_
, (lua_Number
)value
);
555 void push(double value
)
557 lua_pushnumber(state_
, (lua_Number
)value
);
560 void push(const std::string
& value
)
562 lua_pushlstring(state_
, value
.c_str(), value
.length());
564 void push(const char* value
, size_t length
)
566 lua_pushlstring(state_
, value
, length
);
569 void push(const Function
& function
)
571 functions_
.push_back(function
);
573 lua_pushlightuserdata(state_
, (void*)&functions_
.back());
574 lua_pushcclosure(state_
, dispatchCall
, 1);
577 void push(void* data
)
579 lua_pushlightuserdata(state_
, data
);
587 void pushFromThread(Script
& thread
, int n
)
589 lua_xmove(thread
.state_
, state_
, n
);
592 STATUS
pushCode(const std::string
& filename
)
594 return (STATUS
)luaL_loadfile(state_
, filename
.c_str());
597 STATUS
pushCode(const std::string
& name
, const char* buffer
, size_t size
)
599 return (STATUS
)luaL_loadbuffer(state_
, buffer
, size
, name
.c_str());
602 void* pushNewData(size_t size
)
604 return lua_newuserdata(state_
, size
);
609 lua_newtable(state_
);
614 * Call a function on the stack. The correct procedure is to push a
615 * function onto the stack followed by nargs arguments. This method will
616 * pop them off upon return, leaving up to nresults return values (default
617 * is any number of return values, depending on the callee).
620 STATUS
call(int nargs
, int nresults
= LUA_MULTRET
)
622 return (STATUS
)lua_pcall(state_
, nargs
, nresults
, 0);
627 * Pops n values from the top of the stack.
637 * Index into the stack to get a Value.
640 Value
operator [] (int index
) const
642 return Value(state_
, index
);
647 * Getting and setting fields of a table.
650 void get(const std::string
& field
, int index
= GLOBALS
) const
652 lua_getfield(state_
, index
, field
.c_str());
655 void set(const std::string
& field
, int index
= GLOBALS
)
657 lua_setfield(state_
, index
, field
.c_str());
662 * Control over the garbage collection process.
667 lua_gc(state_
, LUA_GCCOLLECT
, 0);
672 lua_gc(state_
, LUA_GCSTOP
, 0);
675 void restartCollector()
677 lua_gc(state_
, LUA_GCRESTART
, 0);
680 int getUsedMemory() const
683 return lua_gc(state_
, LUA_GCCOUNT
, 0);
686 void collectStep(int step
)
688 lua_gc(state_
, LUA_GCSTEP
, step
);
691 void tuneCollector(int pause
, int step
)
693 lua_gc(state_
, LUA_GCSETPAUSE
, pause
);
694 lua_gc(state_
, LUA_GCSETSTEPMUL
, step
);
699 struct Exception
: public Mf::Exception
701 explicit Exception(unsigned error
) :
702 Mf::Exception(error
) {}
713 Script(lua_State
* state
) :
714 state_(lua_newthread(state
)),
715 isMainThread_(false) {}
717 static int dispatchCall(lua_State
* state
)
719 const Function
* function
= (const Function
*)lua_touserdata(state
,
720 lua_upvalueindex(1));
722 lua_getfield(state
, LUA_REGISTRYINDEX
, "_script_obj");
723 Script
* script
= (Script
*)lua_touserdata(state
, -1);
726 return (*function
)(*script
);
731 std::list
<Function
> functions_
;
737 #endif // _MOOF_SCRIPT_HH_
739 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.075236 seconds and 4 git commands to generate.