LUALIB_API int luaopen_hiredis(lua_State * L) { /* * Register module */ luaL_register(L, "hiredis", E); /* * Register module information */ lua_pushliteral(L, LUAHIREDIS_VERSION); lua_setfield(L, -2, "_VERSION"); lua_pushliteral(L, LUAHIREDIS_COPYRIGHT); lua_setfield(L, -2, "_COPYRIGHT"); lua_pushliteral(L, LUAHIREDIS_DESCRIPTION); lua_setfield(L, -2, "_DESCRIPTION"); /* * Register enums */ reg_enum(L, Errors); reg_enum(L, ReplyTypes); /* * Register constants */ push_new_const(L, "NIL", 3, REDIS_REPLY_NIL); lua_setfield(L, -2, LUAHIREDIS_KEY_NIL); push_new_const(L, "OK", 2, REDIS_REPLY_STATUS); lua_setfield(L, -2, "OK"); push_new_const(L, "QUEUED", 6, REDIS_REPLY_STATUS); lua_setfield(L, -2, "QUEUED"); push_new_const(L, "PONG", 4, REDIS_REPLY_STATUS); lua_setfield(L, -2, "PONG"); /* * Register functions */ lua_pushvalue(L, -1); /* Module table to be set as upvalue */ setfuncs(L, R, 1); return 1; }
LUALIB_API int luaopen_hiredis(lua_State * L) { /* * Register module */ luaL_register(L, "hiredis", E); /* * Register module information */ lua_pushliteral(L, LUAHIREDIS_VERSION); lua_setfield(L, -2, "_VERSION"); lua_pushliteral(L, LUAHIREDIS_COPYRIGHT); lua_setfield(L, -2, "_COPYRIGHT"); lua_pushliteral(L, LUAHIREDIS_DESCRIPTION); lua_setfield(L, -2, "_DESCRIPTION"); /* * Register enums */ reg_enum(L, Errors); reg_enum(L, ReplyTypes); /* * Register constants */ push_new_const(L, "NIL", 3, REDIS_REPLY_NIL); lua_setfield(L, -2, LUAHIREDIS_KEY_NIL); lua_newtable(L); /* status */ if (luaL_newmetatable(L, LUAHIREDIS_STATUS_MT)) { luaL_register(L, NULL, STATUS_MT); lua_pushliteral(L, LUAHIREDIS_STATUS_MT); lua_setfield(L, -2, "__metatable"); } lua_setmetatable(L, -2); lua_getfield(L, -1, "OK"); lua_setfield(L, -3, "OK"); /* hiredis.OK = status.OK */ lua_getfield(L, -1, "QUEUED"); lua_setfield(L, -3, "QUEUED"); /* hiredis.QUEUED = status.QUEUED */ lua_getfield(L, -1, "PONG"); lua_setfield(L, -3, "PONG"); /* hiredis.PONG = status.PONG */ lua_setfield(L, -2, "status"); /* hiredis.status = status */ /* * Register functions */ lua_pushvalue(L, -1); /* Module table to be set as upvalue */ setfuncs(L, R, 1); return 1; }
static int lstatus_index(lua_State * L) { size_t key_len = 0; const char * key = NULL; luaL_checktype(L, 1, LUA_TTABLE); key = luaL_checklstring(L, 2, &key_len); push_new_const( L, key, key_len, REDIS_REPLY_STATUS /* status */ ); lua_rawset(L, 1); /* t[key] = status */ luaL_checkstack(L, 1, "not enough stack"); lua_pushlstring(L, key, key_len); /* Push the key again */ lua_gettable(L, 1); /* return t[key] */ return 1; }
static int push_reply(lua_State * L, redisReply * pReply) { switch (pReply->type) { case REDIS_REPLY_STATUS: luaL_checkstack(L, 2, "not enough stack to push reply"); lua_pushvalue(L, lua_upvalueindex(1)); /* M (module table) */ lua_getfield(L, -1, "status"); /* status = M.status */ lua_remove(L, -2); /* Remove module table from stack */ lua_pushlstring(L, pReply->str, pReply->len); /* name */ lua_gettable(L, -2); /* status[name] */ lua_remove(L, -2); /* Remove status table from stack */ break; case REDIS_REPLY_ERROR: /* Not caching errors, they are (hopefully) not that common */ push_new_const(L, pReply->str, pReply->len, REDIS_REPLY_ERROR); break; case REDIS_REPLY_INTEGER: luaL_checkstack(L, 1, "not enough stack to push reply"); lua_pushinteger(L, pReply->integer); break; case REDIS_REPLY_NIL: luaL_checkstack(L, 2, "not enough stack to push reply"); lua_pushvalue(L, lua_upvalueindex(1)); /* module table */ lua_getfield(L, -1, LUAHIREDIS_KEY_NIL); lua_remove(L, -2); /* module table */ break; case REDIS_REPLY_STRING: luaL_checkstack(L, 1, "not enough stack to push reply"); lua_pushlstring(L, pReply->str, pReply->len); break; case REDIS_REPLY_ARRAY: { unsigned int i = 0; luaL_checkstack(L, 2, "not enough stack to push reply"); lua_createtable(L, pReply->elements, 0); for (i = 0; i < pReply->elements; ++i) { /* * Not controlling recursion depth: * if we parsed the reply somehow, * we hope to be able to push it. */ push_reply(L, pReply->element[i]); lua_rawseti(L, -2, i + 1); /* Store sub-reply */ } break; } default: /* should not happen */ return luaL_error(L, "command: unknown reply type: %d", pReply->type); } /* * Always returning a single value. * If changed, change REDIS_REPLY_ARRAY above. */ return 1; }
static int push_reply(lua_State * L, redisReply * pReply) { /* int base = lua_gettop(L); */ switch(pReply->type) { case REDIS_REPLY_STATUS: lua_pushvalue(L, lua_upvalueindex(1)); /* M (module table) */ lua_pushlstring(L, pReply->str, pReply->len); /* status */ lua_gettable(L, -2); /* M[status] */ if (lua_isnil(L, -1)) /* Not bothering with metatables */ { /* * TODO: Following code is likely to be broken due to early binding * (imagine that RETURN is a command that returns given string * as a status): * * assert(conn:command("RETURN", "FOO") == hiredis.FOO) * * Here hiredis.FOO would be nil before conn:command() is called. * * Note that this is not relevant to the current Redis implementation * (that is 2.2 and before), since it seems that it wouldn't * return any status code except OK, QUEUED or PONG, * all of which are alread covered. */ lua_pushlstring(L, pReply->str, pReply->len); /* status */ push_new_const( L, pReply->str, pReply->len, REDIS_REPLY_STATUS /* const */ ); lua_settable(L, -3); /* M[status] = const */ lua_pushlstring(L, pReply->str, pReply->len); /* status */ lua_gettable(L, -2); /* return M[status] */ } lua_remove(L, -2); /* Remove module table */ break; case REDIS_REPLY_ERROR: /* Not caching errors, they are (hopefully) not that common */ push_new_const(L, pReply->str, pReply->len, REDIS_REPLY_ERROR); break; case REDIS_REPLY_INTEGER: lua_pushinteger(L, pReply->integer); break; case REDIS_REPLY_NIL: lua_pushvalue(L, lua_upvalueindex(1)); /* module table */ lua_getfield(L, -1, LUAHIREDIS_KEY_NIL); lua_remove(L, -2); /* module table */ break; case REDIS_REPLY_STRING: lua_pushlstring(L, pReply->str, pReply->len); break; case REDIS_REPLY_ARRAY: { unsigned int i = 0; lua_createtable(L, pReply->elements, 0); for (i = 0; i < pReply->elements; ++i) { /* * Not controlling recursion depth: * if we parsed the reply somehow, * we hope to be able to push it. */ push_reply(L, pReply->element[i]); lua_rawseti(L, -2, i + 1); /* Store sub-reply */ } break; } default: /* should not happen */ return luaL_error(L, "command: unknown reply type: %d", pReply->type); } /* if (lua_gettop(L) != base + 1) { return luaL_error(L, "pushreplystackerror: actual %d expected %d base %d type %d", lua_gettop(L), base + 1, base, pReply->type); } */ /* * Always returning a single value. * If changed, change REDIS_REPLY_ARRAY above. */ return 1; }