Convert sourcedb to new LuaStack stuff
This commit is contained in:
@@ -93,8 +93,8 @@ static void calculate_loadresult(LuaCoreStack &LS0, LuaSlot info, const eng::str
|
|||||||
void SourceDB::diff(const SourceDB &auth, StreamBuffer *sb) {
|
void SourceDB::diff(const SourceDB &auth, StreamBuffer *sb) {
|
||||||
LuaVar sdb, sfn, sinfo, shash, sseq;
|
LuaVar sdb, sfn, sinfo, shash, sseq;
|
||||||
LuaVar mdb, mfn, minfo, mhash, mseq, mcode;
|
LuaVar mdb, mfn, minfo, mhash, mseq, mcode;
|
||||||
LuaOldStack SLS(lua_state_, sdb, sfn, sinfo, shash, sseq);
|
LuaExtStack SLS(lua_state_, sdb, sfn, sinfo, shash, sseq);
|
||||||
LuaOldStack MLS(auth.lua_state_, mdb, mfn, minfo, mhash, mseq, mcode);
|
LuaExtStack MLS(auth.lua_state_, mdb, mfn, minfo, mhash, mseq, mcode);
|
||||||
sb->write_int32(0);
|
sb->write_int32(0);
|
||||||
int wc_after = sb->total_writes();
|
int wc_after = sb->total_writes();
|
||||||
int nupdates = 0;
|
int nupdates = 0;
|
||||||
@@ -145,14 +145,12 @@ void SourceDB::diff(const SourceDB &auth, StreamBuffer *sb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb->overwrite_int32(wc_after, nupdates);
|
sb->overwrite_int32(wc_after, nupdates);
|
||||||
MLS.result();
|
|
||||||
SLS.result();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SourceDB::patch(StreamBuffer *sb, DebugCollector *dbc) {
|
bool SourceDB::patch(StreamBuffer *sb, DebugCollector *dbc) {
|
||||||
lua_State *L = lua_state_;
|
lua_State *L = lua_state_;
|
||||||
LuaVar db, info;
|
LuaVar db, info;
|
||||||
LuaOldStack LS(L, db, info);
|
LuaExtStack LS(L, db, info);
|
||||||
LS.rawget(db, LuaRegistry, "sourcedb");
|
LS.rawget(db, LuaRegistry, "sourcedb");
|
||||||
int nupdates = sb->read_int32();
|
int nupdates = sb->read_int32();
|
||||||
for (int i = 0; i < nupdates; i++) {
|
for (int i = 0; i < nupdates; i++) {
|
||||||
@@ -172,14 +170,13 @@ bool SourceDB::patch(StreamBuffer *sb, DebugCollector *dbc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LS.result();
|
|
||||||
return (nupdates > 0);
|
return (nupdates > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceDB::set(const eng::string &fn, const eng::string &code, int sequence) {
|
void SourceDB::set(const eng::string &fn, const eng::string &code, int sequence) {
|
||||||
lua_State *L = lua_state_;
|
lua_State *L = lua_state_;
|
||||||
LuaVar db, info;
|
LuaVar db, info;
|
||||||
LuaOldStack LS(L, db, info);
|
LuaExtStack LS(L, db, info);
|
||||||
LS.rawget(db, LuaRegistry, "sourcedb");
|
LS.rawget(db, LuaRegistry, "sourcedb");
|
||||||
get_info_table(LS, db, info, fn);
|
get_info_table(LS, db, info, fn);
|
||||||
LS.rawset(info, "sequence", sequence);
|
LS.rawset(info, "sequence", sequence);
|
||||||
@@ -187,17 +184,15 @@ void SourceDB::set(const eng::string &fn, const eng::string &code, int sequence)
|
|||||||
LS.rawset(info, "fingerprint", "");
|
LS.rawset(info, "fingerprint", "");
|
||||||
LS.rawset(info, "hash", util::hash_to_hex(util::hash_string(code)));
|
LS.rawset(info, "hash", util::hash_to_hex(util::hash_string(code)));
|
||||||
calculate_loadresult(LS, info, fn, code);
|
calculate_loadresult(LS, info, fn, code);
|
||||||
LS.result();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eng::string SourceDB::get(const eng::string &fn) {
|
eng::string SourceDB::get(const eng::string &fn) {
|
||||||
lua_State *L = lua_state_;
|
lua_State *L = lua_state_;
|
||||||
LuaVar db, info, code, sequence, loadresult;
|
LuaVar db, info, code, sequence, loadresult;
|
||||||
LuaOldStack LS(L, db, info, code, sequence, loadresult);
|
LuaExtStack LS(L, db, info, code, sequence, loadresult);
|
||||||
LS.rawget(db, LuaRegistry, "sourcedb");
|
LS.rawget(db, LuaRegistry, "sourcedb");
|
||||||
LS.rawget(info, db, fn);
|
LS.rawget(info, db, fn);
|
||||||
if (!LS.istable(info)) {
|
if (!LS.istable(info)) {
|
||||||
LS.result();
|
|
||||||
return "<nonexistent>";
|
return "<nonexistent>";
|
||||||
}
|
}
|
||||||
LS.rawget(code, info, "code");
|
LS.rawget(code, info, "code");
|
||||||
@@ -211,16 +206,13 @@ eng::string SourceDB::get(const eng::string &fn) {
|
|||||||
} else {
|
} else {
|
||||||
cloadresult = LS.ckstring(loadresult);
|
cloadresult = LS.ckstring(loadresult);
|
||||||
}
|
}
|
||||||
eng::ostringstream oss;
|
return util::ss(seqno, ":", ccode, ":", cloadresult);
|
||||||
oss << seqno << ":" << ccode << ":" << cloadresult;
|
|
||||||
LS.result();
|
|
||||||
return oss.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceDB::update(const util::LuaSourceVec &source) {
|
void SourceDB::update(const util::LuaSourceVec &source) {
|
||||||
lua_State *L = lua_state_;
|
lua_State *L = lua_state_;
|
||||||
LuaVar sourcedb, info;
|
LuaVar sourcedb, info;
|
||||||
LuaOldStack LS(L, sourcedb, info);
|
LuaExtStack LS(L, sourcedb, info);
|
||||||
|
|
||||||
// Get and clear the source database.
|
// Get and clear the source database.
|
||||||
LS.rawget(sourcedb, LuaRegistry, "sourcedb");
|
LS.rawget(sourcedb, LuaRegistry, "sourcedb");
|
||||||
@@ -233,7 +225,7 @@ void SourceDB::update(const util::LuaSourceVec &source) {
|
|||||||
for (int i = 0; i < int(source.size()); i++) {
|
for (int i = 0; i < int(source.size()); i++) {
|
||||||
const eng::string &file = source[i].first;
|
const eng::string &file = source[i].first;
|
||||||
const eng::string &code = source[i].second;
|
const eng::string &code = source[i].second;
|
||||||
std::cerr << "Compiling " << file << std::endl;
|
util::dprint("Compiling ", file);
|
||||||
LS.newtable(info);
|
LS.newtable(info);
|
||||||
LS.rawset(info, "name", file);
|
LS.rawset(info, "name", file);
|
||||||
LS.rawset(info, "code", code);
|
LS.rawset(info, "code", code);
|
||||||
@@ -242,7 +234,6 @@ void SourceDB::update(const util::LuaSourceVec &source) {
|
|||||||
calculate_loadresult(LS, info, file, code);
|
calculate_loadresult(LS, info, file, code);
|
||||||
LS.rawset(sourcedb, file, info);
|
LS.rawset(sourcedb, file, info);
|
||||||
}
|
}
|
||||||
LS.result();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete everything from the global environment.
|
// Delete everything from the global environment.
|
||||||
@@ -270,7 +261,7 @@ static void source_clear_globals(lua_State *L) {
|
|||||||
//
|
//
|
||||||
static void source_load_cfunctions(lua_State *L) {
|
static void source_load_cfunctions(lua_State *L) {
|
||||||
LuaVar classobj;
|
LuaVar classobj;
|
||||||
LuaOldStack LS(L, classobj);
|
LuaExtStack LS(L, classobj);
|
||||||
for (auto r = LuaFunctionReg::All; r != nullptr; r=r->next()) {
|
for (auto r = LuaFunctionReg::All; r != nullptr; r=r->next()) {
|
||||||
lua_CFunction func = r->get_func();
|
lua_CFunction func = r->get_func();
|
||||||
if ((func != nullptr) && (!r->get_sandbox())) {
|
if ((func != nullptr) && (!r->get_sandbox())) {
|
||||||
@@ -286,14 +277,13 @@ static void source_load_cfunctions(lua_State *L) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LS.result();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load all the 'LuaConstant' constants into the lua state.
|
// Load all the 'LuaConstant' constants into the lua state.
|
||||||
//
|
//
|
||||||
static void source_load_cconstants(lua_State *L) {
|
static void source_load_cconstants(lua_State *L) {
|
||||||
LuaVar classobj, value;
|
LuaVar classobj, value;
|
||||||
LuaOldStack LS(L, classobj, value);
|
LuaExtStack LS(L, classobj, value);
|
||||||
for (auto r = LuaConstantReg::All; r != nullptr; r=r->next()) {
|
for (auto r = LuaConstantReg::All; r != nullptr; r=r->next()) {
|
||||||
if (r->get_tokenvalue().empty()) {
|
if (r->get_tokenvalue().empty()) {
|
||||||
LS.set(value, r->get_numbervalue());
|
LS.set(value, r->get_numbervalue());
|
||||||
@@ -311,14 +301,13 @@ static void source_load_cconstants(lua_State *L) {
|
|||||||
LS.rawset(classobj, funcname, value);
|
LS.rawset(classobj, funcname, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LS.result();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run all the closures from the source database.
|
// Run all the closures from the source database.
|
||||||
//
|
//
|
||||||
static eng::string source_load_lfunctions(lua_State *L) {
|
static eng::string source_load_lfunctions(lua_State *L) {
|
||||||
LuaVar sourcedb, key, info, seq, closure, err;
|
LuaVar sourcedb, key, info, seq, closure, err;
|
||||||
LuaOldStack LS(L, sourcedb, key, info, seq, closure, err);
|
LuaExtStack LS(L, sourcedb, key, info, seq, closure, err);
|
||||||
|
|
||||||
// Get the source database.
|
// Get the source database.
|
||||||
LS.rawget(sourcedb, LuaRegistry, "sourcedb");
|
LS.rawget(sourcedb, LuaRegistry, "sourcedb");
|
||||||
@@ -355,27 +344,24 @@ static eng::string source_load_lfunctions(lua_State *L) {
|
|||||||
errss << msg << std::endl;
|
errss << msg << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LS.result();
|
|
||||||
return errss.str();
|
return errss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
eng::string SourceDB::rebuild() {
|
eng::string SourceDB::rebuild() {
|
||||||
lua_State *L = lua_state_;
|
lua_State *L = lua_state_;
|
||||||
LuaVar mathclass, httpclass, jsonnull;
|
LuaExtStack LS(L);
|
||||||
LuaOldStack LS(L, mathclass, httpclass, jsonnull);
|
|
||||||
source_clear_globals(L);
|
source_clear_globals(L);
|
||||||
source_load_cfunctions(L);
|
source_load_cfunctions(L);
|
||||||
source_load_cconstants(L);
|
source_load_cconstants(L);
|
||||||
eng::string errs = source_load_lfunctions(L);
|
eng::string errs = source_load_lfunctions(L);
|
||||||
LS.result();
|
|
||||||
return errs;
|
return errs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceDB::run_unittests() {
|
void SourceDB::run_unittests() {
|
||||||
lua_State *L = lua_state_;
|
lua_State *L = lua_state_;
|
||||||
LuaVar unittests, name, func, err, globtab;
|
LuaVar unittests, name, func, err, globtab;
|
||||||
LuaOldStack LS(L, unittests, name, func, err, globtab);
|
LuaExtStack LS(L, unittests, name, func, err, globtab);
|
||||||
|
|
||||||
LS.getglobaltable(globtab);
|
LS.getglobaltable(globtab);
|
||||||
LS.rawget(unittests, globtab, "unittests");
|
LS.rawget(unittests, globtab, "unittests");
|
||||||
@@ -407,13 +393,12 @@ void SourceDB::run_unittests() {
|
|||||||
if (any) {
|
if (any) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
LS.result();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceDB::init(lua_State *L) {
|
void SourceDB::init(lua_State *L) {
|
||||||
lua_state_ = L;
|
lua_state_ = L;
|
||||||
LuaVar globtab, persist, unpersist, classname, classtab, funcname, funcp, rawfunc, nullstring;
|
LuaVar globtab, persist, unpersist, classname, classtab, funcname, funcp, rawfunc, nullstring;
|
||||||
LuaOldStack LS(L, globtab, persist, unpersist, classname, classtab, funcname, funcp, rawfunc, nullstring);
|
LuaExtStack LS(L, globtab, persist, unpersist, classname, classtab, funcname, funcp, rawfunc, nullstring);
|
||||||
LS.getglobaltable(globtab);
|
LS.getglobaltable(globtab);
|
||||||
LS.rawset(LuaRegistry, "sourcedb", LuaNewTable);
|
LS.rawset(LuaRegistry, "sourcedb", LuaNewTable);
|
||||||
|
|
||||||
@@ -467,61 +452,78 @@ void SourceDB::deserialize_source(util::LuaSourceVec *sv, StreamBuffer *sb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function should not touch the dlmalloc heap.
|
// Register lua builtins.
|
||||||
|
//
|
||||||
|
// To find the lua builtins, we use this approach: we create a new lua state
|
||||||
|
// (the 'prototype', we call it), and we call luaL_openlibs on it. The
|
||||||
|
// prototype should now contain all the builtins.
|
||||||
|
//
|
||||||
|
// Then, we iterate over our function registry, looking for LuaDefineBuiltin
|
||||||
|
// records. These records don't have a function pointer yet. For each such
|
||||||
|
// record, we look into the prototype, and look up the function in the global
|
||||||
|
// environment. If it's not found, we print an error. If we find it, we extract
|
||||||
|
// the C function pointer from it. Then, we remove the function from the
|
||||||
|
// prototype, to indicate that we already processed that function.
|
||||||
|
//
|
||||||
|
// At the end, we scan the prototype to make sure all functions have been
|
||||||
|
// removed. If not, we know our function registry is missing something and we
|
||||||
|
// print out an error.
|
||||||
|
//
|
||||||
void SourceDB::register_lua_builtins() {
|
void SourceDB::register_lua_builtins() {
|
||||||
lua_State *L = LuaCoreStack::newstate(nullptr);
|
lua_State *L = LuaCoreStack::newstate(nullptr);
|
||||||
luaL_openlibs(L);
|
luaL_openlibs(L);
|
||||||
LuaVar globals, lclassname, lfuncname, classtab, func;
|
{
|
||||||
LuaOldStack LS(L, globals, lclassname, lfuncname, classtab, func);
|
LuaVar globals, lclassname, lfuncname, classtab, func;
|
||||||
LS.getglobaltable(globals);
|
LuaExtStack LS(L, globals, lclassname, lfuncname, classtab, func);
|
||||||
|
LS.getglobaltable(globals);
|
||||||
|
|
||||||
// Iterate over the function registry, copying function pointers from
|
// Iterate over the function registry, copying function pointers from
|
||||||
// the prototype lua state into the registry, then remove the closure
|
// the prototype lua state into the registry, then remove the closure
|
||||||
// from the prototype.
|
// from the prototype.
|
||||||
for (auto reg = LuaFunctionReg::All; reg != nullptr; reg=reg->next()) {
|
for (auto reg = LuaFunctionReg::All; reg != nullptr; reg=reg->next()) {
|
||||||
std::string_view funcname;
|
std::string_view funcname;
|
||||||
std::string_view classname;
|
std::string_view classname;
|
||||||
get_reg_name(reg->get_name(), classname, funcname);
|
get_reg_name(reg->get_name(), classname, funcname);
|
||||||
if (classname.empty()) {
|
if (classname.empty()) {
|
||||||
LS.getglobaltable(classtab);
|
LS.getglobaltable(classtab);
|
||||||
} else {
|
|
||||||
LS.rawget(classtab, globals, classname);
|
|
||||||
}
|
|
||||||
lua_CFunction builtin = nullptr;
|
|
||||||
if (LS.istable(classtab)) {
|
|
||||||
LS.rawget(func, classtab, funcname);
|
|
||||||
if (LS.iscfunction(func)) {
|
|
||||||
builtin = lua_tocfunction(L, func.index());
|
|
||||||
LS.rawset(classtab, funcname, LuaNil);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reg->get_func() == nullptr) {
|
|
||||||
if (builtin == nullptr) {
|
|
||||||
if (!reg->get_sandbox()) {
|
|
||||||
std::cerr << "No such builtin function: " << classname << " " << funcname << std::endl;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
reg->set_func(builtin);
|
LS.rawget(classtab, globals, classname);
|
||||||
|
}
|
||||||
|
lua_CFunction builtin = nullptr;
|
||||||
|
if (LS.istable(classtab)) {
|
||||||
|
LS.rawget(func, classtab, funcname);
|
||||||
|
if (LS.iscfunction(func)) {
|
||||||
|
builtin = lua_tocfunction(L, func.index());
|
||||||
|
LS.rawset(classtab, funcname, LuaNil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reg->get_func() == nullptr) {
|
||||||
|
if (builtin == nullptr) {
|
||||||
|
if (!reg->get_sandbox()) {
|
||||||
|
std::cerr << "No such builtin function: " << classname << " " << funcname << std::endl;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reg->set_func(builtin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over the prototype. All cfunctions should have been removed.
|
// Iterate over the prototype. All cfunctions should have been removed.
|
||||||
LS.set(lclassname, LuaNil);
|
LS.set(lclassname, LuaNil);
|
||||||
while (LS.next(globals, lclassname, classtab)) {
|
while (LS.next(globals, lclassname, classtab)) {
|
||||||
if (LS.isstring(lclassname)) {
|
if (LS.isstring(lclassname)) {
|
||||||
if (LS.istable(classtab)) {
|
if (LS.istable(classtab)) {
|
||||||
LS.set(lfuncname, LuaNil);
|
LS.set(lfuncname, LuaNil);
|
||||||
while (LS.next(classtab, lfuncname, func)) {
|
while (LS.next(classtab, lfuncname, func)) {
|
||||||
if (LS.iscfunction(func)) {
|
if (LS.iscfunction(func)) {
|
||||||
std::cerr << "Failed to declare builtin: " << LS.ckstring(lclassname) << "."
|
std::cerr << "Failed to declare builtin: " << LS.ckstring(lclassname) << "."
|
||||||
<< LS.ckstring(lfuncname) << std::endl;
|
<< LS.ckstring(lfuncname) << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +531,7 @@ void SourceDB::register_lua_builtins() {
|
|||||||
eng::string SourceDB::function_docs(const LuaCoreStack &LS0, LuaSlot fn) {
|
eng::string SourceDB::function_docs(const LuaCoreStack &LS0, LuaSlot fn) {
|
||||||
lua_State *L = LS0.state();
|
lua_State *L = LS0.state();
|
||||||
LuaVar sourcedb, fname, finfo, code;
|
LuaVar sourcedb, fname, finfo, code;
|
||||||
LuaOldStack LS(L, sourcedb, fname, finfo, code);
|
LuaExtStack LS(L, sourcedb, fname, finfo, code);
|
||||||
|
|
||||||
if (LS.iscfunction(fn)) {
|
if (LS.iscfunction(fn)) {
|
||||||
lua_CFunction cfn = lua_tocfunction(L, fn.index());
|
lua_CFunction cfn = lua_tocfunction(L, fn.index());
|
||||||
@@ -606,7 +608,7 @@ eng::string SourceDB::function_docs(const LuaCoreStack &LS0, LuaSlot fn) {
|
|||||||
// These should go away eventually. They're for debugging.
|
// These should go away eventually. They're for debugging.
|
||||||
LuaDefine(coroutine_setnextid, "thread,id", "set the next id of a thread (debugging only)") {
|
LuaDefine(coroutine_setnextid, "thread,id", "set the next id of a thread (debugging only)") {
|
||||||
LuaArg co, lid;
|
LuaArg co, lid;
|
||||||
LuaOldStack LS(L, co, lid);
|
LuaDefStack LS(L, co, lid);
|
||||||
lua_State *CO = LS.ckthread(co);
|
lua_State *CO = LS.ckthread(co);
|
||||||
lua_Number id = LS.ckinteger(lid);
|
lua_Number id = LS.ckinteger(lid);
|
||||||
lua_setnextid(CO, id);
|
lua_setnextid(CO, id);
|
||||||
@@ -616,7 +618,7 @@ LuaDefine(coroutine_setnextid, "thread,id", "set the next id of a thread (debugg
|
|||||||
LuaDefine(coroutine_getnextid, "thread", "get the next id of a thread (debugging only)") {
|
LuaDefine(coroutine_getnextid, "thread", "get the next id of a thread (debugging only)") {
|
||||||
LuaArg co;
|
LuaArg co;
|
||||||
LuaRet lid;
|
LuaRet lid;
|
||||||
LuaOldStack LS(L, co, lid);
|
LuaDefStack LS(L, co, lid);
|
||||||
lua_State *CO = LS.ckthread(co);
|
lua_State *CO = LS.ckthread(co);
|
||||||
LS.set(lid, lua_getnextid(CO));
|
LS.set(lid, lua_getnextid(CO));
|
||||||
return LS.result();
|
return LS.result();
|
||||||
|
|||||||
@@ -177,9 +177,11 @@ public:
|
|||||||
eng::string get(const eng::string &fn);
|
eng::string get(const eng::string &fn);
|
||||||
|
|
||||||
// Add builtins to the global function registry.
|
// Add builtins to the global function registry.
|
||||||
|
//
|
||||||
static void register_lua_builtins();
|
static void register_lua_builtins();
|
||||||
|
|
||||||
// Get function documentation.
|
// Get function documentation.
|
||||||
|
//
|
||||||
static eng::string function_docs(const LuaCoreStack &LS, LuaSlot slot);
|
static eng::string function_docs(const LuaCoreStack &LS, LuaSlot slot);
|
||||||
|
|
||||||
// Serialize and unserialize a source vector.
|
// Serialize and unserialize a source vector.
|
||||||
|
|||||||
@@ -361,14 +361,14 @@ public:
|
|||||||
|
|
||||||
// send_to_stream: send all arguments to the specified stream.
|
// send_to_stream: send all arguments to the specified stream.
|
||||||
inline void send_to_stream(std::ostream &os) {}
|
inline void send_to_stream(std::ostream &os) {}
|
||||||
template <class ARG, class... REST>
|
template <typename ARG, typename... REST>
|
||||||
inline void send_to_stream(std::ostream &os, const ARG &arg, const REST & ... rest) {
|
inline void send_to_stream(std::ostream &os, const ARG &arg, const REST & ... rest) {
|
||||||
os << arg;
|
os << arg;
|
||||||
send_to_stream(os, rest...);
|
send_to_stream(os, rest...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ss: convert all arguments to a string by sending them to a stringstream.
|
// ss: convert all arguments to a string by sending them to a stringstream.
|
||||||
template <class... ARGS>
|
template <typename... ARGS>
|
||||||
inline eng::string ss(const ARGS & ... args) {
|
inline eng::string ss(const ARGS & ... args) {
|
||||||
eng::ostringstream oss;
|
eng::ostringstream oss;
|
||||||
send_to_stream(oss, args...);
|
send_to_stream(oss, args...);
|
||||||
@@ -390,7 +390,7 @@ void dprintview(std::string_view view);
|
|||||||
void dprintf(const char *format, ...);
|
void dprintf(const char *format, ...);
|
||||||
void hook_dprint(void (*func)(const char *oneline, size_t size));
|
void hook_dprint(void (*func)(const char *oneline, size_t size));
|
||||||
|
|
||||||
template <class... ARGS>
|
template <typename... ARGS>
|
||||||
inline void dprint(const ARGS & ... args) {
|
inline void dprint(const ARGS & ... args) {
|
||||||
util::ostringstream oss;
|
util::ostringstream oss;
|
||||||
send_to_stream(oss, args...);
|
send_to_stream(oss, args...);
|
||||||
|
|||||||
Reference in New Issue
Block a user