-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathLuaTable.cpp
More file actions
173 lines (161 loc) · 4.71 KB
/
LuaTable.cpp
File metadata and controls
173 lines (161 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// Author: Guillaume.Stordeur@gmail.com
// License: none, no restrictions, use at your own risk
// Date: 07/13/12
// Version 1.1
#include "LuaTable.h"
namespace LuaUtils {;
//////////////////////////////////////////////////////////////////////////////
LuaTable::LuaTable(const LuaTable &other)
{
mL = other.mL;
// copy the registry reference
if (mL && other.mRef != -1)
{
lua_rawgeti(mL.get(), LUA_REGISTRYINDEX, other.mRef);
mRef = luaL_ref(mL.get(), LUA_REGISTRYINDEX);
mName = other.mName;
}
}
//////////////////////////////////////////////////////////////////////////////
LuaTable &LuaTable::operator=(const LuaTable &other)
{
unref();
mL = other.mL;
// copy the registry reference
if (mL && other.mRef != -1)
{
lua_rawgeti(mL.get(), LUA_REGISTRYINDEX, other.mRef);
mRef = luaL_ref(mL.get(), LUA_REGISTRYINDEX);
mName = other.mName;
}
return *this;
}
//////////////////////////////////////////////////////////////////////////////
// Returns the number of int-indexed elements of the table
size_t LuaTable::getArraySize() const
{
size_t res = 0;
if (push())
{
res = lua_objlen(mL.get(), -1);
pop();
}
return res;
}
////////////////////////////////////////////////////////////////////////////////////
// Get the table at t.key
bool LuaTable::getValue(const char *key, LuaTable &res) const
{
bool ret = false;
if (push())
{
lua_getfield(mL.get(), -1, key);
char newName[100];
_snprintf(newName, 100, "%s.%s", mName.c_str(), key);
ret = res.init(mL, newName, false);
pop();
}
return ret;
}
////////////////////////////////////////////////////////////////////////////////////
// Get the table at t[i]
bool LuaTable::getValue(int i, LuaTable &res) const
{
bool ret = false;
if (push())
{
lua_rawgeti(mL.get(), -1, i);
char newName[100];
_snprintf(newName, 100, "%s[%d]", mName.c_str(), i);
ret = res.init(mL, newName, false);
pop();
}
return ret;
}
////////////////////////////////////////////////////////////////////////////////////
// Create a new table at t.key
void LuaTable::newTable(const char *key, LuaTable &res) const
{
char newName[100];
_snprintf(newName, 100, "%s.%s", mName.c_str(), key);
res.init(mL, newName, true);
setValue(key, res);
}
////////////////////////////////////////////////////////////////////////////////////
// Create a new table at t[i]
void LuaTable::newTable(int i, LuaTable &res) const
{
char newName[100];
_snprintf(newName, 100, "%s[%d]", mName.c_str(), i);
res.init(mL, newName, true);
setValue(i, res);
}
//////////////////////////////////////////////////////////////////////////////
void LuaTable::unref()
{
// Delete the reference from registry
luaL_unref(mL.get(), LUA_REGISTRYINDEX, mRef);
mRef = -1;
}
//////////////////////////////////////////////////////////////////////////////
// Init from stack index, without checking the type
void LuaTable::initFromArgument(luaStatePtr vm, const std::string &name, int arg)
{
unref();
mL = vm;
lua_pushvalue(mL.get(), arg);
// Store it in registry for later use
mRef = luaL_ref(mL.get(), LUA_REGISTRYINDEX);
mName = name;
}
//////////////////////////////////////////////////////////////////////////////
// If the create flag is true, create a new table and store a new reference to it
// Otherwise, pop Lua table from the stack and store a reference to it
// (if the top of the stack isn't a table, it gets popped anyways but no reference gets created)
bool LuaTable::init(luaStatePtr vm, const std::string &name, bool create)
{
unref();
mL = vm;
// Push new table onto the stack
if (create)
lua_newtable(mL.get());
// Or check that there's one on the stack
else if (!lua_istable(mL.get(), -1))
{
lua_pop(mL.get(), 1);
return false;
}
// Store it in registry for later use
mRef = luaL_ref(mL.get(), LUA_REGISTRYINDEX);
mName = name;
return true;
}
//////////////////////////////////////////////////////////////////////////////
bool LuaTable::push() const
{
if (mRef != -1)
{
lua_rawgeti(mL.get(), LUA_REGISTRYINDEX, mRef);
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////////
void LuaTable::pop() const
{
lua_pop(mL.get(), 1);
}
////////////////////////////////////////////////////////////////////////////////////
// Abort from current Lua C function and give the supplied message as an error message.
// It also adds at the beginning of the message the Lua file name and the line number where the error occurred, if this information is available.
// WARNING: if you call this outside of a Lua C function, it will terminate your program
void LuaTableCFunc::abortCurrentCFunc(const char *format, ...) const
{
char buf[512];
va_list args;
va_start(args, format);
vsnprintf(buf, 512, format, args);
va_end(args);
luaL_error(mL.get(), buf);
}
} // LuaUtils