Repair buggy error-handling in makeclass/getclass
This commit is contained in:
@@ -188,66 +188,142 @@ lua_State *LuaStack::newthread(LuaSlot target) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
void LuaStack::getclass(LuaSlot classtab, LuaSlot classname) const {
|
||||
bool LuaStack::validclassname(const std::string &cname) {
|
||||
if (cname.empty()) return false;
|
||||
if (cname == "_G") return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaStack::validclassname(LuaSlot slot) const {
|
||||
if (!isstring(slot)) return false;
|
||||
return validclassname(ckstring(slot));
|
||||
}
|
||||
|
||||
std::string LuaStack::classname(LuaSlot tab) const {
|
||||
std::string result;
|
||||
if (istable(tab)) {
|
||||
lua_pushstring(L_, "__class");
|
||||
lua_rawget(L_, tab);
|
||||
if (lua_type(L_, -1) == LUA_TSTRING) {
|
||||
lua_pushglobaltable(L_); // cname table
|
||||
lua_pushvalue(L_, -2); // cname table cname
|
||||
lua_rawget(L_, -2); // cname table ctab
|
||||
if (lua_rawequal(L_, -1, tab)) {
|
||||
size_t len;
|
||||
const char *s = lua_tolstring(L_, -3, &len);
|
||||
result = std::string(s, len);
|
||||
if (!validclassname(result)) {
|
||||
result = "";
|
||||
}
|
||||
}
|
||||
lua_pop(L_, 3);
|
||||
} else {
|
||||
lua_pop(L_, 1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string LuaStack::getclass(LuaSlot classtab, LuaSlot classname) const {
|
||||
lua_checkstack(L_, 20);
|
||||
LuaVar globtab, cname;
|
||||
LuaStack LS(L_, globtab, cname);
|
||||
|
||||
if (!LS.isstring(classname)) {
|
||||
luaL_error(L_, "Not a class name: %s", lua_tostring(L_, classname));
|
||||
}
|
||||
|
||||
// Convert class name to a table.
|
||||
if (LS.rawequal(classname, "_G")) {
|
||||
luaL_error(L_, "_G is explicitly not allowed as a class name");
|
||||
}
|
||||
LS.getglobaltable(globtab);
|
||||
LS.rawget(classtab, globtab, classname);
|
||||
if (!LS.istable(classtab)) {
|
||||
luaL_error(L_, "Not a class: %s", lua_tostring(L_, classname));
|
||||
}
|
||||
LS.rawget(cname, classtab, "__class");
|
||||
if (!LS.rawequal(cname, classname)) {
|
||||
luaL_error(L_, "Not a class: %s", lua_tostring(L_, classname));
|
||||
}
|
||||
|
||||
// OK, we're done.
|
||||
LS.result();
|
||||
if (LS.isstring(classname)) {
|
||||
if (!validclassname(LS.ckstring(classname))) {
|
||||
std::string err = "Not allowed as a class name: " + LS.ckstring(classname);
|
||||
LS.result();
|
||||
return err;
|
||||
}
|
||||
LS.rawget(classtab, globtab, classname);
|
||||
if (!LS.istable(classtab)) {
|
||||
std::string err = "Not a class: " + LS.ckstring(classname);
|
||||
LS.result();
|
||||
return err;
|
||||
}
|
||||
LS.rawget(cname, classtab, "__class");
|
||||
if (!LS.rawequal(cname, classname)) {
|
||||
std::string err = "Not a valid class: " + LS.ckstring(classname);
|
||||
LS.result();
|
||||
return err;
|
||||
}
|
||||
LS.result();
|
||||
return "";
|
||||
} else if (LS.istable(classname)) {
|
||||
LS.rawget(cname, classname, "__class");
|
||||
if (!LS.isstring(cname)) {
|
||||
std::string err = "Table is not a class.";
|
||||
LS.result();
|
||||
return err;
|
||||
}
|
||||
if (!validclassname(LS.ckstring(cname))) {
|
||||
std::string err = "Not allowed as a class name: " + LS.ckstring(cname);
|
||||
LS.result();
|
||||
return err;
|
||||
}
|
||||
LS.rawget(classtab, globtab, cname);
|
||||
if (!LS.rawequal(classtab, classname)) {
|
||||
std::string err = "Not a valid class: " + LS.ckstring(cname);
|
||||
LS.result();
|
||||
return err;
|
||||
}
|
||||
LS.result();
|
||||
return "";
|
||||
} else {
|
||||
std::string err = "getclass expects a string or a classtab";
|
||||
LS.result();
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
std::string LuaStack::getclass(LuaSlot tab, const char *name) const {
|
||||
push_any_value(name);
|
||||
LuaSpecial classname(lua_gettop(L_));
|
||||
std::string err = getclass(tab, classname);
|
||||
lua_pop(L_, 1);
|
||||
return err;
|
||||
}
|
||||
|
||||
std::string LuaStack::getclass(LuaSlot tab, const std::string &name) const {
|
||||
push_any_value(name);
|
||||
LuaSpecial classname(lua_gettop(L_));
|
||||
std::string err = getclass(tab, classname);
|
||||
lua_pop(L_, 1);
|
||||
return err;
|
||||
}
|
||||
|
||||
void LuaStack::makeclass(LuaSlot classtab, LuaSlot classname) const {
|
||||
lua_checkstack(L_, 20);
|
||||
LuaVar globtab;
|
||||
LuaStack LS(L_, globtab);
|
||||
LuaVar globtab, cname;
|
||||
LuaStack LS(L_, globtab, cname);
|
||||
|
||||
// Validate the class name.
|
||||
if (!LS.isstring(classname)) {
|
||||
luaL_error(L_, "Not a class name: %s", lua_tostring(L_, classname));
|
||||
}
|
||||
if (LS.rawequal(classname, "_G")) {
|
||||
luaL_error(L_, "_G is explicitly not allowed as a class name");
|
||||
}
|
||||
|
||||
assert(LS.validclassname(classname));
|
||||
|
||||
// Fetch the global environment from the registry.
|
||||
LS.getglobaltable(globtab);
|
||||
|
||||
// Get the classtab from the global environment.
|
||||
// Create it if it doesn't exist.
|
||||
LS.rawget(classtab, globtab, classname);
|
||||
if (LS.isnil(classtab)) {
|
||||
|
||||
// Make sure we're not reusing a table that isn't a class.
|
||||
if (LS.istable(classtab)) {
|
||||
LS.rawget(cname, classtab, "__class");
|
||||
} else {
|
||||
LS.set(cname, LuaNil);
|
||||
}
|
||||
|
||||
// Make a new table if necessary.
|
||||
if (!LS.rawequal(cname, classname)) {
|
||||
LS.newtable(classtab);
|
||||
LS.rawset(globtab, classname, classtab);
|
||||
LS.rawset(classtab, "__class", classname);
|
||||
}
|
||||
|
||||
// If the name isn't bound to a table, abort.
|
||||
if (!LS.istable(classtab)) {
|
||||
luaL_error(L_, "%s is not a class", ckstring(classname).c_str());
|
||||
}
|
||||
|
||||
|
||||
// Repair the special fields.
|
||||
LS.settabletype(classtab, LUA_TT_CLASS);
|
||||
LS.rawset(classtab, "__index", classtab);
|
||||
LS.rawset(classtab, "__class", classname);
|
||||
|
||||
// Put the stack back.
|
||||
LS.result();
|
||||
@@ -267,27 +343,6 @@ void LuaStack::makeclass(LuaSlot tab, const std::string &name) const {
|
||||
lua_pop(L_, 1);
|
||||
}
|
||||
|
||||
std::string LuaStack::classname(LuaSlot tab) const {
|
||||
std::string result;
|
||||
if (istable(tab)) {
|
||||
lua_pushstring(L_, "__class");
|
||||
lua_rawget(L_, tab);
|
||||
if (lua_type(L_, -1) == LUA_TSTRING) {
|
||||
lua_pushglobaltable(L_); // cname table
|
||||
lua_pushvalue(L_, -2); // cname table cname
|
||||
lua_rawget(L_, -2); // cname table ctab
|
||||
if (lua_rawequal(L_, -1, tab)) {
|
||||
size_t len;
|
||||
const char *s = lua_tolstring(L_, -3, &len);
|
||||
result = std::string(s, len);
|
||||
}
|
||||
lua_pop(L_, 3);
|
||||
} else {
|
||||
lua_pop(L_, 1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t LuaStack::tanid(LuaSlot tab) const {
|
||||
int64_t result = 0;
|
||||
|
||||
Reference in New Issue
Block a user