Some more error checking for class names and tangible IDs
This commit is contained in:
@@ -10,6 +10,10 @@ LuaSpecial LuaRegistry(LUA_REGISTRYINDEX);
|
|||||||
LuaNilMarker LuaNil;
|
LuaNilMarker LuaNil;
|
||||||
LuaNewTableMarker LuaNewTable;
|
LuaNewTableMarker LuaNewTable;
|
||||||
|
|
||||||
|
inline bool ascii_islower(char c) { return (c >= 'a') && (c <= 'z'); }
|
||||||
|
inline bool ascii_isupper(char c) { return (c >= 'A') && (c <= 'Z'); }
|
||||||
|
inline bool ascii_isdigit(char c) { return (c >= '0') && (c <= '9'); }
|
||||||
|
|
||||||
LuaFunctionReg::LuaFunctionReg(const char *n, const char *a, const char *d, bool s, lua_CFunction f) {
|
LuaFunctionReg::LuaFunctionReg(const char *n, const char *a, const char *d, bool s, lua_CFunction f) {
|
||||||
name_ = n;
|
name_ = n;
|
||||||
args_ = a;
|
args_ = a;
|
||||||
@@ -220,12 +224,30 @@ lua_State *LuaCoreStack::newthread(LuaSlot target) const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LuaCoreStack::validclassname(std::string_view cname) {
|
bool LuaCoreStack::valididentifier(std::string_view str) {
|
||||||
if (cname.empty()) return false;
|
if (str.size() == 0) return false;
|
||||||
if (cname == "_G") return false;
|
char c=str[0];
|
||||||
|
if ((!ascii_islower(c)) && (!ascii_isupper(c)) && (c!='_')) return false;
|
||||||
|
for (int i = 1; i < int(str.size()); i++) {
|
||||||
|
char c = str[i];
|
||||||
|
if ((!ascii_islower(c)) && (!ascii_isupper(c)) && (!ascii_isdigit(c)) && (c!='_')) return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LuaCoreStack::validint64(int64_t value) {
|
||||||
|
return (value <= MAXINT) && (value >= -MAXINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LuaCoreStack::validpositiveint64(int64_t value) {
|
||||||
|
return (value <= MAXINT) && (value >= 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LuaCoreStack::validclassname(std::string_view cname) {
|
||||||
|
if (cname == "_G") return false;
|
||||||
|
return valididentifier(cname);
|
||||||
|
}
|
||||||
|
|
||||||
bool LuaCoreStack::validclassname(LuaSlot slot) const {
|
bool LuaCoreStack::validclassname(LuaSlot slot) const {
|
||||||
if (!isstring(slot)) return false;
|
if (!isstring(slot)) return false;
|
||||||
return validclassname(ckstring(slot));
|
return validclassname(ckstring(slot));
|
||||||
@@ -352,6 +374,8 @@ void LuaCoreStack::makeclass(LuaSlot tab, std::string_view name) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LuaCoreStack::maketan(LuaSlot tab, int64_t id) const {
|
void LuaCoreStack::maketan(LuaSlot tab, int64_t id) const {
|
||||||
|
assert(validpositiveint64(id));
|
||||||
|
|
||||||
LuaVar tangibles, metatab;
|
LuaVar tangibles, metatab;
|
||||||
LuaExtStack LS(L_, tangibles, metatab);
|
LuaExtStack LS(L_, tangibles, metatab);
|
||||||
|
|
||||||
@@ -412,6 +436,20 @@ int64_t LuaCoreStack::tanid(LuaSlot tab) const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LuaCoreStack::tangetclass(LuaSlot classobj, LuaSlot tab) {
|
||||||
|
if (istable(tab) && (gettabletype(tab) == LUA_TT_TANGIBLE) && lua_getmetatable(L_, tab.index())) {
|
||||||
|
lua_pushstring(L_, "__index");
|
||||||
|
lua_rawget(L_, -2);
|
||||||
|
lua_replace(L_, classobj);
|
||||||
|
lua_pop(L_, 1);
|
||||||
|
if (istable(classobj) && (gettabletype(classobj) == LUA_TT_CLASS)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set(classobj, LuaNil);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool LuaCoreStack::issortablekey(LuaSlot s) const {
|
bool LuaCoreStack::issortablekey(LuaSlot s) const {
|
||||||
int type = lua_type(L_, s);
|
int type = lua_type(L_, s);
|
||||||
return (type == LUA_TBOOLEAN) || (type == LUA_TNUMBER) || (type == LUA_TSTRING);
|
return (type == LUA_TBOOLEAN) || (type == LUA_TNUMBER) || (type == LUA_TSTRING);
|
||||||
|
|||||||
@@ -417,6 +417,15 @@ public:
|
|||||||
|
|
||||||
int next(LuaSlot tab, LuaSlot key, LuaSlot value) const;
|
int next(LuaSlot tab, LuaSlot key, LuaSlot value) const;
|
||||||
|
|
||||||
|
// Return true if the string is a valid lua identifier.
|
||||||
|
static bool valididentifier(std::string_view id);
|
||||||
|
|
||||||
|
// Return true if the int64 can be stored losslessly in a lua_Number.
|
||||||
|
static bool validint64(int64_t value);
|
||||||
|
|
||||||
|
// Return true if the int64 is storable in lua and is positive.
|
||||||
|
static bool validpositiveint64(int64_t value);
|
||||||
|
|
||||||
// Return true if the classname is legal.
|
// Return true if the classname is legal.
|
||||||
bool validclassname(LuaSlot value) const;
|
bool validclassname(LuaSlot value) const;
|
||||||
static bool validclassname(std::string_view cname);
|
static bool validclassname(std::string_view cname);
|
||||||
@@ -446,6 +455,9 @@ public:
|
|||||||
// stub into a full blown tangible, and World::tangible_delete to turn
|
// stub into a full blown tangible, and World::tangible_delete to turn
|
||||||
// a full-blown tangible back into a stub. A stub doesn't have a
|
// a full-blown tangible back into a stub. A stub doesn't have a
|
||||||
// class or a thread table.
|
// class or a thread table.
|
||||||
|
//
|
||||||
|
// Assert-fails if the tangible ID is not a validpositiveint64.
|
||||||
|
//
|
||||||
void maketan(LuaSlot tab, int64_t id) const;
|
void maketan(LuaSlot tab, int64_t id) const;
|
||||||
|
|
||||||
// Return true if a tangible is empty (deleted or not yet created).
|
// Return true if a tangible is empty (deleted or not yet created).
|
||||||
@@ -454,6 +466,9 @@ public:
|
|||||||
// Get the ID of a tangible.
|
// Get the ID of a tangible.
|
||||||
int64_t tanid(LuaSlot tab) const;
|
int64_t tanid(LuaSlot tab) const;
|
||||||
|
|
||||||
|
// Get the class of a tangible.
|
||||||
|
bool tangetclass(LuaSlot classobj, LuaSlot tan);
|
||||||
|
|
||||||
// Return true if the value is a sortable key (string, number, or boolean).
|
// Return true if the value is a sortable key (string, number, or boolean).
|
||||||
bool issortablekey(LuaSlot s) const;
|
bool issortablekey(LuaSlot s) const;
|
||||||
|
|
||||||
|
|||||||
@@ -80,11 +80,19 @@ class Deserializer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case LUA_TT_TANGIBLE: {
|
case LUA_TT_TANGIBLE: {
|
||||||
LS_.maketan(target, sb_->read_int64());
|
int64_t tanid = sb_->read_int64();
|
||||||
|
if (!LS_.validpositiveint64(tanid)) {
|
||||||
|
throw DeserializeError();
|
||||||
|
}
|
||||||
|
LS_.maketan(target, tanid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case LUA_TT_CLASS: {
|
case LUA_TT_CLASS: {
|
||||||
LS_.makeclass(target, sb_->read_string());
|
eng::string name = sb_->read_string();
|
||||||
|
if (!LS_.validclassname(name)) {
|
||||||
|
throw DeserializeError();
|
||||||
|
}
|
||||||
|
LS_.makeclass(target, name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case LUA_PK_REFERENCE: {
|
case LUA_PK_REFERENCE: {
|
||||||
|
|||||||
@@ -21,9 +21,6 @@ LuaDefine(makeclass, "classname", "create a class if it doesn't already exist")
|
|||||||
LuaArg classname;
|
LuaArg classname;
|
||||||
LuaRet classtab;
|
LuaRet classtab;
|
||||||
LuaDefStack LS(L, classname, classtab);
|
LuaDefStack LS(L, classname, classtab);
|
||||||
if (!LS.isstring(classname)) {
|
|
||||||
luaL_error(L, "class name must be a string");
|
|
||||||
}
|
|
||||||
if (!LS.validclassname(classname)) {
|
if (!LS.validclassname(classname)) {
|
||||||
luaL_error(L, "invalid class name: %s", LS.ckstring(classname).c_str());
|
luaL_error(L, "invalid class name: %s", LS.ckstring(classname).c_str());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -178,14 +178,7 @@ int common_prefix_length(string_view a, string_view b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool is_lua_id(string_view str) {
|
bool is_lua_id(string_view str) {
|
||||||
if (str.size() == 0) return false;
|
return LuaCoreStack::valididentifier(str);
|
||||||
char c=str[0];
|
|
||||||
if ((!ascii_isalpha(c)) && (c!='_')) return false;
|
|
||||||
for (int i = 1; i < int(str.size()); i++) {
|
|
||||||
char c = str[i];
|
|
||||||
if ((!ascii_isalpha(c)) && (!ascii_isdigit(c)) && (c!='_')) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_lua_comment(string_view s) {
|
bool is_lua_comment(string_view s) {
|
||||||
|
|||||||
@@ -227,13 +227,12 @@ LuaDefine(tangible_getclass, "tan",
|
|||||||
"|The return value is a string, the class name, not"
|
"|The return value is a string, the class name, not"
|
||||||
"|the class table.") {
|
"|the class table.") {
|
||||||
LuaArg tanobj;
|
LuaArg tanobj;
|
||||||
LuaVar mt, classtab;
|
LuaVar classtab;
|
||||||
LuaRet classname;
|
LuaRet classname;
|
||||||
LuaDefStack LS(L, tanobj, mt, classtab, classname);
|
LuaDefStack LS(L, tanobj, classtab, classname);
|
||||||
World *w = World::fetch_global_pointer(L);
|
World *w = World::fetch_global_pointer(L);
|
||||||
w->tangible_get(LS, tanobj, false);
|
w->tangible_get(LS, tanobj, false);
|
||||||
LS.getmetatable(mt, tanobj);
|
LS.tangetclass(classtab, tanobj);
|
||||||
LS.rawget(classtab, mt, "__index");
|
|
||||||
eng::string name = LS.classname(classtab);
|
eng::string name = LS.classname(classtab);
|
||||||
if (name == "") {
|
if (name == "") {
|
||||||
LS.set(classname, LuaNil);
|
LS.set(classname, LuaNil);
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ Tangible *World::tangible_get(const LuaCoreStack &LS, LuaSlot tab, bool allowdel
|
|||||||
}
|
}
|
||||||
|
|
||||||
Tangible *World::tangible_make(const LuaCoreStack &LS0, LuaSlot database, int64_t id) {
|
Tangible *World::tangible_make(const LuaCoreStack &LS0, LuaSlot database, int64_t id) {
|
||||||
assert(id != 0);
|
assert(LS0.validpositiveint64(id));
|
||||||
LuaVar metatab;
|
LuaVar metatab;
|
||||||
LuaExtStack LS(LS0.state(), metatab);
|
LuaExtStack LS(LS0.state(), metatab);
|
||||||
|
|
||||||
|
|||||||
@@ -58,11 +58,17 @@ eng::string World::tangible_ids_debug_string() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
eng::string World::tangibles_near_debug_string(int64_t actor, int64_t distance) {
|
eng::string World::tangibles_near_debug_string(int64_t actor, int64_t distance) {
|
||||||
|
assert(stack_is_clear());
|
||||||
|
lua_State *L = state();
|
||||||
|
LuaVar tangibles, database, mt;
|
||||||
|
LuaExtStack LS(L, tangibles, database);
|
||||||
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
||||||
eng::ostringstream result;
|
eng::ostringstream result;
|
||||||
util::IdVector tans;
|
util::IdVector tans;
|
||||||
get_near(actor, distance, true, false, true, &tans);
|
get_near(actor, distance, true, false, true, &tans);
|
||||||
for (int64_t id : tans) {
|
for (int64_t id : tans) {
|
||||||
const Tangible *tan = tangible_get(id);
|
const Tangible *tan = tangible_get(id);
|
||||||
|
LS.rawget(database, tangibles, id);
|
||||||
AnimState state = tan->anim_queue_.get_final_everything();
|
AnimState state = tan->anim_queue_.get_final_everything();
|
||||||
result << id << ": " << state.debug_string() << std::endl;
|
result << id << ": " << state.debug_string() << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user