static int tunpack (lua_State *L) { lua_Unsigned n; lua_Integer i = luaL_optinteger(L, 2, 1); lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); if (i > e) return 0; /* empty range */ n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) return luaL_error(L, "too many results to unpack"); for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ lua_geti(L, 1, i); } lua_geti(L, 1, e); /* push last element */ return (int)n; }
static int unpack (lua_State *L) { int i, e, n; luaL_checktype(L, 1, LUA_TTABLE); i = luaL_optint(L, 2, 1); e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1)); if (i > e) return 0; /* empty range */ n = e - i + 1; /* number of elements */ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ return luaL_error(L, "too many results to unpack"); lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ while (i++ < e) /* push arg[i + 1...e] */ lua_rawgeti(L, 1, i); return n; }
int luagi_merge_analysis( lua_State *L ) { git_repository **repo = checkrepo( L, 1 ); int len = luaL_len( L, 2 ); const git_annotated_commit *commits[ len ]; fill_annotated_commit( L, 2, commits, len ); git_merge_analysis_t anout; git_merge_preference_t pout; if( git_merge_analysis( &anout, &pout, *repo, commits, len ) ) { return ltk_push_git_error( L ); } const char *aoutstr = NONE; const char *poutstr = NONE; switch( anout ) { case GIT_MERGE_ANALYSIS_NONE: break; case GIT_MERGE_ANALYSIS_NORMAL: aoutstr = NORMAL; break; case GIT_MERGE_ANALYSIS_UP_TO_DATE: aoutstr = UP_TO_DATE; break; case GIT_MERGE_ANALYSIS_FASTFORWARD: aoutstr = FASTFORWARD; break; case GIT_MERGE_ANALYSIS_UNBORN: aoutstr = UNBORN; break; } lua_pushstring( L, aoutstr ); switch( pout ) { case GIT_MERGE_PREFERENCE_NONE: break; case GIT_MERGE_PREFERENCE_NO_FASTFORWARD: poutstr = NO_FASTFORWARD; break; case GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY: poutstr = FASTFORWARD_ONLY; break; } lua_pushstring( L, poutstr ); return 2; }
/* ** Push on the stack the contents of table 'arg' from 1 to #arg */ static int lnode_pushargs(lua_State *L) { int i, n; if (lua_getglobal(L, "arg") != LUA_TTABLE) { luaL_error(L, "'arg' is not a table"); } n = (int)luaL_len(L, -1); luaL_checkstack(L, n + 3, "too many arguments to script"); for (i = 1; i <= n; i++) { lua_rawgeti(L, -i, i); } lua_remove(L, -i); /* remove table from the stack */ return n; }
static int unpack (lua_State *L) { int i, e; unsigned int n; luaL_checktype(L, 1, LUA_TTABLE); i = luaL_optint(L, 2, 1); e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1)); if (i > e) return 0; /* empty range */ n = (unsigned int)e - (unsigned int)i; /* number of elements minus 1 */ if (n > (INT_MAX - 10) || !lua_checkstack(L, ++n)) return luaL_error(L, "too many results to unpack"); lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ while (i++ < e) /* push arg[i + 1...e] */ lua_rawgeti(L, 1, i); return n; }
static int unpack (lua_State *L) { lua_Integer i, e; lua_Unsigned n; luaL_checktype(L, 1, LUA_TTABLE); i = luaL_optinteger(L, 2, 1); e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); if (i > e) return 0; /* empty range */ n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, ++n)) return luaL_error(L, "too many results to unpack"); do { /* must have at least one element */ lua_rawgeti(L, 1, i); /* push arg[i..e] */ } while (i++ < e); return n; }
/*luadoc @function lcd.drawCombobox(x, y, w, list, idx [, flags]) Draws a combo box @param x,y (positive numbers) top left corner position @param w (number) width of combo box in pixels @param list (table) combo box elements, each element is a string @param idx (integer) index of entry to highlight @param page (number) page number @param flags (unsigned number) drawing flags, the flags can not be combined: * `BLINK` combo box is expanded * `INVERS` combo box collapsed, text inversed * `0 or not present` combo box collapsed, text normal @status current Introduced in 2.0.0 */ static int luaLcdDrawCombobox(lua_State *L) { if (!luaLcdAllowed) return 0; int x = luaL_checkinteger(L, 1); int y = luaL_checkinteger(L, 2); int w = luaL_checkinteger(L, 3); luaL_checktype(L, 4, LUA_TTABLE); int count = luaL_len(L, 4); /* get size of table */ int idx = luaL_checkinteger(L, 5); unsigned int flags = luaL_optunsigned(L, 6, 0); if (idx >= count) { // TODO error } if (flags & BLINK) { drawFilledRect(x, y, w-9, count*9+2, SOLID, ERASE); lcd_rect(x, y, w-9, count*9+2); for (int i=0; i<count; i++) { lua_rawgeti(L, 4, i+1); const char * item = luaL_checkstring(L, -1); lcd_putsAtt(x+2, y+2+9*i, item, 0); } drawFilledRect(x+1, y+1+9*idx, w-11, 9); drawFilledRect(x+w-10, y, 10, 11, SOLID, ERASE); lcd_rect(x+w-10, y, 10, 11); } else if (flags & INVERS) { drawFilledRect(x, y, w, 11); drawFilledRect(x+w-9, y+1, 8, 9, SOLID, ERASE); lua_rawgeti(L, 4, idx+1); const char * item = luaL_checkstring(L, -1); lcd_putsAtt(x+2, y+2, item, INVERS); } else { drawFilledRect(x, y, w, 11, SOLID, ERASE); lcd_rect(x, y, w, 11); drawFilledRect(x+w-10, y+1, 9, 9, SOLID); lua_rawgeti(L, 4, idx+1); const char * item = luaL_checkstring(L, -1); lcd_putsAtt(x+2, y+2, item, 0); } lcd_hline(x+w-8, y+3, 6); lcd_hline(x+w-8, y+5, 6); lcd_hline(x+w-8, y+7, 6); return 0; }
static int readImageHeader(lua_State *L) { luaL_checktype(L, 2, LUA_TTABLE); int k, N = luaL_len(L, 2); unsigned int j[2]; gdcm::Tag tags[N]; for (k=0; k < N; k++) { lua_rawgeti(L, 2, k+1); gettag(L, j); lua_pop(L, 1); tags[k] = gdcm::Tag(j[0], j[1]); } lua_pushinteger(L, getHeader(L, luaL_checkstring(L, 1), tags, N)); // number of missing values return 2; }
static int Init(lua_State *L) { int table_index; int argc, i; char **argv; const char *arg; if(lua_isnoneornil(L, 1)) argc = 1; else { if(!lua_istable(L,1)) return luaL_argerror(L, 1, "table expected"); table_index = 1; argc = luaL_len(L, table_index) + 1; } argv = (char**)malloc(sizeof(char*) * argc); if(argv == NULL) return luaL_error(L, "cannot allocate memory"); //argv[0] = "moonglut"; argv[0] = strdup("moonglut"); if(argc > 1) { for(i = 1; i < argc; i++) { lua_geti(L, table_index, i); arg = luaL_checkstring(L, -1); argv[i] = strdup(arg); if(argv[i] == NULL) return luaL_error(L, "cannot allocate memory"); lua_pop(L, 1); } } glutInit(&argc, argv); /* return the modified arg table */ lua_newtable(L); table_index = lua_gettop(L); for(i = 1; i < argc; i++) { lua_pushstring(L, argv[i]); lua_seti(L, table_index, i); } return 1; }
bool eae6320::cMeshBuilder::LoadTableValues_vertices_values(lua_State& io_luaState) { m_vertexCount = luaL_len(&io_luaState, -1); m_vertexData = new eae6320::cMeshBuilder::sVertex[m_vertexCount]; for (unsigned int i = 1; i <= m_vertexCount; ++i) { lua_pushinteger(&io_luaState, i); lua_gettable(&io_luaState, -2); if (lua_istable(&io_luaState, -1)) { if (!LoadTableValues_vertices_values_position(io_luaState, i - 1)) { return false; } if (!LoadTableValues_vertices_values_normal(io_luaState, i - 1)) { return false; } if (!LoadTableValues_vertices_values_color(io_luaState, i - 1)) { return false; } if (!LoadTableValues_vertices_values_texture(io_luaState, i - 1)) { return false; } } else { std::stringstream errorMessage; errorMessage << "The value at \"" << i << "\" must be a table " "(instead of a " << luaL_typename(&io_luaState, -1) << ")\n"; eae6320::OutputErrorMessage(errorMessage.str().c_str()); // Pop the vertex value table lua_pop(&io_luaState, 1); return false; } // Pop the vertex value table lua_pop(&io_luaState, 1); } return true; }
int syscmd(lua_State *L) { if (luaT_check(L, 1, LUA_TTABLE)) { lua_pushinteger(L, 1); lua_gettable(L, -2); std::wstring cmd(luaT_towstring(L, -1)); lua_pop(L, 1); if (cmd == L"sound" || cmd == L"play") { std::vector<std::wstring> params; int n = luaL_len(L, -1); std::wstring text; for (int i=2; i<=n; ++i) { lua_pushinteger(L, i); lua_gettable(L, -2); if (!lua_isstring(L, -1)) { luaT_pushwstring(L, L"Неверные параметры"); return 1; } else { std::wstring p(luaT_towstring(L, -1)); params.push_back(p); } lua_pop(L, 1); } lua_pop(L, 1); std::wstring error; if (cmd == L"play") player->runPlayCommand(params, &error); else player->runCommand(params, &error); if (!error.empty()) luaT_pushwstring(L, error.c_str() ); else lua_pushnil(L); return 1; } } return 1; }
static int tconcat (lua_State *L) { luaL_Buffer b; size_t lsep; int i, last; const char *sep = luaL_optlstring(L, 2, "", &lsep); luaL_checktype(L, 1, LUA_TTABLE); i = luaL_optint(L, 3, 1); last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1)); luaL_buffinit(L, &b); for (; i < last; i++) { addfield(L, &b, i); luaL_addlstring(&b, sep, lsep); } if (i == last) /* add last value (if interval was not empty) */ addfield(L, &b, i); luaL_pushresult(&b); return 1; }
int lsprite_set_anim(lua_State* L) { struct sprite* self = (struct sprite*)lua_touserdata(L, 1); luaL_checktype(L, 2, LUA_TTABLE); int len = luaL_len(L, 2); struct array* frames = array_new(len); for (int i = 1; i <= len; ++i) { lua_rawgeti(L, -1, i); struct sprite_frame* frame = lua_touserdata(L, -1); array_push_back(frames, frame); lua_pop(L, 1); } struct anim* anim = anim_new(frames); sprite_set_anim(self, anim); array_free(frames); return 0; }
// This one I literally copied and pasted from Lua and added the count check. int luaL_unpack_exact (lua_State *L, int count) { int i, e, n; int tablepos = lua_gettop(L); luaL_checktype(L, -1, LUA_TTABLE); i = luaL_optint(L, tablepos + 1, 1); e = luaL_opt(L, luaL_checkint, tablepos + 2, luaL_len(L, tablepos)); if (i > e) return 0; /* empty range */ n = e - i + 1; /* number of elements */ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ return luaL_error(L, "too many results to unpack"); if (n != count) return luaL_error(L, "wrong number of results to unpack (%d, expected %d)", n, count); lua_rawgeti(L, tablepos, i); /* push arg[i] (avoiding overflow problems) */ while (i++ < e) /* push arg[i + 1...e] */ lua_rawgeti(L, tablepos, i); return n; }
bool eae6320::cMeshBuilder::LoadTableValues_indices_values(lua_State& io_luaState) { const unsigned int triangleCount = luaL_len(&io_luaState, -1); const unsigned int vertexCountPerTriangle = 3; m_indexCount = triangleCount * vertexCountPerTriangle; m_indexData = new uint32_t[m_indexCount]; int k = 0; for (unsigned int i = 1; i <= triangleCount; ++i) { lua_pushinteger(&io_luaState, i); lua_gettable(&io_luaState, -2); if (lua_istable(&io_luaState, -1)) { for (unsigned int j = 1; j <= vertexCountPerTriangle; ++j) { lua_pushinteger(&io_luaState, j); lua_gettable(&io_luaState, -2); m_indexData[k] = (uint32_t)lua_tointeger(&io_luaState, -1); lua_pop(&io_luaState, 1); k++; } } else { std::stringstream errorMessage; errorMessage << "The value at \"" << i << "\" must be a table " "(instead of a " << luaL_typename(&io_luaState, -1) << ")\n"; eae6320::OutputErrorMessage(errorMessage.str().c_str()); // Pop the vertex value table lua_pop(&io_luaState, 1); return false; } // Pop the vertex value table lua_pop(&io_luaState, 1); } return true; }
static int lua_spi_transfer(lua_State *L) { spi_t *spi; uint8_t *buf; unsigned int i, len; int ret; spi = luaL_checkudata(L, 1, "periphery.SPI"); lua_spi_checktype(L, 2, LUA_TTABLE); len = luaL_len(L, 2); if ((buf = malloc(len)) == NULL) return lua_spi_error(L, SPI_ERROR_ALLOC, errno, "Error: allocating memory"); /* Convert byte table to byte buffer */ for (i = 0; i < len; i++) { lua_pushunsigned(L, i+1); lua_gettable(L, -2); if (!lua_isnumber(L, -1)) { free(buf); return lua_spi_error(L, SPI_ERROR_ARG, 0, "Error: invalid element index %d in bytes table.", i+1); } buf[i] = lua_tounsigned(L, -1); lua_pop(L, 1); } if ((ret = spi_transfer(spi, buf, buf, len)) < 0) { free(buf); return lua_spi_error(L, ret, spi_errno(spi), "Error: %s", spi_errmsg(spi)); } /* Convert byte buffer back to bytes table */ for (i = 0; i < len; i++) { lua_pushunsigned(L, i+1); lua_pushunsigned(L, buf[i]); lua_settable(L, -3); } free(buf); return 1; }
static int tconcat (lua_State *L) { TabA ta; luaL_Buffer b; size_t lsep; lua_Integer i, last; const char *sep = luaL_optlstring(L, 2, "", &lsep); checktab(L, 1, &ta); i = luaL_optinteger(L, 3, 1); last = luaL_opt(L, luaL_checkinteger, 4, luaL_len(L, 1)); luaL_buffinit(L, &b); for (; i < last; i++) { addfield(L, &b, &ta, i); luaL_addlstring(&b, sep, lsep); } if (i == last) /* add last value (if interval was not empty) */ addfield(L, &b, &ta, i); luaL_pushresult(&b); return 1; }
static int base_for_multiple( lua_State *L, int (*func)( git_oid *out, git_repository *name, size_t length, const git_oid inarr [] ) ) { git_repository **repo = checkrepo( L, 1 ); luaL_checktype( L, tidx, LUA_TTABLE ); int count = luaL_len( L, tidx ); git_oid input_array [ count ]; for( int i = 1; i <= count; i++ ) { lua_pushinteger( L, i ); lua_gettable( L, tidx ); luagi_check_oid( &input_array[i-1], L, -1 ); } git_oid out; if( func( &out, *repo, count, input_array ) ) { return ltk_push_git_error( L ); } return luagi_push_oid( L, &out ); }
static int lua_mmio_write(lua_State *L) { mmio_t *mmio; uint8_t *buf; uintptr_t offset; unsigned int i, len; int ret; mmio = luaL_checkudata(L, 1, "periphery.MMIO"); lua_mmio_checktype(L, 2, LUA_TNUMBER); lua_mmio_checktype(L, 3, LUA_TTABLE); offset = lua_tounsigned(L, 2); len = luaL_len(L, 3); if ((buf = malloc(len)) == NULL) return lua_mmio_error(L, MMIO_ERROR_ALLOC, errno, "Error: allocating memory"); /* Convert byte table to byte buffer */ for (i = 0; i < len; i++) { lua_pushunsigned(L, i+1); lua_gettable(L, -2); if (!lua_isnumber(L, -1)) { free(buf); return lua_mmio_error(L, MMIO_ERROR_ARG, 0, "Error: invalid element index %d in bytes table.", i+1); } buf[i] = lua_tounsigned(L, -1); lua_pop(L, 1); } if ((ret = mmio_write(mmio, offset, buf, len)) < 0) { free(buf); return lua_mmio_error(L, ret, mmio_errno(mmio), "Error: %s", mmio_errmsg(mmio)); } free(buf); return 0; }
static int luaFuncExeDirs(lua_State* l) { Block* b = mbGetActiveContext()->ActiveBlock(); if (!b) { MB_LOGERROR("must be within a block"); mbExitError(); } luaL_checktype(l, 1, LUA_TTABLE); int tableLen = luaL_len(l, 1); StringVector strings; for (int i = 1; i <= tableLen; ++i) { lua_rawgeti(l, 1, i); strings.push_back(std::string()); mbLuaToStringExpandMacros(&strings.back(), b, l, -1); } b->AddExeDirs(strings); return 0; }
int luagi_commit_create( lua_State *L ) { git_repository** repo = checkrepo( L, 1 ); git_signature *author; int ret = table_to_signature( L, &author, 2 ); git_signature *committer; ret = table_to_signature( L, &committer, 3 ); const char* message = luaL_checkstring( L, 4 ); git_tree** tree = (git_tree**) luaL_checkudata( L, 5, LUAGI_TREE_FUNCS ); // table of parents luaL_checktype( L, 6, LUA_TTABLE ); unsigned int n = luaL_len( L, 6 ); const git_commit* parents[n]; for( unsigned int i = 0; i < n; i++ ) { lua_rawgeti( L, 6, i + 1 ); parents[i] = *( (git_commit**) luaL_checkudata( L, -1, LUAGI_COMMIT_FUNCS ) ); } lua_pop( L, n ); const char* update_ref = luaL_optstring( L, 7, NULL ); const char* encoding = luaL_optstring( L, 8, NULL ); git_oid oid; ret = git_commit_create( &oid, *repo, update_ref, author, committer, encoding, message, *tree, n, parents ); git_signature_free( author ); git_signature_free( committer ); if( ret != 0 ) { return ltk_push_git_error( L ); } return luagi_push_oid( L, &oid ); }
static int l_filter(lua_State *L) { int i, j, n, res; luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 2, LUA_TFUNCTION); n = luaL_len(L, 1); lua_newtable(L); for (j = i = 1; i <= n; i++) { lua_pushvalue(L, 2); lua_rawgeti(L, 1, i); lua_call(L, 1, 1); res = lua_toboolean(L, -1); lua_pop(L, 1); if (res) { lua_rawgeti(L, 1, i); lua_rawseti(L, -2, j); j++; } } return 1; }
static int method_send(module_data_t *mod) { switch(lua_type(lua, -1)) { case LUA_TSTRING: { const int content_size = luaL_len(lua, 2); const char *content = lua_tostring(lua, 2); // TODO: send partially if(asc_socket_send(mod->sock, (void *)content, content_size) != content_size) asc_log_error(MSG("failed to send content")); break; } case LUA_TTABLE: { send_request(mod); break; } default: break; } return 0; }
long long LuaState::Length(int index) const { return luaL_len(m_state, index); }
size_t LuaStack::TableLength(int i_index) { return luaL_len(state, i_index); }
unsigned int NzLuaInstance::Length(int index) const { return luaL_len(m_state, index); }
bool cMeshBuilder::LoadTableValues_parameters_values(lua_State& io_luaState, const char * field_value) { if (strcmp(field_value, "vertex") == 0) { //lua_pushnil(&io_luaState); //std::cout << "in Para-2metres: \n"; //std::cout << "Length " << luaL_len(&io_luaState,-2) << "\n"; //while (lua_next(&io_luaState, -2)) int lengthVector = luaL_len(&io_luaState, -1); //std::cout << "Length " << lengthVector << "\n"; const int numberOfParameters = 17; float * vertexinfo = new float[lengthVector * numberOfParameters]; unsigned int vertexInfo_index = 0; for (int i = 0; i < lengthVector; i++) { lua_pushinteger(&io_luaState, i+1); lua_gettable(&io_luaState, -2); //if (lua_istable(&io_luaState, -1)) const int lengthInfo = static_cast<const int>(luaL_len(&io_luaState, -1)); float key3[numberOfParameters] = {}; for (int j = 0; j < lengthInfo; j++) { lua_pushinteger(&io_luaState, j+1); lua_gettable(&io_luaState, -2); *(vertexinfo + vertexInfo_index) = static_cast< float >(lua_tonumber(&io_luaState, -1)); key3[j] = static_cast< float >(lua_tonumber(&io_luaState, -1)); vertexInfo_index++; lua_pop(&io_luaState, 1); } lua_pop(&io_luaState, 1); } _rout->write((char*)vertexinfo, sizeof(float)* numberOfParameters * lengthVector); delete[] vertexinfo; } else if (strcmp(field_value, "indices") == 0) { int lengthFaces = luaL_len(&io_luaState, -1); int * indicesinfo = new int[lengthFaces * 6]; unsigned int indicesInfo_index = 0; for (int i = 0; i < lengthFaces; i++) { lua_pushinteger(&io_luaState, i + 1); lua_gettable(&io_luaState, -2); //if (lua_istable(&io_luaState, -1)) const int lengthInfo = static_cast<const int>(luaL_len(&io_luaState, -1)); for (int j = 0; j < lengthInfo; j++) { lua_pushinteger(&io_luaState, j + 1); lua_gettable(&io_luaState, -2); *(indicesinfo + indicesInfo_index) = static_cast< int >(lua_tonumber(&io_luaState, -1)); indicesInfo_index++; lua_pop(&io_luaState, 1); } lua_pop(&io_luaState, 1); } _rout->write((char*)indicesinfo, sizeof(int)* 6 * lengthFaces); delete[] indicesinfo; } return true; }
static int test_len (lua_State *L) { luaL_checkany(L, 1); lua_len(L, 1); lua_pushinteger(L, luaL_len(L, 1)); return 2; }
static void send_request(module_data_t *mod) { if(mod->timeout_timer) { asc_timer_destroy(mod->timeout_timer); mod->timeout_timer = NULL; } mod->timeout_timer = asc_timer_init(REQUEST_TIMEOUT_INTERVAL, timeout_callback, mod); mod->ready_state = 0; // default values static const char def_method[] = "GET"; static const char def_uri[] = "/"; static const char def_version[] = "HTTP/1.1"; char *buffer = mod->buffer; const char *buffer_tail = mod->buffer + HTTP_BUFFER_SIZE; lua_getfield(lua, -1, __method); buffer_set_text(&buffer, buffer_tail - buffer , def_method, sizeof(def_method) - 1, 0); lua_pop(lua, 1); // method lua_getfield(lua, -1, __uri); buffer_set_text(&buffer, buffer_tail - buffer , def_uri, sizeof(def_uri) - 1, 0); lua_pop(lua, 1); // uri lua_getfield(lua, -1, __version); buffer_set_text(&buffer, buffer_tail - buffer , def_version, sizeof(def_version) - 1, 1); lua_pop(lua, 1); // version lua_getfield(lua, -1, __headers); if(lua_type(lua, -1) == LUA_TTABLE) { for(lua_pushnil(lua); lua_next(lua, -2); lua_pop(lua, 1)) buffer_set_text(&buffer, buffer_tail - buffer, "", 0, 1); } lua_pop(lua, 1); // headers lua_pushnil(lua); buffer_set_text(&buffer, buffer_tail - buffer, "", 0, 1); lua_pop(lua, 1); // empty line const int header_size = buffer - mod->buffer; if(asc_socket_send(mod->sock, mod->buffer, header_size) != header_size) { asc_log_error(MSG("failed to send header")); // call error return; } // send request content lua_getfield(lua, -1, __content); if(!lua_isnil(lua, -1)) { const int content_size = luaL_len(lua, -1); const char *content = lua_tostring(lua, -1); // TODO: send partially if(asc_socket_send(mod->sock, (void *)content, content_size) != content_size) asc_log_error(MSG("failed to send content")); } lua_pop(lua, 1); // content }
static void on_read(void *arg) { module_data_t *mod = arg; asc_timer_destroy(mod->timeout_timer); mod->timeout_timer = NULL; char *buffer = mod->buffer; int skip = mod->ts_len_in_buf; int r = asc_socket_recv(mod->sock, buffer + skip, HTTP_BUFFER_SIZE - skip); if(r <= 0) { on_close(mod); return; } r += mod->ts_len_in_buf;// Imagine that we've received more (+ previous part) int response = 0; parse_match_t m[4]; // parse response if(mod->ready_state == 0) { if(!http_parse_response(buffer, m)) { call_error(mod, "invalid response"); on_close(mod); return; } lua_newtable(lua); response = lua_gettop(lua); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref); lua_pushvalue(lua, -2); // duplicate table lua_setfield(lua, -2, __response); lua_pop(lua, 1); // options lua_pushnumber(lua, atoi(&buffer[m[2].so])); lua_setfield(lua, response, __code); lua_pushlstring(lua, &buffer[m[3].so], m[3].eo - m[3].so); lua_setfield(lua, response, __message); skip = m[0].eo; mod->ready_state = 1; if(skip >= r) { lua_pop(lua, 1); // response return; } } // parse headers if(mod->ready_state == 1) { if(!response) { lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref); lua_getfield(lua, -1, __response); lua_remove(lua, -2); response = lua_gettop(lua); } int headers_count = 0; lua_getfield(lua, response, __headers); if(lua_isnil(lua, -1)) { lua_pop(lua, 1); lua_newtable(lua); lua_pushvalue(lua, -1); lua_setfield(lua, response, __headers); } else { headers_count = luaL_len(lua, -1); } const int headers = lua_gettop(lua); while(skip < r && http_parse_header(&buffer[skip], m)) { const size_t so = m[1].so; const size_t length = m[1].eo - so; if(!length) { skip += m[0].eo; mod->ready_state = 2; break; } const char *header = &buffer[skip + so]; if(!strncasecmp(header, __transfer_encoding, sizeof(__transfer_encoding) - 1)) { const char *val = &header[sizeof(__transfer_encoding) - 1]; if(!strncasecmp(val, __chunked, sizeof(__chunked) - 1)) mod->is_chunked = 1; } else if(!strncasecmp(header, __connection, sizeof(__connection) - 1)) { const char *val = &header[sizeof(__connection) - 1]; if(!strncasecmp(val, __close, sizeof(__close) - 1)) mod->is_close = 1; else if(!strncasecmp(val, __keep_alive, sizeof(__keep_alive) - 1)) mod->is_keep_alive = 1; } else if(!strncasecmp(header, __content_length, sizeof(__content_length) - 1)) { const char *val = &header[sizeof(__content_length) - 1]; mod->is_content_length = 1; mod->chunk_left = strtoul(val, NULL, 10); } ++headers_count; lua_pushnumber(lua, headers_count); lua_pushlstring(lua, header, length); lua_settable(lua, headers); skip += m[0].eo; } lua_pop(lua, 1); // headers if(mod->ready_state == 2) { get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); lua_pushvalue(lua, response); lua_call(lua, 2, 0); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref); lua_pushnil(lua); lua_setfield(lua, -2, __response); lua_pop(lua, 1); // options } lua_pop(lua, 1); // response if(skip >= r) return; } // content if(mod->ready_state == 2) { /* Push to stream */ if (mod->is_ts) { int pos = skip - mod->ts_len_in_buf;// buffer rewind while (r - pos >= TS_PACKET_SIZE) { module_stream_send(mod, (uint8_t*)&mod->buffer[pos]); pos += TS_PACKET_SIZE; } int left = r - pos; if (left > 0) {//there is something usefull in the end of buffer, move it to begin if (pos > 0) memmove(&mod->buffer[0], &mod->buffer[pos], left); mod->ts_len_in_buf = left; } else {//all data is processed mod->ts_len_in_buf = 0; } } // Transfer-Encoding: chunked else if(mod->is_chunked) { while(skip < r) { if(!mod->chunk_left) { if(!http_parse_chunk(&buffer[skip], m)) { call_error(mod, "invalid chunk"); on_close(mod); return; } char cs_str[] = "00000000"; const size_t cs_size = m[1].eo - m[1].so; const size_t cs_skip = 8 - cs_size; memcpy(&cs_str[cs_skip], &buffer[skip], cs_size); uint8_t cs_hex[4]; str_to_hex(cs_str, cs_hex, sizeof(cs_hex)); mod->chunk_left = (cs_hex[0] << 24) | (cs_hex[1] << 16) | (cs_hex[2] << 8) | (cs_hex[3] ); skip += m[0].eo; if(!mod->chunk_left) { if(mod->is_keep_alive) { // keep-alive connection get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); lua_pushstring(lua, ""); lua_call(lua, 2, 0); } else { // close connection on_close(mod); } return; } } const size_t r_skip = r - skip; get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); if(mod->chunk_left < r_skip) { lua_pushlstring(lua, &buffer[skip], mod->chunk_left); lua_call(lua, 2, 0); skip += mod->chunk_left; mod->chunk_left = 0; if(buffer[skip] == '\r') ++skip; if(buffer[skip] == '\n') ++skip; else { call_error(mod, "invalid chunk"); on_close(mod); return; } } else { lua_pushlstring(lua, &buffer[skip], r_skip); lua_call(lua, 2, 0); mod->chunk_left -= r_skip; break; } } } // Content-Length else if(mod->is_content_length) { if(mod->chunk_left > 0) { const size_t r_skip = r - skip; get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); if(mod->chunk_left > r_skip) { lua_pushlstring(lua, &buffer[skip], r_skip); lua_call(lua, 2, 0); mod->chunk_left -= r_skip; } else { lua_pushlstring(lua, &buffer[skip], mod->chunk_left); lua_call(lua, 2, 0); mod->chunk_left = 0; if(mod->is_keep_alive) { // keep-alive connection get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); lua_pushstring(lua, ""); lua_call(lua, 2, 0); } else { // close connection on_close(mod); } return; } } } // Stream else { get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); lua_pushlstring(lua, &buffer[skip], r - skip); lua_call(lua, 2, 0); } } } /* on_read */