bool transferFunction(lua_State* toL, lua_State* fromL) { bool result = false; if (!lua_iscfunction(fromL, -1) && lua_isfunction(fromL, -1)) { try { TransferBuffer tb; if (lua_dump(fromL, functionWriter, &tb) == 0) { // sigh, was hoping to do this without any ifdefs... // alas, i don't see how this one can be avoided #if LUA_VERSION_NUM > 501 if (lua_load(toL, functionReader, &tb, "transferFunction", NULL) == 0) result = true; #else if (lua_load(toL, functionReader, &tb, "transferFunction") == 0) result = true; #endif } } catch (const std::exception& e) { (void) e; // catch a std::bad_alloc result = false; } } return result; }
static const char* luv_thread_dumped(lua_State* L, int idx, size_t* l) { if (lua_isstring(L, idx)) { return lua_tolstring(L, idx, l); } else { const char* buff = NULL; int top = lua_gettop(L); luaL_Buffer b; luaL_checktype(L, idx, LUA_TFUNCTION); lua_pushvalue(L, idx); luaL_buffinit(L, &b); #if LUA_VERSION_NUM>=503 int test_lua_dump = (lua_dump(L, thread_dump, &b, 1) == 0); #else int test_lua_dump = (lua_dump(L, thread_dump, &b) == 0); #endif if (test_lua_dump) { luaL_pushresult(&b); buff = lua_tolstring(L, -1, l); } else luaL_error(L, "Error: unable to dump given function"); lua_settop(L, top); return buff; } }
static const char *tek_lib_exec_dump(lua_State *L, size_t *len) { luaL_Buffer b; luaL_buffinit(L, &b); #if LUA_VERSION_NUM < 503 lua_dump(L, tek_lib_exec_write, &b); #else lua_dump(L, tek_lib_exec_write, &b, 0); #endif luaL_pushresult(&b); lua_remove(L, -2); return luaL_checklstring(L, -1, len); }
/** * @brief Attempts to compile a Lua script. * * @param filename Filename of the script. * @param buffer The buffer to store the script's compiled bytecode. * * @return true if it succeeds, false if it fails. */ bool CLuaScript::CompileScript(const char * filename, BytecodeBuffer & buffer) { // ensure that we wait until the last user's done executing their script. Guard lock(m_lock); /* Attempt to load the file */ int err = luaL_loadfile(m_luaState, filename); // If something bad happened, try to find an error. if (err != LUA_OK) { RetrieveLoadError(err, filename); return false; } // Everything's OK so far, the script has been loaded, now we need to start dumping it to bytecode. err = lua_dump(m_luaState, (lua_Writer)LoadBytecodeChunk, &buffer); if (err || buffer.empty()) { printf("ERROR: Failed to dump the Lua script `%s` to bytecode.\n", filename); return false; } // Compiled! return true; }
static void serialize_function(lua_State *L, luaL_Buffer* b, int pos) { lua_pushvalue(L, pos); luaL_buffinit(L, b); if (lua_dump(L, f_writer, b) != 0) luaL_error(L, "cannot serialize: unable to dump function"); luaL_pushresult(b); lua_remove(L, -2); // consume the function, leave the serialized string on the stack }
int LuaScriptEngine::Compiler::dumper(lua_State* L) { Options* opt = static_cast<Options*>(lua_touserdata(L, 1)); int result = lua_dump(L, Compiler::writer, opt->s, !opt->stripDebug); return 0; }
compiled_chunk* lua_context::compile_chunk(const std::string& name, const std::string& str) { compiled_chunk* chunk = new compiled_chunk(); luaL_loadbuffer(context_ptr(), str.c_str(), str.size(), name.c_str()); // (-0,+1,-) lua_dump(context_ptr(), chunk_writer, reinterpret_cast<void*>(chunk)); // (-0,+0,-) lua_pop(context_ptr(), 1); // (-n(1),+0,-) chunk->add_chunk(0, 0); return chunk; }
static int str_dump (lua_State *L) { luaL_Buffer b; luaL_checktype(L, 1, LUA_TFUNCTION); luaL_buffinit(L,&b); if (!lua_dump(L, writer, &b)) luaL_error(L, "unable to dump given function"); luaL_pushresult(&b); return 1; }
void lpi_broadcast_object(lua_State * L, int index, PI_BUNDLE * bundle) { int n; if (luaL_getmetafield(L, index, "__recv")) { /* transmit __recv */ lpi_broadcast_header(L, bundle, LUA_TUSERDATA, (lua_Number)0); lpi_broadcast_object(L, lua_gettop(L), bundle); lua_pop(L, 1); } if (luaL_getmetafield(L, index, "__send")) { lua_pushvalue(L, index); lua_call(L, 1, 1); lpi_broadcast_object(L, lua_gettop(L), bundle); lua_pop(L, 1); return; } switch(lua_type(L, index)) { case LUA_TNIL: lpi_broadcast_header(L, bundle, LUA_TNIL, (lua_Number)0); break; case LUA_TNUMBER: lpi_broadcast_header(L, bundle, LUA_TNUMBER, lua_tonumber(L, index)); break; case LUA_TBOOLEAN: lpi_broadcast_header(L, bundle, LUA_TBOOLEAN, (lua_Number)lua_toboolean(L, index)); break; case LUA_TSTRING: lpi_broadcast_header(L, bundle, LUA_TSTRING, (lua_Number)lua_objlen(L, index)); lpi_broadcast_data(L, bundle, lua_tostring(L, index), lua_objlen(L, index)); break; case LUA_TFUNCTION: lua_pushvalue(L, index); n = lua_gettop(L); lua_dump(L, lpi_functionWriter, NULL); n = lua_gettop(L) - n; lua_concat(L, n); lpi_broadcast_header(L, bundle, LUA_TFUNCTION, (lua_Number)lua_objlen(L, -1)); lpi_broadcast_data(L, bundle, lua_tostring(L, -1), lua_objlen(L, -1)); lua_pop(L, 2); break; case LUA_TTABLE: lpi_broadcast_table(L, index, bundle); break; default: luaL_typerror(L, index, "nil, number, boolean, or string"); break; } }
// Compile a script by name and dump it back to disk. void LUA_DumpFile(const char *filename) { FILE *handle; char filenamebuf[MAX_WADPATH]; if (!gL) // Lua needs to be initialized LUA_ClearState(false); // find the file the SRB2 way strncpy(filenamebuf, filename, MAX_WADPATH); filenamebuf[MAX_WADPATH - 1] = '\0'; filename = filenamebuf; if ((handle = fopen(filename, "rb")) == NULL) { // If we failed to load the file with the path as specified by // the user, strip the directories and search for the file. nameonly(filenamebuf); // If findfile finds the file, the full path will be returned // in filenamebuf == filename. if (findfile(filenamebuf, NULL, true)) { if ((handle = fopen(filename, "rb")) == NULL) { CONS_Alert(CONS_ERROR, M_GetText("Can't open %s\n"), filename); return; } } else { CONS_Alert(CONS_ERROR, M_GetText("File %s not found.\n"), filename); return; } } fclose(handle); // pass the path we found to Lua // luaL_loadfile will open and read the file in as a Lua function if (luaL_loadfile(gL, filename)) { CONS_Alert(CONS_ERROR,"%s\n",lua_tostring(gL,-1)); lua_pop(gL, 1); return; } // dump it back to disk if ((handle = fopen(filename, "wb")) == NULL) CONS_Alert(CONS_ERROR, M_GetText("Can't write to %s\n"), filename); if (lua_dump(gL, dumpWriter, handle)) CONS_Printf("Failed while writing %s to disk... Sorry!\n", filename); else CONS_Printf("Successfully compiled %s into bytecode.\n", filename); fclose(handle); lua_pop(gL, 1); // function is still on stack after lua_dump lua_gc(gL, LUA_GCCOLLECT, 0); return; }
/** * @brief Copies the function on the top of src to the top of dst. * * It can be a Lua function or a C function. * * @param src source state * @param dst destination state */ static void sglua_copy_function(lua_State* src, lua_State* dst) { if (lua_iscfunction(src, -1)) { /* it's a C function */ XBT_DEBUG("It's a C function"); sglua_stack_dump("src before copying upvalues: ", src); /* get the function pointer */ int function_index = lua_gettop(src); lua_CFunction f = lua_tocfunction(src, function_index); /* copy the upvalues */ int i = 0; const char* upvalue_name = NULL; do { i++; upvalue_name = lua_getupvalue(src, function_index, i); if (upvalue_name != NULL) { XBT_DEBUG("Upvalue %s", upvalue_name); sglua_move_value(src, dst); } } while (upvalue_name != NULL); sglua_stack_dump("src before copying pointer: ", src); /* set the function */ lua_pushcclosure(dst, f, i - 1); XBT_DEBUG("Function pointer copied"); } else { /* it's a Lua function: dump it from src */ s_sglua_buffer_t buffer; buffer.capacity = 128; /* an empty function uses 77 bytes */ buffer.size = 0; buffer.data = xbt_new(char, buffer.capacity); /* copy the binary chunk from src into a buffer */ _XBT_GNUC_UNUSED int error = lua_dump(src, sglua_memory_writer, &buffer); xbt_assert(!error, "Failed to dump the function from the source state: error %d", error); XBT_DEBUG("Fonction dumped: %zu bytes", buffer.size); /* fwrite(buffer.data, buffer.size, buffer.size, stderr); fprintf(stderr, "\n"); */ /* load the chunk into dst */ error = luaL_loadbuffer(dst, buffer.data, buffer.size, "(dumped function)"); xbt_assert(!error, "Failed to load the function into the destination state: %s", lua_tostring(dst, -1)); } }
static int str_dump (lua_State *L) { luaL_Buffer b; int strip = lua_toboolean(L, 2); luaL_checktype(L, 1, LUA_TFUNCTION); lua_settop(L, 1); luaL_buffinit(L,&b); if (lua_dump(L, writer, &b, strip) != 0) return luaL_error(L, "unable to dump given function"); luaL_pushresult(&b); return 1; }
static int set_bytecode(lua_State * L) { int k, ltype; unsigned int i; k = (int) luaL_checkinteger(L, -2); i = (unsigned) k + 1; if ((int) (UINT_MAX32 / sizeof(bytecode) + 1) < i) { luaL_error(L, "value too large"); } if (k < 0) { luaL_error(L, "negative values not allowed"); } ltype = lua_type(L, -1); if (ltype != LUA_TFUNCTION && ltype != LUA_TNIL) { luaL_error(L, "unsupported type"); } if (k > luabytecode_max) { i = (unsigned) (sizeof(bytecode) * ((unsigned) k + 1)); lua_bytecode_registers = xrealloc(lua_bytecode_registers, i); if (luabytecode_max == -1) { luabytecode_bytes += (unsigned) (sizeof(bytecode) * (unsigned) (k + 1)); } else { luabytecode_bytes += (unsigned) (sizeof(bytecode) * (unsigned) (k + 1 - luabytecode_max)); } for (i = (unsigned) (luabytecode_max + 1); i <= (unsigned) k; i++) { lua_bytecode_registers[i].buf = NULL; lua_bytecode_registers[i].size = 0; lua_bytecode_registers[i].done = 0; } luabytecode_max = k; } if (lua_bytecode_registers[k].buf != NULL) { xfree(lua_bytecode_registers[k].buf); luabytecode_bytes -= (unsigned) lua_bytecode_registers[k].size; lua_bytecode_registers[k].size = 0; lua_bytecode_registers[k].done = 0; lua_pushnil(L); bytecode_register_shadow_set(L, k); } if (ltype == LUA_TFUNCTION) { lua_bytecode_registers[k].buf = xmalloc(LOAD_BUF_SIZE); lua_bytecode_registers[k].alloc = LOAD_BUF_SIZE; memset(lua_bytecode_registers[k].buf, 0, LOAD_BUF_SIZE); lua_dump(L, writer, (void *) (lua_bytecode_registers + k)); } lua_pop(L, 1); return 0; }
static int str_dump (lua_State *L) { luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); if(!b) luaL_error(L, "str_dump: cannot allocate memory"); luaL_checktype(L, 1, LUA_TFUNCTION); lua_settop(L, 1); luaL_buffinit(L,b); if (lua_dump(L, writer, b) != 0){ kfree(b); luaL_error(L, "unable to dump given function"); } luaL_pushresult(b); kfree(b); return 1; }
static void write_function( Transport *tpt, lua_State *L, int var_index ) { luaL_Buffer b; // push function onto stack, serialize to string lua_pushvalue( L, var_index ); luaL_buffinit( L, &b ); lua_dump(L, writer, &b); // put string representation on stack and send it luaL_pushresult( &b ); write_variable( tpt, L, lua_gettop( L ) ); // Remove function & dumped string from stack lua_pop( L, 2 ); }
static void pa_setcallback__(lua_State *L, int idx, pa_Stream *stream) { luaL_Buffer b; size_t l; const char *str; lua_State *pa_L = stream->pa_L; if(!lua_isfunction(L, idx)) luaL_error(L, "internal error: provided callback is not a function"); lua_pushvalue(L, idx); luaL_buffinit(L, &b); if(lua_dump(L, pa_writer, &b) != 0) { lua_pop(L, 1); luaL_error(L, "invalid callback function -- cannot be dumped"); } luaL_pushresult(&b); str = luaL_checklstring(L, -1, &l); lua_settop(pa_L, 0); if(luaL_loadbuffer(pa_L, str, l, NULL)) { lua_pop(L, 2); luaL_error(L, "could not load the callback function properly"); } if(lua_pcall(pa_L, 0, LUA_MULTRET, 0)) { lua_pop(L, 2); luaL_error(L, "could not execute the callback function properly: %s", lua_tostring(pa_L, -1)); } if(!((lua_gettop(pa_L) > 0) && lua_isfunction(pa_L, -1))) { lua_pop(L, 2); luaL_error(L, "the callback function did not return a function"); } lua_pop(L, 2); }
bool script::compile() { if (needs_recompilation) { int result = 0; bytecode.clear(); if (is_associated_string_filename) result = luaL_loadstring(lua_state, get_file_contents(associated_string).c_str()); else result = luaL_loadstring(lua_state, associated_string.c_str()); if (result != 0) return false; else { lua_dump(lua_state, lua_writer, &bytecode, 0); lua_pop(lua_state, 1); } } needs_recompilation = false; return true; }
/** * @brief Attempts to compile a Lua script. * * @param filename Filename of the script. * @param buffer The buffer to store the script's compiled bytecode. * * @return true if it succeeds, false if it fails. */ bool CLuaScript::CompileScript(const char * filename, BytecodeBuffer & buffer) { // ensure that we wait until the last user's done executing their script. FastGuard lock(m_lock); /* Attempt to load the file */ int err = luaL_loadfile(m_luaState, filename); // If something bad happened, try to find an error. if (err != LUA_OK) { RetrieveLoadError(err, filename); return false; } // Everything's OK so far, the script has been loaded, now we need to start dumping it to bytecode. err = lua_dump(m_luaState, (lua_Writer)LoadBytecodeChunk, &buffer); if (err || buffer.empty()) { printf("ERROR: Failed to dump the Lua script `%s` to bytecode.\n", filename); return false; } #if !defined(USE_ORIGINAL_QUESTS) // Load up the script & revert the stack. // This step's only here for cleanup purposes. err = lua_pcall(m_luaState, 0, LUA_MULTRET, 0); if (err != LUA_OK) { RetrieveLoadError(err, filename); return false; } #endif // Compiled! return true; }
static int lua_import_stream(stream_t* stream, const uuid_t uuid, luaimport_dump_t* dump) { lua_t* env; lua_State* state; int result = 0; lua_readstream_t read_stream = { .stream = stream, }; env = lua_allocate(); state = lua_state(env); if (lua_load(state, lua_read_stream, &read_stream, "import") != 0) { log_errorf(HASH_LUA, ERROR_INTERNAL_FAILURE, STRING_CONST("Lua load failed: %s"), lua_tostring(state, -1)); lua_pop(state, 1); result = -1; goto exit; } lua_dump(state, lua_import_dump_writer, dump); if (lua_pcall(state, 0, 0, 0) != 0) { log_errorf(HASH_LUA, ERROR_INTERNAL_FAILURE, STRING_CONST("Lua pcall failed: %s"), lua_tostring(state, -1)); lua_pop(state, 1); result = -1; goto exit; } log_debug(HASH_LUA, STRING_CONST("Lua bytecode dump successful")); exit: lua_deallocate(env); return result; }
static int pmain(lua_State* L) { struct Smain* s = (struct Smain*)lua_touserdata(L, 1); int argc=s->argc; char** argv=s->argv; int i; lua_pop(L,1); if (!lua_checkstack(L,argc)) fatal("too many input files"); for (i=0; i<argc; i++) { const char* filename=IS("-") ? NULL : argv[i]; if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1)); if (dumping) { FILE* D= (output==NULL) ? stdout : fopen(output,(i > 0 ? "ab" : "wb")); if (D==NULL) cannot("open"); char* bytecode = 0L; size_t len = 0; wdata wd = {&len, &bytecode}; if(lua_dump(L, write_dump, &wd)) fatal("failed to dump bytecode"); fwrite(bytecode,len,1,D); lua_pop(L,3); if (ferror(D)) cannot("write"); if (fclose(D)) cannot("close"); } } return 0; }
static int headerinfo (lua_State *L) { const char *dump; lua_settop(L, 1); if (lua_isnil(L, 1)) { if (luaL_loadstring(L, "return function () end") != LUA_OK) return Error(L, "unable to load dummy function"); lua_replace(L, 1); } switch (lua_type(L, 1)) { case LUA_TSTRING: { size_t l; dump = lua_tolstring(L, 1, &l); if (l < HEADERSIZE || strncmp(LUA_SIGNATURE, dump, SIGSIZE) != 0) return Error(L, "not a valid Lua function dump"); break; } case LUA_TFUNCTION: { luaL_Buffer b; luaL_buffinit(L, &b); if (lua_dump(L, Writer, &b) != LUA_OK) return Error(L, "unable to dump given function"); luaL_pushresult(&b); lua_replace(L, 1); dump = lua_tostring(L, 1); break; } default: { return Error(L, "not a function or function dump"); } } lua_createtable(L, 0, INFOSIZE); { int major = (GetInfo(dump, 0) >> 4); int minor = (GetInfo(dump, 0) & 0xf); lua_pushfstring(L, "%d.%d", major, minor); lua_setfield(L, 2, "version"); } lua_pushinteger(L, GetInfo(dump, 1)); lua_setfield(L, 2, "format"); lua_pushstring(L, (GetInfo(dump, 2) ? "little-endian" : "big-endian")); lua_setfield(L, 2, "endianness"); lua_pushinteger(L, GetInfo(dump, 3)); lua_setfield(L, 2, "int_size"); lua_pushinteger(L, GetInfo(dump, 4)); lua_setfield(L, 2, "size_size"); lua_pushinteger(L, GetInfo(dump, 5)); lua_setfield(L, 2, "instruction_size"); lua_pushinteger(L, GetInfo(dump, 6)); lua_setfield(L, 2, "number_size"); lua_pushboolean(L, GetInfo(dump, 7)); lua_setfield(L, 2, "number_is_int"); return 1; }
int CompileAspPage(lua_State *L, const char *asp_path, const struct AspEngineConfig *config, char **error_message) { int requires_recompilation = 0; struct _stat asp_file_stat; struct _stat luac_file_stat; char cache_path[MAX_PATH]; char lua_file[MAX_PATH]; char luac_file[MAX_PATH]; struct membuf *lua_content; lua_State *LL; int result; struct ReaderState reader_state; int use_cache; assert(((!config->cache_lua && !config->cache_luac) || ((config->cache_lua || config->cache_luac)) && config->root_path && config->cache_path)); if (error_message != NULL) *error_message = NULL; if (config->cache_path && !RetargetPath(config->root_path, asp_path, config->cache_path, cache_path)) { use_cache = config->cache_lua || config->cache_luac; } else { use_cache = 0; } if (_stat(asp_path, &asp_file_stat) != 0) { if (error_message) *error_message = strdup(strerror(errno)); return errno; } requires_recompilation = 1; if (use_cache) { CreateDirectories(cache_path); strcat(strcpy(lua_file, cache_path), ".lua"); strcat(strcpy(luac_file, cache_path), ".luac"); if (_stat(luac_file, &luac_file_stat) == 0) { if (asp_file_stat.st_mtime < luac_file_stat.st_mtime) requires_recompilation = 0; } } if (requires_recompilation) { lua_content = GenerateLuaFile(asp_path, (use_cache && config->cache_lua) ? lua_file : NULL, error_message); if (lua_content == NULL) return 1; } else { FILE *luac_fp = fopen(luac_file, "rb"); if (luac_fp == NULL) { if (error_message) *error_message = strdup(strerror(errno)); return 1; } lua_content = membuf_create(luac_file_stat.st_size, _dup(_fileno(luac_fp)), 1, 0); fclose(luac_fp); } reader_state.ptr = (char *)membuf_begin(lua_content); reader_state.end = (char *)membuf_end(lua_content); LL = L ? L : luaL_newstate(); result = lua_load(LL, StringStreamReader, &reader_state, asp_path, NULL); if (result != LUA_OK) { membuf_close(lua_content); if (error_message) *error_message = strdup(lua_tostring(LL, -1)); if (L == NULL) lua_close(LL); return 1; } membuf_close(lua_content); if (use_cache && requires_recompilation && config->cache_luac) { struct FileWriterState writer_state; writer_state.fp = fopen(luac_file, "wb"); if (writer_state.fp != NULL) { lua_dump(LL, FileWriter, &writer_state); fclose(writer_state.fp); } } if (L != NULL) { result = lua_pcall(LL, 0, 0, 0); if (result && error_message) *error_message = strdup(lua_tostring(LL, -1)); } else { lua_close(LL); } return result; }
void ·lua_dump(uintptr L, uintptr dumpinfo, uintptr ret) { ret = lua_dump((lua_State*)L, stubwriter, (void*)dumpinfo); FLUSH(&ret); }
static void mar_encode_value(lua_State *L, mar_Buffer *buf, int val, size_t *idx) { size_t l; int val_type = lua_type(L, val); lua_pushvalue(L, val); buf_write(L, (void*)&val_type, MAR_CHR, buf); switch (val_type) { case LUA_TBOOLEAN: { int int_val = lua_toboolean(L, -1); buf_write(L, (void*)&int_val, MAR_CHR, buf); break; } case LUA_TSTRING: { const char *str_val = lua_tolstring(L, -1, &l); buf_write(L, (void*)&l, MAR_I32, buf); buf_write(L, str_val, l, buf); break; } case LUA_TNUMBER: { lua_Number num_val = lua_tonumber(L, -1); buf_write(L, (void*)&num_val, MAR_I64, buf); break; } case LUA_TTABLE: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); /* pop nil */ if (luaL_getmetafield(L, -1, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, -2); /* self */ lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_remove(L, -2); /* __persist */ lua_newtable(L); lua_pushvalue(L, -2); /* callback */ lua_rawseti(L, -2, 1); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } else { tag = MAR_TVAL; lua_pushvalue(L, -1); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -1); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx); lua_pop(L, 1); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data,rec_buf.head, buf); buf_done(L, &rec_buf); } } break; } case LUA_TFUNCTION: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; int i; lua_Debug ar; lua_pop(L, 1); /* pop nil */ 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); } tag = MAR_TVAL; lua_pushvalue(L, -1); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -1); buf_init(L, &rec_buf); lua_dump(L, (lua_Writer)buf_write, &rec_buf); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); lua_newtable(L); for (i=1; i <= ar.nups; i++) { lua_getupvalue(L, -2, i); lua_rawseti(L, -2, i); } buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } break; } case LUA_TUSERDATA: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); /* pop nil */ if (luaL_getmetafield(L, -1, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, -2); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -2); lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_newtable(L); lua_pushvalue(L, -2); lua_rawseti(L, -2, 1); lua_remove(L, -2); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); } else { luaL_error(L, "attempt to encode userdata (no __persist hook)"); } lua_pop(L, 1); } break; } case LUA_TNIL: break; default: luaL_error(L, "invalid value type (%s)", lua_typename(L, val_type)); } lua_pop(L, 1); }
static void dumpit () { lua_dump (lua_vm, writer, NULL); }
static void pack_value(lua_State *L, mar_Buffer *buf, int val, int *idx) { size_t l; int val_type = lua_type(L, val); buf_write(L, (void*)&val_type, MAR_CHR, buf); switch (val_type) { case LUA_TBOOLEAN: { int int_val = lua_toboolean(L, val); buf_write(L, (void*)&int_val, MAR_CHR, buf); break; } case LUA_TSTRING: { const char *str_val = lua_tolstring(L, val, &l); buf_write(L, (void*)&l, MAR_I32, buf); buf_write(L, str_val, l, buf); break; } case LUA_TNUMBER: { lua_Number num_val = lua_tonumber(L, val); buf_write(L, (void*)&num_val, MAR_I64, buf); break; } case LUA_TTABLE: { int tag, ref; lua_pushvalue(L, val); lua_rawget(L, 2); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); if (luaL_getmetafield(L, val, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, val-1); lua_pushinteger(L, (*idx)++); lua_rawset(L, 2); lua_pushvalue(L, val-1); lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_newtable(L); lua_pushvalue(L, -2); lua_rawseti(L, -2, 1); lua_remove(L, -2); buf_init(L, &rec_buf); mar_pack(L, &rec_buf, idx); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } else { tag = MAR_TVAL; lua_pushvalue(L, val); lua_pushinteger(L, (*idx)++); lua_rawset(L, 2); lua_pushvalue(L, val); buf_init(L, &rec_buf); mar_pack(L, &rec_buf, idx); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data,rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } } break; } case LUA_TFUNCTION: { int tag, ref; lua_pushvalue(L, val); lua_rawget(L, 2); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; int i; lua_Debug ar; lua_pop(L, 1); tag = MAR_TVAL; lua_pushvalue(L, val); lua_pushinteger(L, (*idx)++); lua_rawset(L, 2); lua_pushvalue(L, val); buf_init(L, &rec_buf); lua_dump(L, (lua_Writer)buf_write, &rec_buf); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); lua_pushvalue(L, val); lua_getinfo(L, ">uS", &ar); if (ar.what[0] != 'L') { luaL_error(L, "attempt to persist a C function"); } lua_newtable(L); for (i=1; i <= ar.nups; i++) { lua_getupvalue(L, -2, i); lua_rawseti(L, -2, i); } buf_init(L, &rec_buf); mar_pack(L, &rec_buf, idx); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } break; } case LUA_TUSERDATA: { int tag, ref; lua_pushvalue(L, val); lua_rawget(L, 2); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); if (luaL_getmetafield(L, val, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, val-1); lua_pushinteger(L, (*idx)++); lua_rawset(L, 2); lua_pushvalue(L, val-1); lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_newtable(L); lua_pushvalue(L, -2); lua_rawseti(L, -2, 1); lua_remove(L, -2); buf_init(L, &rec_buf); mar_pack(L, &rec_buf, idx); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } else { tag = MAR_TVAL; buf_write(L, (void*)&tag, MAR_CHR, buf); } } break; } case LUA_TTHREAD: break; /* just give them a nil during unpack */ default: luaL_error(L, "invalid value type"); } }
static void mar_encode_value(lua_State *L, mar_Buffer *buf, int val, size_t *idx, int nowrap) { size_t l; int val_type = lua_type(L, val); lua_pushvalue(L, val); buf_write(L, (void*)&val_type, MAR_CHR, buf); switch (val_type) { case LUA_TBOOLEAN: { int int_val = lua_toboolean(L, -1); buf_write(L, (void*)&int_val, MAR_CHR, buf); break; } case LUA_TSTRING: { const char *str_val = lua_tolstring(L, -1, &l); buf_write(L, (void*)&l, MAR_I32, buf); buf_write(L, str_val, l, buf); break; } case LUA_TNUMBER: { lua_Number num_val = lua_tonumber(L, -1); buf_write(L, (void*)&num_val, MAR_I64, buf); break; } case LUA_TLIGHTUSERDATA: { if(nowrap) luaL_error(L, "light userdata not permitted"); void * ptr_val = lua_touserdata(L, -1); long long v = (long long)ptr_val; buf_write(L, (char*)&v, MAR_I64, buf); break; } case LUA_TTABLE: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); /* pop nil */ if (luaL_getmetafield(L, -1, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, -2); /* self */ lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_remove(L, -2); /* __persist */ lua_newtable(L); lua_pushvalue(L, -2); /* callback */ lua_rawseti(L, -2, 1); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx, nowrap); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } else { tag = MAR_TVAL; lua_pushvalue(L, -1); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -1); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx, nowrap); lua_pop(L, 1); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data,rec_buf.head, buf); buf_done(L, &rec_buf); } } break; } case LUA_TFUNCTION: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; int i; lua_Debug ar; lua_pop(L, 1); /* pop nil */ lua_pushvalue(L, -1); lua_getinfo(L, ">nuS", &ar); //printf("Function name='%s' type='%s' nups=%d\n",ar.namewhat,ar.what,ar.nups); if (ar.what[0] != 'L') { luaL_error(L, "attempt to persist a C function '%s'", ar.name); } tag = MAR_TVAL; lua_pushvalue(L, -1); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -1); buf_init(L, &rec_buf); lua_dump(L, (lua_Writer)buf_write, &rec_buf); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); lua_newtable(L); for (i=1; i <= ar.nups; i++) { #if LUA_VERSION_NUM > 501 const char * str=lua_getupvalue(L, -2, i); if(!strncmp(str,"_ENV",4)) { //printf("Stripping _ENV\n"); lua_pop(L,1); lua_pushliteral(L,LEDA_ENV_MARKER); } #else lua_getupvalue(L, -2, i); #endif lua_rawseti(L, -2, i); } buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx, nowrap); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } break; } case LUA_TUSERDATA: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); /* pop nil */ if (!nowrap && luaL_getmetafield(L, -1, "__wrap")) { tag = MAR_TUSR; lua_pushvalue(L, -2); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -2); lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__wrap must return a function"); } lua_newtable(L); lua_pushvalue(L, -2); lua_rawseti(L, -2, 1); lua_remove(L, -2); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx, nowrap); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); } else if (luaL_getmetafield(L, -1, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, -2); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -2); lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_newtable(L); lua_pushvalue(L, -2); lua_rawseti(L, -2, 1); lua_remove(L, -2); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx, nowrap); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); } else { luaL_error(L, "attempt to encode userdata (no __wrap hook - or not permited - and no __persist hook)"); } lua_pop(L, 1); } break; } case LUA_TNIL: break; default: luaL_error(L, "invalid value type (%s)", lua_typename(L, val_type)); } lua_pop(L, 1); }
static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) { lua_CFunction cfunc= lua_tocfunction( L,i ); unsigned n; ASSERT_L( L2_cache_i != 0 ); STACK_GROW(L,2); STACK_CHECK(L) if (!cfunc) { // Lua function luaL_Buffer b; const char *s; size_t sz; int tmp; const char *name= NULL; #if 0 // "To get information about a function you push it onto the // stack and start the what string with the character '>'." // { lua_Debug ar; lua_pushvalue( L, i ); lua_getinfo(L, ">n", &ar); // fills 'name' and 'namewhat', pops function name= ar.namewhat; fprintf( stderr, "NAME: %s\n", name ); // just gives NULL } #endif // 'lua_dump()' needs the function at top of stack // if (i!=-1) lua_pushvalue( L, i ); luaL_buffinit(L,&b); tmp= lua_dump(L, buf_writer, &b); ASSERT_L(tmp==0); // // "value returned is the error code returned by the last call // to the writer" (and we only return 0) luaL_pushresult(&b); // pushes dumped string on 'L' s= lua_tolstring(L,-1,&sz); ASSERT_L( s && sz ); if (i!=-1) lua_remove( L, -2 ); // Note: Line numbers seem to be taken precisely from the // original function. 'name' is not used since the chunk // is precompiled (it seems...). // // TBD: Can we get the function's original name through, as well? // if (luaL_loadbuffer(L2, s, sz, name) != 0) { // chunk is precompiled so only LUA_ERRMEM can happen // "Otherwise, it pushes an error message" // STACK_GROW( L,1 ); luaL_error( L, "%s", lua_tostring(L2,-1) ); } lua_pop(L,1); // remove the dumped string STACK_MID(L,0) }
bool Serializer::writeRoomData() { // Write the enable status for the spots of all nodes of all rooms if (!SDL_WriteBE16(_rw, Control::instance().numRooms())) return false; for (Room *room : Control::instance().rooms()) { if (!SDL_WriteBE16(_rw, room->numNodes())) return false; if (room->hasNodes()) { room->beginIteratingNodes(); do { Node *node = room->iterator(); if (!SDL_WriteBE16(_rw, node->numSpots())) return false; if (node->hasSpots()) { node->beginIteratingSpots(); do { if (!SDL_WriteU8(_rw, node->currentSpot()->isEnabled())) return false; } while (node->iterateSpots()); } } while (room->iterateNodes()); } } Room *room = Control::instance().currentRoom(); // Write node number uint16_t nodeIdx = 0; if (room->hasNodes()) { room->beginIteratingNodes(); do { if (room->iterator() == room->currentNode()) break; nodeIdx++; } while (room->iterateNodes()); } if (!SDL_WriteBE16(_rw, nodeIdx)) return false; // Write camera angles int hAngle = CameraManager::instance().angleHorizontal(); const std::string hAngleStr = std::to_string(hAngle); if (!SDL_WriteU8(_rw, hAngleStr.length())) return false; if (!SDL_RWwrite(_rw, hAngleStr.c_str(), hAngleStr.length(), 1)) return false; int vAngle = CameraManager::instance().angleVertical(); const std::string vAngleStr = std::to_string(vAngle); if (!SDL_WriteU8(_rw, vAngleStr.length())) return false; if (!SDL_RWwrite(_rw, vAngleStr.c_str(), vAngleStr.length(), 1)) return false; float fov = CameraManager::instance().fieldOfView(); const std::string fovStr = std::to_string(fov); if (!SDL_WriteU8(_rw, fovStr.length())) return false; if (!SDL_RWwrite(_rw, fovStr.c_str(), fovStr.length(), 1)) return false; // Write audio states if (!SDL_WriteBE16(_rw, room->arrayOfAudios().size())) return false; for (Audio *audio : room->arrayOfAudios()) { if (!SDL_WriteU8(_rw, audio->state())) return false; } // Write timers int64_t timersPtr = SDL_RWtell(_rw); if (timersPtr < 0) return false; if (!SDL_WriteBE16(_rw, 0)) // 2 placeholder bytes for the actual number of timers return false; uint16_t numTimers = 0; for (const auto &timer : TimerManager::instance().timers()) { if (timer.type != DGTimerNormal || !timer.isEnabled || (!timer.isLoopable && timer.hasTriggered)) continue; double elapsed = TimerManager::instance().timeElapsed(timer); if (timer.trigger - elapsed > 0) { const std::string triggerStr = std::to_string(timer.trigger); if (!SDL_WriteU8(_rw, timer.isLoopable)) return false; if (!SDL_WriteU8(_rw, triggerStr.length())) return false; if (!SDL_RWwrite(_rw, triggerStr.c_str(), triggerStr.length(), 1)) return false; const std::string elapsedStr = std::to_string(elapsed); if (!SDL_WriteU8(_rw, elapsedStr.length())) return false; if (!SDL_RWwrite(_rw, elapsedStr.c_str(), elapsedStr.length(), 1)) return false; lua_rawgeti(_L, LUA_REGISTRYINDEX, timer.luaHandler); // Push timer function to top of stack int64_t funcSizePtr = SDL_RWtell(_rw); if (funcSizePtr < 0) return false; if (!SDL_WriteBE16(_rw, 0)) // 2 placeholder bytes for the actual function size return false; int64_t beforeFuncPtr = SDL_RWtell(_rw); if (beforeFuncPtr < 0) return false; int errCode = lua_dump(_L, writeFunction, _rw); if (errCode != 0) return false; int64_t afterFuncPtr = SDL_RWtell(_rw); if (afterFuncPtr < 0) return false; uint16_t numBytesWritten = afterFuncPtr - beforeFuncPtr; if (SDL_RWseek(_rw, funcSizePtr, RW_SEEK_SET) < 0) return false; if (!SDL_WriteBE16(_rw, numBytesWritten)) return false; if (SDL_RWseek(_rw, 0, RW_SEEK_END) < 0) // Restore file pointer to end return false; numTimers++; } } if (SDL_RWseek(_rw, timersPtr, RW_SEEK_SET) < 0) return false; if (!SDL_WriteBE16(_rw, numTimers)) return false; if (SDL_RWseek(_rw, 0, RW_SEEK_END) < 0) // Restore file pointer to end return false; // Write control mode if (!SDL_WriteU8(_rw, Config::instance().controlMode)) return false; return true; }
static inline int _cloneNoTable(lua_State *L, const int idx, lua_State *L_, const int r_lv ) { int ret_= 1; switch(lua_type(L, idx ) ) { case LUA_TSTRING: { size_t l; const char *s= lua_tolstring(L, idx, &l ); lua_pushlstring(L_, s, l ); } break; case LUA_TNUMBER: lua_pushnumber(L_, lua_tonumber(L, idx ) ); break; case LUA_TLIGHTUSERDATA: lua_pushlightuserdata(L_, lua_touserdata(L, idx ) ); break; case LUA_TBOOLEAN: lua_pushboolean(L_, lua_toboolean(L, idx ) ); break; case LUA_TUSERDATA: { // userdata 的 meta 暂时不能拷贝 const size_t l= lua_objlen(L, idx ); memmove(lua_newuserdata(L_, l ), lua_touserdata(L, idx ), l ); if(0) //屏蔽 meta 处理 if(lua_getmetatable(L, idx ) ) { const int k= _cloneRecursion(L, lua_gettop(L ), L_, ((0<= r_lv )? r_lv: -1 ) ); lua_pop(L, 1 ); if((0<= r_lv )&& lua_istable(L_, -1 )&& (0< k ) ) printf("%*.s__{%3d}\n", (r_lv- 1 )* 2, "", k ); lua_setmetatable(L_, -2 ); } } break; case LUA_TFUNCTION: if(lua_iscfunction(L, idx ) ) { int j= 1; lua_CFunction f= lua_tocfunction(L, idx ); for(j= 1; UPVALUE_MAX>= j; ++j ) { //设置函数的 upvalue if(!lua_getupvalue(L, idx, j ) ) break; _cloneRecursion(L, lua_gettop(L ), L_, ((0<= r_lv )? (r_lv+ 1 ): -1 ) ); lua_pop(L, 1 ); } lua_pushcclosure(L_, f, j- 1 ); } else { int j= 1; DUMP_CB ud; memset(&ud, 0, sizeof(ud ) ); lua_pushvalue(L, idx ); lua_dump(L, writer_CB, &ud ); if(ud.p ) { //载入函数到新的栈 lua_load(L_, reader_CB, &ud, (char * )0 ); free(ud.p ); } lua_pop(L, 1 ); for(j= 1; UPVALUE_MAX>= j; ++j ) { //设置函数的 upvalue if(!lua_getupvalue(L, idx, j ) ) break; printf("upvalue %d\n", j ); _cloneRecursion(L, lua_gettop(L ), L_, ((0<= r_lv )? (r_lv+ 1 ): -1 ) ); lua_pop(L, 1 ); lua_setupvalue(L_, -2, j ); } } break; case LUA_TNIL: lua_pushnil(L_ ); break; case LUA_TNONE: case LUA_TTHREAD: //? default: ret_= 0; break; } return ret_; }