From 42e43b044ffc49e3128ae59e75ce5ffd84c371be Mon Sep 17 00:00:00 2001 From: deva Date: Fri, 1 Jul 2011 10:02:42 +0000 Subject: Fixed bug in field check/creation with depth greater than 1. --- server/src/luaquerymapper.cc | 67 ++++++++++---------- server/src/luautil.cc | 143 +++++++++++++++++++++++++++++++++++++++++++ server/src/luautil.h | 13 ++++ 3 files changed, 188 insertions(+), 35 deletions(-) diff --git a/server/src/luaquerymapper.cc b/server/src/luaquerymapper.cc index 380960c..f593c28 100644 --- a/server/src/luaquerymapper.cc +++ b/server/src/luaquerymapper.cc @@ -29,35 +29,24 @@ #include #include -static bool hasField(lua_State *L, int i, std::string name) -{ - lua_getfield(L, i, name.c_str()); - bool ret = lua_isnil(L, lua_gettop(L)); - lua_pop(L, 1); - return ret; -} +#include "luautil.h" static void loadResult(lua_State *L, QueryResult &res, - std::vector group = std::vector()) + std::vector group = std::vector()) { - int grp = 0; + std::vector groups; std::vector::iterator gi = group.begin(); while(gi != group.end()) { const char *name = gi->c_str(); - printf("[%d: %s]", grp, name); fflush(stdout); - if(grp == 0) grp = LUA_GLOBALSINDEX; - if(hasField(L, grp, name)) { - lua_newtable(L); - lua_setfield(L, grp, name); - lua_getfield(L, grp, name); + if(!Pracro::testField(L, groups, name)) { + Pracro::createField(L, groups, name); } - grp = lua_gettop(L); + groups.push_back(name); gi++; } - printf("\n"); fflush(stdout); - + std::string s; std::stringstream timestamp; timestamp << res.timestamp; @@ -66,33 +55,30 @@ static void loadResult(lua_State *L, QueryResult &res, const char *name = v->first.c_str(); - if(grp == 0) grp = LUA_GLOBALSINDEX; - if(hasField(L, grp, name)) { - lua_newtable(L); - lua_setfield(L, grp, name); + if(!Pracro::testField(L, group, name)) { + Pracro::createField(L, group, name); } - int val; + int top = lua_gettop(L); + Pracro::getField(L, group, name); - lua_getfield(L, grp, name); - val = lua_gettop(L); lua_pushstring(L, v->second.c_str()); - lua_setfield(L, val, "value"); + lua_setfield(L, -2, "value"); - lua_getfield(L, grp, name); - val = lua_gettop(L); lua_pushstring(L, timestamp.str().c_str()); - lua_setfield(L, val, "timestamp"); + lua_setfield(L, -2, "timestamp"); - lua_getfield(L, grp, name); - val = lua_gettop(L); lua_pushstring(L, res.source.c_str()); - lua_setfield(L, val, "source"); + lua_setfield(L, -2, "source"); + + while(lua_gettop(L) > top) lua_pop(L, 1); v++; } - while(lua_gettop(L) > 1) lua_pop(L, 1); + while(lua_gettop(L)) lua_pop(L, 1); + + printf("< %d\n", lua_gettop(L)); fflush(stdout); std::map< std::string, QueryResult >::iterator g = res.groups.begin(); while(g != res.groups.end()) { @@ -232,7 +218,7 @@ std::string LUAQueryMapper::automap(const std::string &name) } #ifdef TEST_LUAQUERYMAPPER -//deps: exception.cc log.cc debug.cc +//deps: exception.cc log.cc debug.cc luautil.cc //cflags: -I.. ${LUA_CFLAGS} //libs:${LUA_LIBS} #include @@ -250,15 +236,26 @@ time_t now = time(NULL); res.groups["test"].groups["subtest"].source = "test app 2"; res.groups["test"].groups["subtest"].timestamp = now + 1; res.groups["test"].groups["subtest"].values["somevalue"] = "hello world!"; + res.groups["test"].groups["subtest"].groups["subsubtest"].source = "test app 3"; + res.groups["test"].groups["subtest"].groups["subsubtest"].timestamp = now + 2; + res.groups["test"].groups["subtest"].groups["subsubtest"].values["somevalue"] = "hello world!!"; LUAQueryMapper mapper; mapper.addQueryResult(res); // Test simple value forwarding with nesting - std::string luamap = "return test.subtest.somevalue.value, test.subtest.somevalue.timestamp, test.subtest.somevalue.source"; + std::string luamap = "return test.subtest.subsubtest.somevalue.value, test.subtest.subsubtest.somevalue.timestamp, test.subtest.subsubtest.somevalue.source"; Value value = mapper.map(luamap); + TEST_EQUAL_STR(value.value, "hello world!!", "Test value"); + TEST_EQUAL_INT(value.timestamp, now + 2, "Test timestamp"); + TEST_EQUAL_STR(value.source, "test app 3", "Test source"); + + luamap = "return test.subtest.somevalue.value, test.subtest.somevalue.timestamp, test.subtest.somevalue.source"; + + value = mapper.map(luamap); + TEST_EQUAL_STR(value.value, "hello world!", "Test value"); TEST_EQUAL_INT(value.timestamp, now + 1, "Test timestamp"); TEST_EQUAL_STR(value.source, "test app 2", "Test source"); diff --git a/server/src/luautil.cc b/server/src/luautil.cc index 116d219..1042d8f 100644 --- a/server/src/luautil.cc +++ b/server/src/luautil.cc @@ -217,6 +217,129 @@ int Pracro::checkParameters(lua_State *L, ...) return 0; } +void Pracro::stack(lua_State* l, const char *fmt, ...) +{ + int i; + int top = lua_gettop(l); + + va_list va; + va_start(va, fmt); + + printf("---Stack: "); + vprintf(fmt, va); + printf("---\nSize: %d\n", top); + + for (i = 1; i <= top; i++) { + int t = lua_type(l, i); + switch (t) { + case LUA_TSTRING: + printf("string: '%s'\n", lua_tostring(l, i)); + break; + case LUA_TBOOLEAN: + printf("boolean %s\n",lua_toboolean(l, i) ? "true" : "false"); + break; + case LUA_TNUMBER: + printf("number: %g\n", lua_tonumber(l, i)); + break; + default: + printf("%s\n", lua_typename(l, t)); + break; + } + printf(" "); + } + printf("\n"); + fflush(stdout); +} + +bool Pracro::hasField(lua_State *L, int i, std::string name) +{ + // stack [] + lua_getfield(L, i, name.c_str()); // stack [field|nil] + bool ret = !lua_isnil(L, lua_gettop(L)); // stack [field|nil] + lua_pop(L, 1); // stack [] + + return ret; +} + +bool Pracro::testField(lua_State *L, std::vector groups, + std::string field) +{ + int top = lua_gettop(L); + + groups.push_back(field); + + int grp = LUA_GLOBALSINDEX; + std::vector::iterator gi = groups.begin(); + while(gi != groups.end()) { + const char *name = gi->c_str(); + + if(!hasField(L, grp, name)) { + while(lua_gettop(L) > top) lua_pop(L, 1); + return false; + } + lua_getfield(L, grp, name); + + grp = lua_gettop(L); + gi++; + } + + while(lua_gettop(L) > top) lua_pop(L, 1); + + return true; +} + +bool Pracro::getField(lua_State *L, std::vector groups, + std::string field) +{ + int top = lua_gettop(L); + groups.push_back(field); + + int grp = LUA_GLOBALSINDEX; + std::vector::iterator gi = groups.begin(); + while(gi != groups.end()) { + const char *name = gi->c_str(); + + if(!hasField(L, grp, name)) { + while(lua_gettop(L) > top) lua_pop(L, 1); + return false; + } + lua_getfield(L, grp, name); + + grp = lua_gettop(L); + gi++; + } + + return true; +} + +bool Pracro::createField(lua_State *L, std::vector groups, + std::string field) +{ + int top = lua_gettop(L); + + int grp = LUA_GLOBALSINDEX; + std::vector::iterator gi = groups.begin(); + while(gi != groups.end()) { + const char *name = gi->c_str(); + + if(!hasField(L, grp, name)) { + while(lua_gettop(L) > top) lua_pop(L, 1); + return false; + } + lua_getfield(L, grp, name); + + grp = lua_gettop(L); + gi++; + } + + lua_newtable(L); + lua_setfield(L, grp, field.c_str()); + + while(lua_gettop(L) > top) lua_pop(L, 1); + + return true; +} + #ifdef TEST_LUAUTIL //deps: //cflags: $(LUA_CFLAGS) -I.. @@ -305,6 +428,26 @@ if(luaL_loadstring(L, LUAPROG_MISSING_END)) { } TEST_NOTEQUAL_INT(lua_pcall(L, 0, LUA_MULTRET, 0), 0, "Missing T_END"); +std::string src = + "foo = {}" + "foo.bar = {}" + "foo.bar.bas = {}" + "foo.bar.bas.value = 'hello'" + "print('done')"; + +luaL_loadbuffer(L, src.c_str(), src.size(), "src"); +lua_pcall(L, 0, LUA_MULTRET, 0); + +std::vector g; +g.push_back("foo"); +g.push_back("bar"); +g.push_back("bas"); +TEST_TRUE(Pracro::testField(L, g, "value"), "?"); + +TEST_TRUE(Pracro::createField(L, g, "abe"), "?"); + +TEST_TRUE(Pracro::testField(L, g, "abe"), "?"); + lua_close(L); TEST_END; diff --git a/server/src/luautil.h b/server/src/luautil.h index ebbba45..0d9d445 100644 --- a/server/src/luautil.h +++ b/server/src/luautil.h @@ -31,6 +31,7 @@ #include #include +#include namespace Pracro { @@ -76,6 +77,18 @@ namespace Pracro { // int checkParameters(lua_State *L, types_t types[]); int checkParameters(lua_State *L, ...); + bool hasField(lua_State *L, int i, std::string name); + + bool testField(lua_State *L, std::vector groups, + std::string field); + + bool getField(lua_State *L, std::vector groups, + std::string field); + + bool createField(lua_State *L, std::vector groups, + std::string field); + + void stack(lua_State* l, const char *fmt, ...); }; #endif/*__PRACRO_LUAUTIL_H__*/ -- cgit v1.2.3