static int getTag(lua_State* L) { BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1)); lua_pushstring(L, barrier->GetTag(lua_tostring(L, 2)).c_str()); return 1; }
/** * Converts a t_string object to a string (__tostring metamethod); * that is, performs a translation. */ static int impl_tstring_tostring(lua_State *L) { t_string *t = static_cast<t_string *>(lua_touserdata(L, 1)); lua_pushstring(L, t->c_str()); return 1; }
int _lua_write_connection(lua_State *lua_state) { /* allocates the data (original message data) */ const char *data; /* allocates the (final) buffer to send the message */ unsigned char *buffer; /* allocates the data size */ unsigned int data_size; /* allocates the HTTP parser */ struct http_parser_t *http_parser; /* allocates the connection */ struct connection_t *connection; /* retrieves the number of (received) arguments */ unsigned int number_arguments = lua_gettop(lua_state); /* in case the number of arguments is invalid */ if(number_arguments != 3) { /* prints a warning message */ V_WARNING("Invalid number of arguments\n"); /* pushes an error message to Lua */ lua_pushstring(lua_state, "Invalid number of arguments"); lua_error(lua_state); } if(!lua_isnumber(lua_state, -1)) { /* prints a warning message */ V_WARNING("Incorrect argument 'expected number'\n"); /* pushes an error message to Lua */ lua_pushstring(lua_state, "Incorrect argument to 'expected number'"); lua_error(lua_state); } if(!lua_isstring(lua_state, -2)) { /* prints a warning message */ V_WARNING("Incorrect argument 'expected string'\n"); /* pushes an error message to Lua */ lua_pushstring(lua_state, "Incorrect argument to 'expected string'"); lua_error(lua_state); } if(!lua_islightuserdata(lua_state, -3)) { /* prints a warning message */ V_WARNING("Incorrect argument 'expected lightuserdata'\n"); /* pushes an error message to Lua */ lua_pushstring(lua_state, "Incorrect argument 'expected lightuserdata'"); lua_error(lua_state); } /* converts the third argument into an integer */ data_size = lua_tointeger(lua_state, -1); /* converts the second argument into a string */ data = lua_tostring(lua_state, -2); /* converts the first argument into HTTP parser structure */ http_parser = (struct http_parser_t *) lua_touserdata(lua_state, -3); /* retrieves the connection from the HTTP parser parameters */ connection = (struct connection_t *) http_parser->parameters; /* allocates the data buffer (in a safe maner) then copies the data (from Lua) into the buffer */ connection->alloc_data(connection, data_size * sizeof(unsigned char), (void **) &buffer); memcpy(buffer, data, data_size); /* writes the response to the connection */ connection->write_connection( connection, buffer, data_size, _send_response_callback_handler_lua, (void *) (size_t) http_parser->flags ); /* return the number of results */ return 0; }
static int ngx_http_lua_ngx_re_gmatch(lua_State *L) { ngx_http_lua_main_conf_t *lmcf = NULL; ngx_http_request_t *r; ngx_str_t subj; ngx_str_t pat; ngx_str_t opts; int ovecsize; ngx_http_lua_regex_t *re; ngx_lua_regex_compile_t re_comp; ngx_http_lua_regex_ctx_t *ctx; const char *msg; int nargs; ngx_int_t flags; int *cap = NULL; ngx_int_t rc; ngx_pool_t *pool, *old_pool; u_char errstr[NGX_MAX_CONF_ERRSTR + 1]; pcre_extra *sd = NULL; ngx_http_cleanup_t *cln; nargs = lua_gettop(L); if (nargs != 2 && nargs != 3) { return luaL_error(L, "expecting two or three arguments, but got %d", nargs); } lua_pushlightuserdata(L, &ngx_http_lua_request_key); lua_rawget(L, LUA_GLOBALSINDEX); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } subj.data = (u_char *) luaL_checklstring(L, 1, &subj.len); pat.data = (u_char *) luaL_checklstring(L, 2, &pat.len); if (nargs == 3) { opts.data = (u_char *) luaL_checklstring(L, 3, &opts.len); lua_pop(L, 1); } else { opts.data = (u_char *) ""; opts.len = 0; } /* stack: subj regex */ re_comp.options = 0; flags = ngx_http_lua_ngx_re_parse_opts(L, &re_comp, &opts, 3); if (flags & NGX_LUA_RE_COMPILE_ONCE) { lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); pool = lmcf->pool; dd("server pool %p", lmcf->pool); lua_pushlightuserdata(L, &ngx_http_lua_regex_cache_key); lua_rawget(L, LUA_REGISTRYINDEX); /* table */ lua_pushliteral(L, "m"); lua_pushvalue(L, 2); /* table regex */ dd("options size: %d", (int) sizeof(re_comp.options)); lua_pushlstring(L, (char *) &re_comp.options, sizeof(re_comp.options)); /* table regex opts */ lua_concat(L, 3); /* table key */ lua_pushvalue(L, -1); /* table key key */ dd("regex cache key: %.*s", (int) (pat.len + sizeof(re_comp.options)), lua_tostring(L, -1)); lua_rawget(L, -3); /* table key re */ re = lua_touserdata(L, -1); lua_pop(L, 1); /* table key */ if (re) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua regex cache hit for match regex \"%s\" " "with options \"%s\"", pat.data, opts.data); lua_pop(L, 2); dd("restoring regex %p, ncaptures %d, captures %p", re->regex, re->ncaptures, re->captures); re_comp.regex = re->regex; sd = re->regex_sd; re_comp.captures = re->ncaptures; cap = re->captures; if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; } else { ovecsize = (re->ncaptures + 1) * 3; } goto compiled; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua regex cache miss for match regex \"%s\" " "with options \"%s\"", pat.data, opts.data); if (lmcf->regex_cache_entries >= lmcf->regex_cache_max_entries) { if (lmcf->regex_cache_entries == lmcf->regex_cache_max_entries) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "lua exceeding regex cache max entries (%i)", lmcf->regex_cache_max_entries); lmcf->regex_cache_entries++; } pool = r->pool; flags &= ~NGX_LUA_RE_COMPILE_ONCE; } } else { pool = r->pool; } re_comp.pattern = pat; re_comp.err.len = NGX_MAX_CONF_ERRSTR; re_comp.err.data = errstr; re_comp.pool = pool; ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua compiling gmatch regex \"%s\" with options \"%s\" " "(compile once: %d) (dfa mode: %d) (jit mode: %d)", pat.data, opts.data, (flags & NGX_LUA_RE_COMPILE_ONCE) != 0, (flags & NGX_LUA_RE_MODE_DFA) != 0, (flags & NGX_LUA_RE_MODE_JIT) != 0); old_pool = ngx_http_lua_pcre_malloc_init(pool); rc = ngx_lua_regex_compile(&re_comp); ngx_http_lua_pcre_malloc_done(old_pool); if (rc != NGX_OK) { dd("compile failed"); re_comp.err.data[re_comp.err.len] = '\0'; msg = lua_pushfstring(L, "failed to compile regex \"%s\": %s", pat.data, re_comp.err.data); return luaL_argerror(L, 2, msg); } #if LUA_HAVE_PCRE_JIT if (flags & NGX_LUA_RE_MODE_JIT) { old_pool = ngx_http_lua_pcre_malloc_init(pool); sd = pcre_study(re_comp.regex, PCRE_STUDY_JIT_COMPILE, &msg); ngx_http_lua_pcre_malloc_done(old_pool); # if (NGX_DEBUG) dd("sd = %p", sd); if (msg != NULL) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre_study failed with PCRE_STUDY_JIT_COMPILE: %s (%p)", msg, sd); } if (sd != NULL) { int jitted; old_pool = ngx_http_lua_pcre_malloc_init(pool); pcre_fullinfo(re_comp.regex, sd, PCRE_INFO_JIT, &jitted); ngx_http_lua_pcre_malloc_done(old_pool); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre JIT compiling result: %d", jitted); } # endif /* NGX_DEBUG */ } else { old_pool = ngx_http_lua_pcre_malloc_init(pool); sd = pcre_study(re_comp.regex, 0, &msg); ngx_http_lua_pcre_malloc_done(old_pool); # if (NGX_DEBUG) dd("sd = %p", sd); if (msg != NULL) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre study failed with PCRE_STUDY_JIT_COMPILE: %s (%p)", msg, sd); } # endif /* NGX_DEBUG */ } #else /* LUA_HAVE_PCRE_JIT */ if (flags & NGX_LUA_RE_MODE_JIT) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "your pcre build does not have JIT support and " "the \"j\" regex option is ignored"); } #endif /* LUA_HAVE_PCRE_JIT */ dd("compile done, captures %d", re_comp.captures); if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; } else { ovecsize = (re_comp.captures + 1) * 3; } cap = ngx_palloc(pool, ovecsize * sizeof(int)); if (cap == NULL) { flags &= ~NGX_LUA_RE_COMPILE_ONCE; msg = "out of memory"; goto error; } if (flags & NGX_LUA_RE_COMPILE_ONCE) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua saving compiled regex (%d captures) into the cache " "(entries %i)", re_comp.captures, lmcf ? lmcf->regex_cache_entries : 0); re = ngx_palloc(pool, sizeof(ngx_http_lua_regex_t)); if (re == NULL) { return luaL_error(L, "out of memory"); } dd("saving regex %p, ncaptures %d, captures %p", re_comp.regex, re_comp.captures, cap); re->regex = re_comp.regex; re->regex_sd = sd; re->ncaptures = re_comp.captures; re->captures = cap; re->replace = NULL; lua_pushlightuserdata(L, re); /* table key value */ lua_rawset(L, -3); /* table */ lua_pop(L, 1); if (lmcf) { lmcf->regex_cache_entries++; } } compiled: lua_settop(L, 1); ctx = lua_newuserdata(L, sizeof(ngx_http_lua_regex_ctx_t)); ctx->request = r; ctx->regex = re_comp.regex; ctx->regex_sd = sd; ctx->ncaptures = re_comp.captures; ctx->captures = cap; ctx->captures_len = ovecsize; ctx->flags = (uint8_t) flags; if (!(flags & NGX_LUA_RE_COMPILE_ONCE)) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return luaL_error(L, "out of memory"); } cln->handler = ngx_http_lua_ngx_re_gmatch_cleanup; cln->data = ctx; } lua_pushinteger(L, 0); /* upvalues in order: subj ctx offset */ lua_pushcclosure(L, ngx_http_lua_ngx_re_gmatch_iterator, 3); return 1; error: if (!(flags & NGX_LUA_RE_COMPILE_ONCE)) { if (sd) { ngx_http_lua_regex_free_study_data(pool, sd); } if (re_comp.regex) { ngx_pfree(pool, re_comp.regex); } if (cap) { ngx_pfree(pool, cap); } } return luaL_error(L, msg); }
static int ngx_http_lua_ngx_re_match(lua_State *L) { /* u_char *p; */ ngx_http_request_t *r; ngx_str_t subj; ngx_str_t pat; ngx_str_t opts; ngx_lua_regex_compile_t re_comp; ngx_http_lua_regex_t *re; const char *msg; ngx_int_t rc; ngx_uint_t n; int i; ngx_int_t pos = 0; int nargs; int *cap = NULL; int ovecsize; ngx_uint_t flags; ngx_pool_t *pool, *old_pool; ngx_http_lua_main_conf_t *lmcf = NULL; u_char errstr[NGX_MAX_CONF_ERRSTR + 1]; pcre_extra *sd = NULL; nargs = lua_gettop(L); if (nargs != 2 && nargs != 3 && nargs != 4) { return luaL_error(L, "expecting two or three or four arguments, " "but got %d", nargs); } lua_pushlightuserdata(L, &ngx_http_lua_request_key); lua_rawget(L, LUA_GLOBALSINDEX); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } subj.data = (u_char *) luaL_checklstring(L, 1, &subj.len); pat.data = (u_char *) luaL_checklstring(L, 2, &pat.len); ngx_memzero(&re_comp, sizeof(ngx_lua_regex_compile_t)); if (nargs >= 3) { opts.data = (u_char *) luaL_checklstring(L, 3, &opts.len); if (nargs == 4) { luaL_checktype(L, 4, LUA_TTABLE); lua_getfield(L, 4, "pos"); if (lua_isnumber(L, -1)) { pos = (ngx_int_t) lua_tointeger(L, -1); if (pos < 0) { pos = 0; } } else if (lua_isnil(L, -1)) { pos = 0; } else { msg = lua_pushfstring(L, "bad pos field type in the ctx table " "argument: %s", luaL_typename(L, -1)); return luaL_argerror(L, 4, msg); } lua_pop(L, 1); } } else { opts.data = (u_char *) ""; opts.len = 0; } re_comp.options = 0; flags = ngx_http_lua_ngx_re_parse_opts(L, &re_comp, &opts, 3); if (flags & NGX_LUA_RE_COMPILE_ONCE) { lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); pool = lmcf->pool; dd("server pool %p", lmcf->pool); lua_pushlightuserdata(L, &ngx_http_lua_regex_cache_key); lua_rawget(L, LUA_REGISTRYINDEX); /* table */ lua_pushliteral(L, "m"); lua_pushvalue(L, 2); /* table regex */ dd("options size: %d", (int) sizeof(re_comp.options)); lua_pushlstring(L, (char *) &re_comp.options, sizeof(re_comp.options)); /* table regex opts */ lua_concat(L, 3); /* table key */ lua_pushvalue(L, -1); /* table key key */ dd("regex cache key: %.*s", (int) (pat.len + sizeof(re_comp.options)), lua_tostring(L, -1)); lua_rawget(L, -3); /* table key re */ re = lua_touserdata(L, -1); lua_pop(L, 1); /* table key */ if (re) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua regex cache hit for match regex \"%s\" with " "options \"%s\"", pat.data, opts.data); lua_pop(L, 2); dd("restoring regex %p, ncaptures %d, captures %p", re->regex, re->ncaptures, re->captures); re_comp.regex = re->regex; sd = re->regex_sd; re_comp.captures = re->ncaptures; cap = re->captures; if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; } else { ovecsize = (re->ncaptures + 1) * 3; } goto exec; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua regex cache miss for match regex \"%s\" " "with options \"%s\"", pat.data, opts.data); if (lmcf->regex_cache_entries >= lmcf->regex_cache_max_entries) { if (lmcf->regex_cache_entries == lmcf->regex_cache_max_entries) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "lua exceeding regex cache max entries (%i)", lmcf->regex_cache_max_entries); lmcf->regex_cache_entries++; } pool = r->pool; flags &= ~NGX_LUA_RE_COMPILE_ONCE; } } else { pool = r->pool; } dd("pool %p, r pool %p", pool, r->pool); re_comp.pattern = pat; re_comp.err.len = NGX_MAX_CONF_ERRSTR; re_comp.err.data = errstr; re_comp.pool = pool; ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua compiling match regex \"%s\" with options \"%s\" " "(compile once: %d) (dfa mode: %d) (jit mode: %d)", pat.data, opts.data, (flags & NGX_LUA_RE_COMPILE_ONCE) != 0, (flags & NGX_LUA_RE_MODE_DFA) != 0, (flags & NGX_LUA_RE_MODE_JIT) != 0); old_pool = ngx_http_lua_pcre_malloc_init(pool); rc = ngx_lua_regex_compile(&re_comp); ngx_http_lua_pcre_malloc_done(old_pool); if (rc != NGX_OK) { dd("compile failed"); re_comp.err.data[re_comp.err.len] = '\0'; msg = lua_pushfstring(L, "failed to compile regex \"%s\": %s", pat.data, re_comp.err.data); return luaL_argerror(L, 2, msg); } #if LUA_HAVE_PCRE_JIT if (flags & NGX_LUA_RE_MODE_JIT) { old_pool = ngx_http_lua_pcre_malloc_init(pool); sd = pcre_study(re_comp.regex, PCRE_STUDY_JIT_COMPILE, &msg); ngx_http_lua_pcre_malloc_done(old_pool); # if (NGX_DEBUG) dd("sd = %p", sd); if (msg != NULL) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre study failed with PCRE_STUDY_JIT_COMPILE: %s (%p)", msg, sd); } if (sd != NULL) { int jitted; old_pool = ngx_http_lua_pcre_malloc_init(pool); pcre_fullinfo(re_comp.regex, sd, PCRE_INFO_JIT, &jitted); ngx_http_lua_pcre_malloc_done(old_pool); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre JIT compiling result: %d", jitted); } # endif /* NGX_DEBUG */ } else { old_pool = ngx_http_lua_pcre_malloc_init(pool); sd = pcre_study(re_comp.regex, 0, &msg); ngx_http_lua_pcre_malloc_done(old_pool); # if (NGX_DEBUG) dd("sd = %p", sd); if (msg != NULL) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre_study failed with PCRE_STUDY_JIT_COMPILE: %s (%p)", msg, sd); } # endif /* NGX_DEBUG */ } #else /* LUA_HAVE_PCRE_JIT */ if (flags & NGX_LUA_RE_MODE_JIT) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "your pcre build does not have JIT support and " "the \"j\" regex option is ignored"); } #endif /* LUA_HAVE_PCRE_JIT */ dd("compile done, captures %d", (int) re_comp.captures); if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; } else { ovecsize = (re_comp.captures + 1) * 3; } dd("allocating cap with size: %d", (int) ovecsize); cap = ngx_palloc(pool, ovecsize * sizeof(int)); if (cap == NULL) { flags &= ~NGX_LUA_RE_COMPILE_ONCE; msg = "out of memory"; goto error; } if (flags & NGX_LUA_RE_COMPILE_ONCE) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua saving compiled regex (%d captures) into the cache " "(entries %i)", re_comp.captures, lmcf ? lmcf->regex_cache_entries : 0); re = ngx_palloc(pool, sizeof(ngx_http_lua_regex_t)); if (re == NULL) { return luaL_error(L, "out of memory"); } dd("saving regex %p, ncaptures %d, captures %p", re_comp.regex, re_comp.captures, cap); re->regex = re_comp.regex; re->regex_sd = sd; re->ncaptures = re_comp.captures; re->captures = cap; re->replace = NULL; lua_pushlightuserdata(L, re); /* table key value */ lua_rawset(L, -3); /* table */ lua_pop(L, 1); if (lmcf) { lmcf->regex_cache_entries++; } } exec: if (flags & NGX_LUA_RE_MODE_DFA) { #if LUA_HAVE_PCRE_DFA int ws[NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT]; rc = ngx_http_lua_regex_dfa_exec(re_comp.regex, sd, &subj, (int) pos, cap, ovecsize, ws, NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT); #else /* LUA_HAVE_PCRE_DFA */ msg = "at least pcre 6.0 is required for the DFA mode"; goto error; #endif /* LUA_HAVE_PCRE_DFA */ } else { rc = ngx_http_lua_regex_exec(re_comp.regex, sd, &subj, (int) pos, cap, ovecsize); } if (rc == NGX_REGEX_NO_MATCHED) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "regex \"%s\" not matched on string \"%s\" starting from %z", pat.data, subj.data, pos); if (!(flags & NGX_LUA_RE_COMPILE_ONCE)) { if (sd) { ngx_http_lua_regex_free_study_data(pool, sd); } ngx_pfree(pool, re_comp.regex); ngx_pfree(pool, cap); } lua_pushnil(L); return 1; } if (rc < 0) { msg = lua_pushfstring(L, ngx_regex_exec_n " failed: %d on \"%s\" " "using \"%s\"", (int) rc, subj.data, pat.data); goto error; } if (rc == 0) { if (flags & NGX_LUA_RE_MODE_DFA) { rc = 1; } else { msg = "capture size too small"; goto error; } } dd("rc = %d", (int) rc); lua_createtable(L, rc - 1 /* narr */, 1 /* nrec */); for (i = 0, n = 0; i < rc; i++, n += 2) { dd("capture %d: %d %d", i, cap[n], cap[n + 1]); if (cap[n] < 0) { lua_pushnil(L); } else { lua_pushlstring(L, (char *) &subj.data[cap[n]], cap[n + 1] - cap[n]); dd("pushing capture %s at %d", lua_tostring(L, -1), (int) i); } lua_rawseti(L, -2, (int) i); } if (nargs == 4) { /* having ctx table */ pos = cap[1]; lua_pushinteger(L, (lua_Integer) pos); lua_setfield(L, 4, "pos"); } if (!(flags & NGX_LUA_RE_COMPILE_ONCE)) { if (sd) { ngx_http_lua_regex_free_study_data(pool, sd); } ngx_pfree(pool, re_comp.regex); ngx_pfree(pool, cap); } return 1; error: if (!(flags & NGX_LUA_RE_COMPILE_ONCE)) { if (sd) { ngx_http_lua_regex_free_study_data(pool, sd); } if (re_comp.regex) { ngx_pfree(pool, re_comp.regex); } if (cap) { ngx_pfree(pool, cap); } } return luaL_error(L, msg); }
int rb_save(lua_State *L, int index, ringbuffer_t *rb, int oop, int upval) { char type = lua_type(L, index); switch (type) { case LUA_TNIL: { RB_WRITE(L, rb, &type, sizeof(char)); return 0; } case LUA_TBOOLEAN: { RB_WRITE(L, rb, &type, sizeof(char)); type = lua_toboolean(L, index); RB_WRITE(L, rb, &type, sizeof(char)); return 0; } case LUA_TNUMBER: { #if LUA_VERSION_NUM >= 503 if (lua_isinteger(L, index)) { type = EXTRA_LUA_TINTEGER; RB_WRITE(L, rb, &type, sizeof(char)); lua_Integer n = lua_tointeger(L, index); RB_WRITE(L, rb, &n, sizeof(n)); } else #endif { RB_WRITE(L, rb, &type, sizeof(char)); lua_Number n = lua_tonumber(L, index); RB_WRITE(L, rb, &n, sizeof(n)); } return 0; } case LUA_TSTRING: { RB_WRITE(L, rb, &type, sizeof(char)); size_t str_len; const char *str = lua_tolstring(L, index, &str_len); RB_WRITE(L, rb, &str_len, sizeof(str_len)); RB_WRITE(L, rb, str, str_len); return 0; } case LUA_TTABLE: { RB_WRITE(L, rb, &type, sizeof(char)); int top = lua_gettop(L); int ret; lua_pushnil(L); while (lua_next(L, index) != 0) { ret = rb_save(L, top + 1, rb, oop, upval); // key if (ret) { lua_pop(L, 2); return ret; } ret = rb_save(L, top + 2, rb, oop, upval); // value if (ret) { lua_pop(L, 2); return ret; } lua_pop(L, 1); } type = LUA_TNIL; RB_WRITE(L, rb, &type, sizeof(char)); // breaks the read loop // the typename identifies the metatable const char *str = luaT_typename(L, index); if (!str) { if (luaL_callmeta(L, index, "metatablename")) { str = lua_tostring(L, lua_gettop(L)); lua_pop(L, 1); } else { str = ""; } } size_t str_len = strlen(str); RB_WRITE(L, rb, &str_len, sizeof(str_len)); RB_WRITE(L, rb, str, str_len); return 0; } case LUA_TFUNCTION: { RB_WRITE(L, rb, &type, sizeof(char)); if (index != lua_gettop(L)) { lua_pushvalue(L, index); } lua_Debug ar; lua_pushvalue(L, -1); lua_getinfo(L, ">nuS", &ar); if (ar.what[0] != 'L') { luaL_error(L, "attempt to persist a C function '%s'", ar.name); } // this returns different things under LuaJIT vs Lua #if LUA_VERSION_NUM >= 503 lua_dump(L, rb_lua_writer, rb, 0); #else lua_dump(L, rb_lua_writer, rb); #endif size_t str_len = 0; RB_WRITE(L, rb, &str_len, sizeof(size_t)); // zero-terminated // does the serialization accept upvalues? RB_WRITE(L, rb, &upval, sizeof(int)); // upvalues if (upval == 1) { lua_newtable(L); int envIdx = -1; for (int i=1; i <= ar.nups; i++) { const char *name = lua_getupvalue(L, -2, i); if (strcmp(name, "_ENV") != 0) { lua_rawseti(L, -2, i); } else { // ignore _ENV as we assume that this is the global _G variable lua_pop(L, 1); envIdx = i; } } // write upvalue index of _ENV RB_WRITE(L, rb, &envIdx, sizeof(int)); // write upvalue table int ret = rb_save(L, lua_gettop(L), rb, oop, upval); if (ret) { return ret; } lua_pop(L, 1); } else if (ar.nups > 1) { luaL_error(L, "attempt to serialize a funciton with upvalues (i.e. a closure). Use ipc.workqueue.writeup()."); } if (index != lua_gettop(L)) { lua_pop(L, 1); } return 0; } case LUA_TUSERDATA: { if (oop) return -EPERM; const char *str = luaT_typename(L, index); if (!str) { if (luaL_callmeta(L, index, "metatablename")) { str = lua_tostring(L, lua_gettop(L)); lua_pop(L, 1); type = -type; } else { return -EINVAL; } } RB_WRITE(L, rb, &type, sizeof(char)); size_t str_len = strlen(str); RB_WRITE(L, rb, &str_len, sizeof(str_len)); RB_WRITE(L, rb, str, str_len); void *ptr = lua_touserdata(L, index); RB_WRITE(L, rb, ptr, sizeof(void *)); if (luaL_callmeta(L, index, "retain")) { lua_pop(L, 1); } else { return -EINVAL; } return 0; } default: return -EPERM; } }
static int _draw_screen(lua_State *L) { JiveSurface *srf; Uint32 t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; clock_t c0 = 0, c1 = 0; bool_t standalone_draw, drawn = false; JIVEL_STACK_CHECK_BEGIN(L); /* stack is: * 1: framework * 2: surface (in screen format) * 3: standalone_draw (used to draw screen to a new surface) */ srf = *(JiveSurface **)lua_touserdata(L, 2); standalone_draw = lua_toboolean(L, 3); /* Exit if we have no windows, nothing to draw */ lua_getfield(L, 1, "windowStack"); if (lua_objlen(L, -1) == 0) { lua_pop(L, 2); JIVEL_STACK_CHECK_ASSERT(L); return 0; } lua_rawgeti(L, -1, 1); // topwindow if (perfwarn.screen) { t0 = jive_jiffies(); c0 = clock(); } do { jive_origin = next_jive_origin; /* Layout window and widgets */ if (jive_getmethod(L, -1, "checkLayout")) { lua_pushvalue(L, -2); lua_call(L, 1, 0); } /* check in case the origin changes during layout */ } while (jive_origin != next_jive_origin); if (perfwarn.screen) t1 = jive_jiffies(); /* Widget animations - don't update in a standalone draw as its not the main screen update */ if (!standalone_draw) { lua_getfield(L, 1, "animations"); lua_pushnil(L); while (lua_next(L, -2) != 0) { lua_getfield(L, -1, "animations"); lua_pushnil(L); while (lua_next(L, -2) != 0) { int frame; /* stack is: * -2: key * -1: table */ lua_rawgeti(L, -1, 2); frame = lua_tointeger(L, -1) - 1; if (frame == 0) { lua_rawgeti(L, -2, 1); // function lua_pushvalue(L, -6); // widget lua_call(L, 1, 0); // function is poped by lua_call lua_rawgeti(L, -2, 3); lua_rawseti(L, -3, 2); } else { lua_pushinteger(L, frame); lua_rawseti(L, -3, 2); } lua_pop(L, 2); } lua_pop(L, 2); } lua_pop(L, 1); } if (perfwarn.screen) t2 = jive_jiffies(); /* Window transitions */ lua_getfield(L, 1, "transition"); if (!lua_isnil(L, -1)) { /* Draw background */ jive_surface_set_clip(srf, NULL); jive_tile_set_alpha(jive_background, 0); // no alpha channel jive_tile_blit(jive_background, srf, 0, 0, screen_w, screen_h); if (perfwarn.screen) t3 = jive_jiffies(); /* Animate screen transition */ lua_pushvalue(L, -1); lua_pushvalue(L, -3); // widget lua_pushvalue(L, 2); // surface lua_call(L, 2, 0); drawn = true; } else if (jive_dirty_region.w || standalone_draw) { SDL_Rect dirty; /* only redraw dirty region for non standalone draws */ if (!standalone_draw) { jive_rect_union(&jive_dirty_region, &last_dirty_region, &dirty); jive_surface_set_clip(srf, &dirty); } #if 0 printf("REDRAW: %d,%d %dx%d\n", jive_dirty_region.x, jive_dirty_region.y, jive_dirty_region.w, jive_dirty_region.h); printf("--> %d,%d %dx%d\n", dirty.x, dirty.y, dirty.w, dirty.h); #endif /* Draw background */ jive_tile_blit(jive_background, srf, 0, 0, screen_w, screen_h); if (perfwarn.screen) t3 = jive_jiffies(); /* Draw screen */ if (jive_getmethod(L, -2, "draw")) { lua_pushvalue(L, -3); // widget lua_pushvalue(L, 2); // surface lua_pushinteger(L, JIVE_LAYER_ALL); // layer lua_call(L, 3, 0); } #if 0 // show the dirty region for debug purposes: jive_surface_rectangleColor(srf, jive_dirty_region.x, jive_dirty_region.y, jive_dirty_region.x + jive_dirty_region.w, jive_dirty_region.y + jive_dirty_region.h, 0xFFFFFFFF); #endif /* clear the dirty region for non standalone draws */ if (!standalone_draw) { memcpy(&last_dirty_region, &jive_dirty_region, sizeof(last_dirty_region)); jive_dirty_region.w = 0; } drawn = true; } if (perfwarn.screen) { t4 = jive_jiffies(); c1 = clock(); if (t4-t0 > perfwarn.screen) { if (!t3) { t3 = t2; } printf("update_screen > %dms: %4dms (%dms) [layout:%dms animate:%dms background:%dms draw:%dms]\n", perfwarn.screen, t4-t0, (int)((c1-c0) * 1000 / CLOCKS_PER_SEC), t1-t0, t2-t1, t3-t2, t4-t3); } } lua_pop(L, 3); JIVEL_STACK_CHECK_END(L); lua_pushboolean(L, drawn); return 1; }
static int impl_name_generator_call(lua_State *L) { name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1)); lua_pushstring(L, gen->generate().c_str()); return 1; }
static int impl_name_generator_collect(lua_State *L) { name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1)); gen->~name_generator(); return 0; }
static int getStatus(lua_State* L) { BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1)); lua_pushinteger(L, barrier->GetStatus(lua_tointeger(L, 2) - 1)); return 1; }
int MyCPrint( lua_State* L ) { // 获取参数数量 int nArgs = lua_gettop(L); for (int i = 1; i <= nArgs; i++) { // 获取参数类型 size_t nLen = 0; int bRet = 0; LUA_INTEGER nRet = 0; LUA_NUMBER dblRet = 0; const void* pAddr = NULL; const char* szRet = NULL; lua_State* pL = NULL; lua_CFunction pFunc = 0; int nType = lua_type(L, i); switch (nType) { case LUA_TNIL: printf("参数 %d 类型为:NIL\n", i); break; case LUA_TBOOLEAN: bRet = lua_toboolean(L, i); printf("参数 %d 类型为:BOOLEAN value = %s\n", i, (!!bRet ? "true" : "false")); break; case LUA_TLIGHTUSERDATA: pAddr = lua_touserdata(L, i); printf("参数 %d 类型为:LIGHTUSERDATA pointer = 0x%08X\n", i, (int)pAddr); break; case LUA_TNUMBER: nRet = lua_tointeger(L, i); dblRet = lua_tonumber(L, i); if (nRet < dblRet) // 浮点数 { printf("参数 %d 类型为:NUMBER value = %g\n", i, dblRet); } else { printf("参数 %d 类型为:NUMBER value = %ld\n", i, nRet); } break; case LUA_TSTRING: nLen = lua_objlen(L, i); szRet = lua_tostring(L, i); printf("参数 %d 类型为:STRING len = %u value = %s\n", i, nLen, szRet); break; case LUA_TTABLE: nLen = lua_objlen(L, i); pAddr = lua_topointer(L, i); printf("参数 %d 类型为:TABLE len = %u pointer = 0x%p\n", i, nLen, (int)pAddr); break; case LUA_TFUNCTION: nLen = lua_objlen(L, i); pFunc = lua_tocfunction(L, i); printf("参数 %d 类型为:FUNCTION len = %u pointer = 0x%p\n", i, nLen, (int)pFunc); break; case LUA_TUSERDATA: pAddr = lua_touserdata(L, i); printf("参数 %d 类型为:USERDATA pointer = 0x%p\n", i, (int)pAddr); break; case LUA_TTHREAD: pL = lua_tothread(L, i); printf("参数 %d 类型为:THREAD pointer = 0x%p\n", i, (int)pL); break; default: nLen = lua_objlen(L, i); szRet = lua_typename(L, i); printf("参数 %d 类型未知!len = %u typename = %s\n", i, nLen, szRet); break; } } return 0; }
static int setStatus(lua_State* L) { BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1)); barrier->SetStatus(lua_tointeger(L, 2) - 1, lua_tointeger(L, 3)); return 0; }
static int getInstance(lua_State* L) { BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1)); lua_pushinteger(L, barrier->GetInstanceIndex()); return 1; }
static int setInstance(lua_State* L) { BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1)); barrier->SetInstanceIndex(lua_tointeger(L, 2)); return 0; }
static int ngx_http_lua_shdict_set_helper(lua_State *L, int flags) { int i, n; ngx_str_t key; uint32_t hash; ngx_int_t rc; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; ngx_str_t value; int value_type; double num; u_char c; lua_Number exptime = 0; u_char *p; ngx_rbtree_node_t *node; ngx_time_t *tp; ngx_shm_zone_t *zone; int forcible = 0; /* indicates whether to foricibly override other * valid entries */ int32_t user_flags = 0; n = lua_gettop(L); if (n != 3 && n != 4 && n != 5) { return luaL_error(L, "expecting 3, 4 or 5 arguments, " "but only seen %d", n); } zone = lua_touserdata(L, 1); if (zone == NULL) { return luaL_error(L, "bad \"zone\" argument"); } ctx = zone->data; if (lua_isnil(L, 2)) { lua_pushnil(L); lua_pushliteral(L, "nil key"); return 2; } key.data = (u_char *) luaL_checklstring(L, 2, &key.len); if (key.len == 0) { lua_pushnil(L); lua_pushliteral(L, "empty key"); return 2; } if (key.len > 65535) { lua_pushnil(L); lua_pushliteral(L, "key too long"); return 2; } hash = ngx_crc32_short(key.data, key.len); value_type = lua_type(L, 3); switch (value_type) { case LUA_TSTRING: value.data = (u_char *) lua_tolstring(L, 3, &value.len); break; case LUA_TNUMBER: value.len = sizeof(double); num = lua_tonumber(L, 3); value.data = (u_char *) # break; case LUA_TBOOLEAN: value.len = sizeof(u_char); c = lua_toboolean(L, 3) ? 1 : 0; value.data = &c; break; case LUA_TNIL: if (flags & (NGX_HTTP_LUA_SHDICT_ADD|NGX_HTTP_LUA_SHDICT_REPLACE)) { lua_pushnil(L); lua_pushliteral(L, "attempt to add or replace nil values"); return 2; } ngx_str_null(&value); break; default: lua_pushnil(L); lua_pushliteral(L, "bad value type"); return 2; } if (n >= 4) { exptime = luaL_checknumber(L, 4); if (exptime < 0) { exptime = 0; } } if (n == 5) { user_flags = (uint32_t) luaL_checkinteger(L, 5); } ngx_shmtx_lock(&ctx->shpool->mutex); #if 1 ngx_http_lua_shdict_expire(ctx, 1); #endif rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); dd("shdict lookup returned %d", (int) rc); if (flags & NGX_HTTP_LUA_SHDICT_REPLACE) { if (rc == NGX_DECLINED || rc == NGX_DONE) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "not found"); lua_pushboolean(L, forcible); return 3; } /* rc == NGX_OK */ goto replace; } if (flags & NGX_HTTP_LUA_SHDICT_ADD) { if (rc == NGX_OK) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "exists"); lua_pushboolean(L, forcible); return 3; } if (rc == NGX_DONE) { /* exists but expired */ dd("go to replace"); goto replace; } /* rc == NGX_DECLINED */ dd("go to insert"); goto insert; } if (rc == NGX_OK || rc == NGX_DONE) { if (value_type == LUA_TNIL) { goto remove; } replace: if (value.data && value.len == (size_t) sd->value_len) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: found old entry and value " "size matched, reusing it"); ngx_queue_remove(&sd->queue); ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); sd->key_len = (u_short) key.len; if (exptime > 0) { tp = ngx_timeofday(); sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + (uint64_t) (exptime * 1000); } else { sd->expires = 0; } sd->user_flags = user_flags; sd->value_len = (uint32_t) value.len; dd("setting value type to %d", value_type); sd->value_type = (uint8_t) value_type; p = ngx_copy(sd->data, key.data, key.len); ngx_memcpy(p, value.data, value.len); ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 1); lua_pushnil(L); lua_pushboolean(L, forcible); return 3; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: found old entry bug value size " "NOT matched, removing it first"); remove: ngx_queue_remove(&sd->queue); node = (ngx_rbtree_node_t *) ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); ngx_rbtree_delete(&ctx->sh->rbtree, node); ngx_slab_free_locked(ctx->shpool, node); } insert: /* rc == NGX_DECLINED or value size unmatch */ if (value.data == NULL) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 1); lua_pushnil(L); lua_pushboolean(L, 0); return 3; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: creating a new entry"); n = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_lua_shdict_node_t, data) + key.len + value.len; node = ngx_slab_alloc_locked(ctx->shpool, n); if (node == NULL) { if (flags & NGX_HTTP_LUA_SHDICT_SAFE_STORE) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "no memory"); return 2; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: overriding non-expired items " "due to memory shortage for entry \"%V\"", &key); for (i = 0; i < 30; i++) { if (ngx_http_lua_shdict_expire(ctx, 0) == 0) { break; } forcible = 1; node = ngx_slab_alloc_locked(ctx->shpool, n); if (node != NULL) { goto allocated; } } ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "no memory"); lua_pushboolean(L, forcible); return 3; } allocated: sd = (ngx_http_lua_shdict_node_t *) &node->color; node->key = hash; sd->key_len = (u_short) key.len; if (exptime > 0) { tp = ngx_timeofday(); sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + (uint64_t) (exptime * 1000); } else { sd->expires = 0; } sd->user_flags = user_flags; sd->value_len = (uint32_t) value.len; dd("setting value type to %d", value_type); sd->value_type = (uint8_t) value_type; p = ngx_copy(sd->data, key.data, key.len); ngx_memcpy(p, value.data, value.len); ngx_rbtree_insert(&ctx->sh->rbtree, node); ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 1); lua_pushnil(L); lua_pushboolean(L, forcible); return 3; }
static char * _get_value(lua_State *L, int index, char * ptr, char type) { switch(type) { case 'i': { int32_t v = luaL_checkinteger(L, index); memcpy(ptr, &v, 4); return ptr + 4; } case 'u': { uint64_t v = (uint64_t)luaL_checknumber(L, index); memcpy(ptr, &v, 8); return ptr + 8; } case 'd': { int64_t v = (int64_t)luaL_checknumber(L, index); memcpy(ptr, &v, 8); return ptr + 8; } case 'b': { int32_t v = lua_toboolean(L, index); memcpy(ptr, &v, 4); return ptr + 4; } case 'p': { void *p = lua_touserdata(L, index); uint32_t v = (uint32_t)(intptr_t)p; memcpy(ptr, &v , 4); return ptr + 4; } case 'x': { const char * i64 = luaL_checkstring(L, index); memcpy(ptr, i64, 8); return ptr + 8; } case 'r': { double v = luaL_checknumber(L, index); memcpy(ptr, &v, 8); return ptr + 8; } case 's': { size_t sz = 0; const char * str = luaL_checklstring(L, index, &sz); struct pbc_slice * slice = (struct pbc_slice *)ptr; slice->buffer = (void*)str; slice->len = sz; return ptr + sizeof(struct pbc_slice); } case 'm': { struct pbc_slice * slice = (struct pbc_slice *)ptr; if (lua_istable(L,index)) { lua_rawgeti(L,index,1); slice->buffer = lua_touserdata(L,-1); lua_rawgeti(L,index,2); slice->len = lua_tointeger(L,-1); lua_pop(L,2); } else { size_t sz = 0; const char * buffer = luaL_checklstring(L, index, &sz); slice->buffer = (void *)buffer; slice->len = sz; } return ptr + sizeof(struct pbc_slice); } default: luaL_error(L,"unknown format %c", type); return ptr; } }
static int js_parser_delete(lua_State *L) { luaL_checktype(L, 1, LUA_TUSERDATA); yajl_free(*(yajl_handle*)lua_touserdata(L, 1)); return 0; }
static void _get_array_value(lua_State *L, pbc_array array, char type) { switch(type) { case 'I': { int32_t v = luaL_checkinteger(L, -1); uint32_t hi = 0; if (v<0) { hi = ~0; } pbc_array_push_integer(array, v, hi); break; } case 'U' : { uint64_t v = (uint64_t)luaL_checknumber(L, -1); pbc_array_push_integer(array, (uint32_t)v, (uint32_t)(v >> 32)); break; } case 'D' : { int64_t v = (int64_t)luaL_checknumber(L, -1); pbc_array_push_integer(array, (uint32_t)v, (uint32_t)(v >> 32)); break; } case 'B': { int32_t v = lua_toboolean(L, -1); pbc_array_push_integer(array, v ? 1: 0, 0); break; } case 'P': { void *p = lua_touserdata(L, -1); uint32_t v = (uint32_t)(intptr_t)p; pbc_array_push_integer(array, v, 0); break; } case 'X': { const char * i64 = luaL_checkstring(L, -1); uint64_t v = *(uint64_t *)i64; pbc_array_push_integer(array, (uint32_t)v, (uint32_t)(v >> 32)); break; } case 'R': { double v = luaL_checknumber(L, -1); pbc_array_push_real(array, v); break; } case 'S': { size_t sz = 0; const char * str = luaL_checklstring(L, -1, &sz); struct pbc_slice slice; slice.buffer = (void*)str; slice.len = sz; pbc_array_push_slice(array, &slice); break; } case 'M': { struct pbc_slice slice; if (lua_istable(L,-1)) { lua_rawgeti(L,-1,1); slice.buffer = lua_touserdata(L,-1); lua_rawgeti(L,-2,2); slice.len = lua_tointeger(L,-1); lua_pop(L,2); } else { size_t sz = 0; const char * buffer = luaL_checklstring(L, -1, &sz); slice.buffer = (void *)buffer; slice.len = sz; } pbc_array_push_slice(array, &slice); break; } } }
/** * @brief Gets system at index. * * @param L Lua state to get system from. * @param ind Index position of system. * @return The LuaSystem at ind. */ LuaSystem lua_tosystem( lua_State *L, int ind ) { return *((LuaSystem*) lua_touserdata(L,ind)); }
// __depersist metamethod handler static int l_str_depersist(lua_State *L) { lua_settop(L, 2); lua_insert(L, 1); LuaPersistReader *pReader = (LuaPersistReader*)lua_touserdata(L, 1); // Read the instructions for re-creating the value if(!pReader->readStackObject()) return 0; if(lua_type(L, 3) == LUA_TBOOLEAN && lua_toboolean(L, 3) == 1) { // The current code uses a boolean marker to indicate that the // instructions were stored in the environment. Replace the marker // with them. lua_getfenv(L, 2); lua_replace(L, 3); } else { // Older versions of the code wrote the instructions here, or nil for // no instructions. Convert nil to the empty table, and store the // instructions as the userdata's environment. if(lua_type(L, 3) == LUA_TNIL) { lua_newtable(L); lua_replace(L, 3); } lua_pushvalue(L, 3); lua_setfenv(L, 2); } // Prepare t, k for saving the value aux_push_weak_table(L, 0); lua_pushvalue(L, 2); if(lua_objlen(L, 3) == 0) { // No instructions provided, so read the value itself if(!pReader->readStackObject()) return 0; } else { // The instructions are a table of values; unpack them and replace // proxies with their values. bool bIsIndexOperation = false; int iCount = (int)lua_objlen(L, 3); lua_checkstack(L, iCount + 1); for(int i = 1; i <= iCount; ++i) { lua_rawgeti(L, 3, i); if(lua_type(L, -1) == LUA_TUSERDATA) { if(i == 1) bIsIndexOperation = true; lua_rawget(L, 4); } } if(iCount == 2 && bIsIndexOperation) { // If there were two values, and the first was a proxy, then the // instruction is to perform a table lookup. lua_gettable(L, -2); lua_replace(L, -2); } else { // Otherwise, the first value was a method or method name. if(lua_type(L, 6) != LUA_TFUNCTION) { lua_pushvalue(L, 6); lua_gettable(L, 7); lua_replace(L, 6); } lua_call(L, iCount - 1, 1); } } // Save the value lua_rawset(L, 4); return 0; }
static int ngx_http_lua_ngx_re_sub_helper(lua_State *L, unsigned global) { ngx_http_lua_regex_t *re; ngx_http_request_t *r; ngx_str_t subj; ngx_str_t pat; ngx_str_t opts; ngx_str_t tpl; ngx_http_lua_main_conf_t *lmcf = NULL; ngx_pool_t *pool, *old_pool; ngx_lua_regex_compile_t re_comp; const char *msg; ngx_int_t rc; ngx_uint_t n; ngx_int_t i; int nargs; int *cap = NULL; int ovecsize; int type; unsigned func; int offset; size_t count; luaL_Buffer luabuf; ngx_int_t flags; u_char *p; u_char errstr[NGX_MAX_CONF_ERRSTR + 1]; pcre_extra *sd = NULL; ngx_http_lua_complex_value_t *ctpl = NULL; ngx_http_lua_compile_complex_value_t ccv; nargs = lua_gettop(L); if (nargs != 3 && nargs != 4) { return luaL_error(L, "expecting three or four arguments, but got %d", nargs); } lua_pushlightuserdata(L, &ngx_http_lua_request_key); lua_rawget(L, LUA_GLOBALSINDEX); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } subj.data = (u_char *) luaL_checklstring(L, 1, &subj.len); pat.data = (u_char *) luaL_checklstring(L, 2, &pat.len); func = 0; type = lua_type(L, 3); switch (type) { case LUA_TFUNCTION: func = 1; tpl.len = 0; tpl.data = (u_char *) ""; break; case LUA_TNUMBER: case LUA_TSTRING: tpl.data = (u_char *) lua_tolstring(L, 3, &tpl.len); break; default: msg = lua_pushfstring(L, "string, number, or function expected, " "got %s", lua_typename(L, type)); return luaL_argerror(L, 3, msg); } ngx_memzero(&re_comp, sizeof(ngx_lua_regex_compile_t)); if (nargs == 4) { opts.data = (u_char *) luaL_checklstring(L, 4, &opts.len); lua_pop(L, 1); } else { /* nargs == 3 */ opts.data = (u_char *) ""; opts.len = 0; } /* stack: subj regex repl */ re_comp.options = 0; flags = ngx_http_lua_ngx_re_parse_opts(L, &re_comp, &opts, 4); if (flags & NGX_LUA_RE_COMPILE_ONCE) { lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); pool = lmcf->pool; dd("server pool %p", lmcf->pool); lua_pushlightuserdata(L, &ngx_http_lua_regex_cache_key); lua_rawget(L, LUA_REGISTRYINDEX); /* table */ lua_pushliteral(L, "s"); lua_pushinteger(L, tpl.len); lua_pushliteral(L, ":"); lua_pushvalue(L, 2); if (tpl.len != 0) { lua_pushvalue(L, 3); } dd("options size: %d", (int) sizeof(re_comp.options)); lua_pushlstring(L, (char *) &re_comp.options, sizeof(re_comp.options)); /* table regex opts */ if (tpl.len == 0) { lua_concat(L, 5); /* table key */ } else { lua_concat(L, 6); /* table key */ } lua_pushvalue(L, -1); /* table key key */ dd("regex cache key: %.*s", (int) (pat.len + sizeof(re_comp.options)), lua_tostring(L, -1)); lua_rawget(L, -3); /* table key re */ re = lua_touserdata(L, -1); lua_pop(L, 1); /* table key */ if (re) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua regex cache hit for sub regex \"%s\" with options " "\"%s\" and replace \"%s\"", pat.data, opts.data, func ? (u_char *) "<func>" : tpl.data); lua_pop(L, 2); dd("restoring regex %p, ncaptures %d, captures %p", re->regex, re->ncaptures, re->captures); re_comp.regex = re->regex; sd = re->regex_sd; re_comp.captures = re->ncaptures; cap = re->captures; ctpl = re->replace; if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; } else { ovecsize = (re->ncaptures + 1) * 3; } goto exec; } ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua regex cache miss for %ssub regex \"%s\" with options " "\"%s\" and replace \"%s\"", global ? "g" : "", pat.data, opts.data, func ? (u_char *) "<func>" : tpl.data); if (lmcf->regex_cache_entries >= lmcf->regex_cache_max_entries) { if (lmcf->regex_cache_entries == lmcf->regex_cache_max_entries) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "lua exceeding regex cache max entries (%i)", lmcf->regex_cache_max_entries); lmcf->regex_cache_entries++; } pool = r->pool; flags &= ~NGX_LUA_RE_COMPILE_ONCE; } } else { pool = r->pool; } re_comp.pattern = pat; re_comp.err.len = NGX_MAX_CONF_ERRSTR; re_comp.err.data = errstr; re_comp.pool = pool; dd("compiling regex"); ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua compiling %ssub regex \"%s\" with options \"%s\" " "(compile once: %d) (dfa mode: %d) (jit mode: %d)", global ? "g" : "", pat.data, opts.data, (flags & NGX_LUA_RE_COMPILE_ONCE) != 0, (flags & NGX_LUA_RE_MODE_DFA) != 0, (flags & NGX_LUA_RE_MODE_JIT) != 0); old_pool = ngx_http_lua_pcre_malloc_init(pool); rc = ngx_lua_regex_compile(&re_comp); ngx_http_lua_pcre_malloc_done(old_pool); if (rc != NGX_OK) { dd("compile failed"); re_comp.err.data[re_comp.err.len] = '\0'; msg = lua_pushfstring(L, "failed to compile regex \"%s\": %s", pat.data, re_comp.err.data); return luaL_argerror(L, 2, msg); } #if LUA_HAVE_PCRE_JIT if (flags & NGX_LUA_RE_MODE_JIT) { old_pool = ngx_http_lua_pcre_malloc_init(pool); sd = pcre_study(re_comp.regex, PCRE_STUDY_JIT_COMPILE, &msg); ngx_http_lua_pcre_malloc_done(old_pool); # if (NGX_DEBUG) dd("sd = %p", sd); if (msg != NULL) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre study failed with PCRE_STUDY_JIT_COMPILE: %s (%p)", msg, sd); } if (sd != NULL) { int jitted; old_pool = ngx_http_lua_pcre_malloc_init(pool); pcre_fullinfo(re_comp.regex, sd, PCRE_INFO_JIT, &jitted); ngx_http_lua_pcre_malloc_done(old_pool); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre JIT compiling result: %d", jitted); } # endif /* NGX_DEBUG */ } else { old_pool = ngx_http_lua_pcre_malloc_init(pool); sd = pcre_study(re_comp.regex, 0, &msg); ngx_http_lua_pcre_malloc_done(old_pool); # if (NGX_DEBUG) dd("sd = %p", sd); if (msg != NULL) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre_study failed with PCRE_STUDY_JIT_COMPILE: %s (%p)", msg, sd); } # endif /* NGX_DEBUG */ } #else /* LUA_HAVE_PCRE_JIT */ if (flags & NGX_LUA_RE_MODE_JIT) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "your pcre build does not have JIT support and " "the \"j\" regex option is ignored"); } #endif /* LUA_HAVE_PCRE_JIT */ dd("compile done, captures %d", re_comp.captures); if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; } else { ovecsize = (re_comp.captures + 1) * 3; } cap = ngx_palloc(pool, ovecsize * sizeof(int)); if (cap == NULL) { flags &= ~NGX_LUA_RE_COMPILE_ONCE; msg = "out of memory"; goto error; } if (func) { ctpl = NULL; } else { ctpl = ngx_palloc(pool, sizeof(ngx_http_lua_complex_value_t)); if (ctpl == NULL) { flags &= ~NGX_LUA_RE_COMPILE_ONCE; msg = "out of memory"; goto error; } if ((flags & NGX_LUA_RE_COMPILE_ONCE) && tpl.len != 0) { /* copy the string buffer pointed to by tpl.data from Lua VM */ p = ngx_palloc(pool, tpl.len + 1); if (p == NULL) { flags &= ~NGX_LUA_RE_COMPILE_ONCE; msg = "out of memory"; goto error; } ngx_memcpy(p, tpl.data, tpl.len); p[tpl.len] = '\0'; tpl.data = p; } ngx_memzero(&ccv, sizeof(ngx_http_lua_compile_complex_value_t)); ccv.pool = pool; ccv.log = r->connection->log; ccv.value = &tpl; ccv.complex_value = ctpl; if (ngx_http_lua_compile_complex_value(&ccv) != NGX_OK) { ngx_pfree(pool, cap); ngx_pfree(pool, ctpl); if ((flags & NGX_LUA_RE_COMPILE_ONCE) && tpl.len != 0) { ngx_pfree(pool, tpl.data); } if (sd) { ngx_http_lua_regex_free_study_data(pool, sd); } ngx_pfree(pool, re_comp.regex); return luaL_error(L, "bad template for substitution: \"%s\"", lua_tostring(L, 3)); } } if (flags & NGX_LUA_RE_COMPILE_ONCE) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua saving compiled sub regex (%d captures) into the cache " "(entries %i)", re_comp.captures, lmcf ? lmcf->regex_cache_entries : 0); re = ngx_palloc(pool, sizeof(ngx_http_lua_regex_t)); if (re == NULL) { return luaL_error(L, "out of memory"); } dd("saving regex %p, ncaptures %d, captures %p", re_comp.regex, re_comp.captures, cap); re->regex = re_comp.regex; re->regex_sd = sd; re->ncaptures = re_comp.captures; re->captures = cap; re->replace = ctpl; lua_pushlightuserdata(L, re); /* table key value */ lua_rawset(L, -3); /* table */ lua_pop(L, 1); if (lmcf) { lmcf->regex_cache_entries++; } } exec: count = 0; offset = 0; for (;;) { if (subj.len == 0) { break; } if (flags & NGX_LUA_RE_MODE_DFA) { #if LUA_HAVE_PCRE_DFA int ws[NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT]; rc = ngx_http_lua_regex_dfa_exec(re_comp.regex, sd, &subj, offset, cap, ovecsize, ws, NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT); #else /* LUA_HAVE_PCRE_DFA */ msg = "at least pcre 6.0 is required for the DFA mode"; goto error; #endif /* LUA_HAVE_PCRE_DFA */ } else { rc = ngx_http_lua_regex_exec(re_comp.regex, sd, &subj, offset, cap, ovecsize); } if (rc == NGX_REGEX_NO_MATCHED) { break; } if (rc < 0) { msg = lua_pushfstring(L, ngx_regex_exec_n " failed: %d on \"%s\" " "using \"%s\"", (int) rc, subj.data, pat.data); goto error; } if (rc == 0) { if (flags & NGX_LUA_RE_MODE_DFA) { rc = 1; } else { msg = "capture size too small"; goto error; } } dd("rc = %d", (int) rc); count++; if (count == 1) { luaL_buffinit(L, &luabuf); } if (func) { lua_pushvalue(L, -1); lua_createtable(L, rc - 1 /* narr */, 1 /* nrec */); for (i = 0, n = 0; i < rc; i++, n += 2) { dd("capture %d: %d %d", (int) i, cap[n], cap[n + 1]); if (cap[n] < 0) { lua_pushnil(L); } else { lua_pushlstring(L, (char *) &subj.data[cap[n]], cap[n + 1] - cap[n]); dd("pushing capture %s at %d", lua_tostring(L, -1), (int) i); } lua_rawseti(L, -2, (int) i); } dd("stack size at call: %d", lua_gettop(L)); lua_call(L, 1 /* nargs */, 1 /* nresults */); type = lua_type(L, -1); switch (type) { case LUA_TNUMBER: case LUA_TSTRING: tpl.data = (u_char *) lua_tolstring(L, -1, &tpl.len); break; default: msg = lua_pushfstring(L, "string or number expected to be " "returned by the replace function, got %s", lua_typename(L, type)); return luaL_argerror(L, 3, msg); } luaL_addlstring(&luabuf, (char *) &subj.data[offset], cap[0] - offset); luaL_addlstring(&luabuf, (char *) tpl.data, tpl.len); lua_pop(L, 1); offset = cap[1]; if (global) { continue; } break; } rc = ngx_http_lua_complex_value(r, &subj, offset, rc, cap, ctpl, &luabuf); if (rc != NGX_OK) { msg = lua_pushfstring(L, "failed to eval the template for " "replacement: \"%s\"", tpl.data); goto error; } offset = cap[1]; if (global) { continue; } break; } if (count == 0) { dd("no match, just the original subject"); lua_settop(L, 1); } else { if (offset != (int) subj.len) { dd("adding trailer: %s (len %d)", &subj.data[offset], (int) (subj.len - offset)); luaL_addlstring(&luabuf, (char *) &subj.data[offset], subj.len - offset); } luaL_pushresult(&luabuf); dd("the dst string: %s", lua_tostring(L, -1)); } if (!(flags & NGX_LUA_RE_COMPILE_ONCE)) { if (sd) { ngx_http_lua_regex_free_study_data(pool, sd); } if (re_comp.regex) { ngx_pfree(pool, re_comp.regex); } if (ctpl) { ngx_pfree(pool, ctpl); } if (cap) { ngx_pfree(pool, cap); } } lua_pushinteger(L, count); return 2; error: if (!(flags & NGX_LUA_RE_COMPILE_ONCE)) { if (sd) { ngx_http_lua_regex_free_study_data(pool, sd); } if (re_comp.regex) { ngx_pfree(pool, re_comp.regex); } if (ctpl) { ngx_pfree(pool, ctpl); } if (cap) { ngx_pfree(pool, cap); } } return luaL_error(L, msg); }
static int ngx_http_lua_shdict_incr(lua_State *L) { int n; ngx_str_t key; uint32_t hash; ngx_int_t rc; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; double num; u_char *p; ngx_shm_zone_t *zone; double value; n = lua_gettop(L); if (n != 3) { return luaL_error(L, "expecting 3 arguments, but only seen %d", n); } if (lua_type(L, 1) != LUA_TLIGHTUSERDATA) { return luaL_error(L, "bad \"zone\" argument"); } zone = lua_touserdata(L, 1); if (zone == NULL) { return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); } ctx = zone->data; if (lua_isnil(L, 2)) { lua_pushnil(L); lua_pushliteral(L, "nil key"); return 2; } key.data = (u_char *) luaL_checklstring(L, 2, &key.len); if (key.len == 0) { lua_pushnil(L); lua_pushliteral(L, "empty key"); return 2; } if (key.len > 65535) { lua_pushnil(L); lua_pushliteral(L, "key too long"); return 2; } hash = ngx_crc32_short(key.data, key.len); value = luaL_checknumber(L, 3); dd("looking up key %.*s in shared dict %.*s", (int) key.len, key.data, (int) ctx->name.len, ctx->name.data); ngx_shmtx_lock(&ctx->shpool->mutex); #if 1 ngx_http_lua_shdict_expire(ctx, 1); #endif rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); dd("shdict lookup returned %d", (int) rc); if (rc == NGX_DECLINED || rc == NGX_DONE) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnil(L); lua_pushliteral(L, "not found"); return 2; } /* rc == NGX_OK */ if (sd->value_type != LUA_TNUMBER || sd->value_len != sizeof(double)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnil(L); lua_pushliteral(L, "not a number"); return 2; } ngx_queue_remove(&sd->queue); ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); dd("setting value type to %d", (int) sd->value_type); p = sd->data + key.len; num = *(double *) p; num += value; ngx_memcpy(p, (double *) &num, sizeof(double)); ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnumber(L, num); lua_pushnil(L); return 2; }
static int ngx_http_lua_ngx_re_gmatch_iterator(lua_State *L) { ngx_http_lua_regex_ctx_t *ctx; ngx_http_request_t *r; int *cap; ngx_int_t rc; ngx_uint_t n; int i; ngx_str_t subj; int offset; const char *msg = NULL; /* upvalues in order: subj ctx offset */ subj.data = (u_char *) lua_tolstring(L, lua_upvalueindex(1), &subj.len); ctx = (ngx_http_lua_regex_ctx_t *) lua_touserdata(L, lua_upvalueindex(2)); offset = (int) lua_tointeger(L, lua_upvalueindex(3)); if (offset < 0) { lua_pushnil(L); return 1; } cap = ctx->captures; dd("offset %d, r %p, subj %s", (int) offset, ctx->request, subj.data); lua_pushlightuserdata(L, &ngx_http_lua_request_key); lua_rawget(L, LUA_GLOBALSINDEX); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } if (r != ctx->request || r->pool != ctx->request->pool) { return luaL_error(L, "attempt to use ngx.re.gmatch iterator in a " "request that did not create it"); } dd("regex exec..."); if (ctx->flags & NGX_LUA_RE_MODE_DFA) { #if LUA_HAVE_PCRE_DFA int ws[NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT]; rc = ngx_http_lua_regex_dfa_exec(ctx->regex, ctx->regex_sd, &subj, offset, cap, ctx->captures_len, ws, NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT); #else /* LUA_HAVE_PCRE_DFA */ msg = "at least pcre 6.0 is required for the DFA mode"; goto error; #endif /* LUA_HAVE_PCRE_DFA */ } else { rc = ngx_http_lua_regex_exec(ctx->regex, ctx->regex_sd, &subj, offset, cap, ctx->captures_len); } if (rc == NGX_REGEX_NO_MATCHED) { /* set upvalue "offset" to -1 */ lua_pushinteger(L, -1); lua_replace(L, lua_upvalueindex(3)); if (!(ctx->flags & NGX_LUA_RE_COMPILE_ONCE)) { if (ctx->regex_sd) { ngx_http_lua_regex_free_study_data(r->pool, ctx->regex_sd); ctx->regex_sd = NULL; } ngx_pfree(r->pool, cap); } lua_pushnil(L); return 1; } if (rc < 0) { msg = lua_pushfstring(L, ngx_regex_exec_n " failed: %d on \"%s\"", (int) rc, subj.data); goto error; } if (rc == 0) { if (ctx->flags & NGX_LUA_RE_MODE_DFA) { rc = 1; } else { goto error; } } dd("rc = %d", (int) rc); lua_createtable(L, rc - 1 /* narr */, 1 /* nrec */); for (i = 0, n = 0; i < rc; i++, n += 2) { dd("capture %d: %d %d", i, cap[n], cap[n + 1]); if (cap[n] < 0) { lua_pushnil(L); } else { lua_pushlstring(L, (char *) &subj.data[cap[n]], cap[n + 1] - cap[n]); dd("pushing capture %s at %d", lua_tostring(L, -1), (int) i); } lua_rawseti(L, -2, (int) i); } offset = cap[1]; if (offset == (ssize_t) subj.len) { offset = -1; if (!(ctx->flags & NGX_LUA_RE_COMPILE_ONCE)) { if (ctx->regex_sd) { ngx_http_lua_regex_free_study_data(r->pool, ctx->regex_sd); ctx->regex_sd = NULL; } ngx_pfree(r->pool, cap); } } lua_pushinteger(L, offset); lua_replace(L, lua_upvalueindex(3)); return 1; error: lua_pushinteger(L, -1); lua_replace(L, lua_upvalueindex(3)); if (!(ctx->flags & NGX_LUA_RE_COMPILE_ONCE)) { if (ctx->regex_sd) { ngx_http_lua_regex_free_study_data(r->pool, ctx->regex_sd); ctx->regex_sd = NULL; } ngx_pfree(r->pool, cap); } return luaL_error(L, msg); }
static int ngx_http_lua_shdict_get_helper(lua_State *L, int get_stale) { int n; ngx_str_t name; ngx_str_t key; uint32_t hash; ngx_int_t rc; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; ngx_str_t value; int value_type; double num; u_char c; ngx_shm_zone_t *zone; uint32_t user_flags = 0; n = lua_gettop(L); if (n != 2) { return luaL_error(L, "expecting exactly two arguments, " "but only seen %d", n); } zone = lua_touserdata(L, 1); if (zone == NULL) { return luaL_error(L, "bad \"zone\" argument"); } ctx = zone->data; name = ctx->name; if (lua_isnil(L, 2)) { lua_pushnil(L); lua_pushliteral(L, "nil key"); return 2; } key.data = (u_char *) luaL_checklstring(L, 2, &key.len); if (key.len == 0) { lua_pushnil(L); lua_pushliteral(L, "empty key"); return 2; } if (key.len > 65535) { lua_pushnil(L); lua_pushliteral(L, "key too long"); return 2; } hash = ngx_crc32_short(key.data, key.len); #if (NGX_DEBUG) ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "fetching key \"%V\" in shared dict \"%V\"", &key, &name); #endif /* NGX_DEBUG */ ngx_shmtx_lock(&ctx->shpool->mutex); #if 1 if (!get_stale) { ngx_http_lua_shdict_expire(ctx, 1); } #endif rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); dd("shdict lookup returns %d", (int) rc); if (rc == NGX_DECLINED || (rc == NGX_DONE && !get_stale)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnil(L); return 1; } /* rc == NGX_OK || (rc == NGX_DONE && get_stale) */ value_type = sd->value_type; dd("data: %p", sd->data); dd("key len: %d", (int) sd->key_len); value.data = sd->data + sd->key_len; value.len = (size_t) sd->value_len; switch (value_type) { case LUA_TSTRING: lua_pushlstring(L, (char *) value.data, value.len); break; case LUA_TNUMBER: if (value.len != sizeof(double)) { ngx_shmtx_unlock(&ctx->shpool->mutex); return luaL_error(L, "bad lua number value size found for key %s " "in shared_dict %s: %lu", key.data, name.data, (unsigned long) value.len); } num = *(double *) value.data; lua_pushnumber(L, num); break; case LUA_TBOOLEAN: if (value.len != sizeof(u_char)) { ngx_shmtx_unlock(&ctx->shpool->mutex); return luaL_error(L, "bad lua boolean value size found for key %s " "in shared_dict %s: %lu", key.data, name.data, (unsigned long) value.len); } c = *value.data; lua_pushboolean(L, c ? 1 : 0); break; default: ngx_shmtx_unlock(&ctx->shpool->mutex); return luaL_error(L, "bad value type found for key %s in " "shared_dict %s: %d", key.data, name.data, value_type); } user_flags = sd->user_flags; ngx_shmtx_unlock(&ctx->shpool->mutex); if (get_stale) { /* always return value, flags, stale */ if (user_flags) { lua_pushinteger(L, (lua_Integer) user_flags); } else { lua_pushnil(L); } lua_pushboolean(L, rc == NGX_DONE); return 3; } if (user_flags) { lua_pushinteger(L, (lua_Integer) user_flags); return 2; } return 1; }
/** * Destroys a t_string object before it is collected (__gc metamethod). */ static int impl_tstring_collect(lua_State *L) { t_string *t = static_cast<t_string *>(lua_touserdata(L, 1)); t->t_string::~t_string(); return 0; }
static int ngx_http_lua_shdict_flush_expired(lua_State *L) { ngx_queue_t *q, *prev; ngx_http_lua_shdict_node_t *sd; ngx_http_lua_shdict_ctx_t *ctx; ngx_shm_zone_t *zone; ngx_time_t *tp; int freed = 0; int attempts = 0; ngx_rbtree_node_t *node; uint64_t now; int n; n = lua_gettop(L); if (n != 1 && n != 2) { return luaL_error(L, "expecting 1 or 2 argument(s), but saw %d", n); } luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); zone = lua_touserdata(L, 1); if (zone == NULL) { return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); } if (n == 2) { attempts = luaL_checkint(L, 2); } ctx = zone->data; ngx_shmtx_lock(&ctx->shpool->mutex); if (ngx_queue_empty(&ctx->sh->queue)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnumber(L, 0); return 1; } tp = ngx_timeofday(); now = (uint64_t) tp->sec * 1000 + tp->msec; q = ngx_queue_last(&ctx->sh->queue); while (q != ngx_queue_sentinel(&ctx->sh->queue)) { prev = ngx_queue_prev(q); sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue); if (sd->expires != 0 && sd->expires <= now) { ngx_queue_remove(q); node = (ngx_rbtree_node_t *) ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); ngx_rbtree_delete(&ctx->sh->rbtree, node); ngx_slab_free_locked(ctx->shpool, node); freed++; if (attempts && freed == attempts) { break; } } q = prev; } ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnumber(L, freed); return 1; }
/* lpty_toLPty * * If the value at the given acceptable index is a full userdata, returns its block address. * Otherwise, returns NULL. * * Arguments: * L Lua State * index stack index where the userdata is expected */ static lPty* lpty_toLPty(lua_State *L, int index) { lPty *pty = (lPty*) lua_touserdata(L, index); return pty; }
static int ngx_http_lua_shdict_get_keys(lua_State *L) { ngx_queue_t *q, *prev; ngx_http_lua_shdict_node_t *sd; ngx_http_lua_shdict_ctx_t *ctx; ngx_shm_zone_t *zone; ngx_time_t *tp; int total = 0; int attempts = 1024; uint64_t now; int n; n = lua_gettop(L); if (n != 1 && n != 2) { return luaL_error(L, "expecting 1 or 2 argument(s), " "but saw %d", n); } luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); zone = lua_touserdata(L, 1); if (zone == NULL) { return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); } if (n == 2) { attempts = luaL_checkint(L, 2); } ctx = zone->data; ngx_shmtx_lock(&ctx->shpool->mutex); if (ngx_queue_empty(&ctx->sh->queue)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_createtable(L, 0, 0); return 1; } tp = ngx_timeofday(); now = (uint64_t) tp->sec * 1000 + tp->msec; /* first run through: get total number of elements we need to allocate */ q = ngx_queue_last(&ctx->sh->queue); while (q != ngx_queue_sentinel(&ctx->sh->queue)) { prev = ngx_queue_prev(q); sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue); if (sd->expires == 0 || sd->expires > now) { total++; if (attempts && total == attempts) { break; } } q = prev; } lua_createtable(L, total, 0); /* second run through: add keys to table */ total = 0; q = ngx_queue_last(&ctx->sh->queue); while (q != ngx_queue_sentinel(&ctx->sh->queue)) { prev = ngx_queue_prev(q); sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue); if (sd->expires == 0 || sd->expires > now) { lua_pushlstring(L, (char *) sd->data, sd->key_len); lua_rawseti(L, -2, ++total); if (attempts && total == attempts) { break; } } q = prev; } ngx_shmtx_unlock(&ctx->shpool->mutex); /* table is at top of stack */ return 1; }
int merger_map_newindex( lua_State *L ) { const char *field; if ( !lua_isstring( L, 2 ) ) { lua_pushstring( L, "Cannot index the map-userdata with a non-string." ); lua_error( L ); } field = lua_tostring( L, 2 ); if ( !strcmp( field, "mode" ) ) { const char *value; if ( !lua_isstring( L, 3 ) ) { lua_pushstring( L, "map.mode accepts only string values." ); lua_error( L ); } value = lua_tostring( L, 3 ); if ( !strcmp( value, "none" ) ) mode = NONE; else if ( !strcmp( value, "get_unlost" ) ) mode = GET_UNLOST; else if ( !strcmp( value, "following" ) || !strcmp( value, "follow" ) ) mode = FOLLOWING; else if ( !strcmp( value, "creating" ) || !strcmp( value, "create" ) ) mode = CREATING; else { lua_pushstring( L, "map.mode accepts only 'none', " "'get_unlost', 'following', or 'creating'." ); lua_error( L ); } } else if ( !strcmp( field, "current_room" ) ) { if ( lua_isnil( L, 3 ) ) { current_room = NULL; current_area = NULL; } else if ( !lua_isuserdata( L, 3 ) ) { lua_pushstring( L, "map.current_room accepts only 'nil' or a room-userdata." ); lua_error( L ); } else { ROOM_DATA *room; room = *(ROOM_DATA**) lua_touserdata( L, 3 ); current_room = room; if ( current_room ) current_area = current_room->area; } } else { lua_pushfstring( L, "'map' does not accept a writable '%s' property.", field ); lua_error( L ); } return 0; }
static int setTag(lua_State* L) { BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1)); barrier->SetTag(lua_tostring(L, 2), lua_tostring(L, 3)); return 0; }