diff_tables and patch_table are working and tested
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "luastack.hpp"
|
||||
#include "streambuffer.hpp"
|
||||
#include "table.hpp"
|
||||
#include "world.hpp"
|
||||
|
||||
// Given a table and an tnmap, return the table number of the table.
|
||||
@@ -52,11 +53,11 @@ static bool equivalent_values(LuaStack &MLS, LuaSlot mval, LuaSlot mtnmap,
|
||||
return SLS.type(sval) == MLS.type(mval);
|
||||
}
|
||||
case LUA_TT_GENERAL: {
|
||||
if (SLS.xtype(sval) != LUA_TT_GENERAL) return false;
|
||||
int midx = get_table_number(MLS, mval, mtnmap);
|
||||
if (midx == 0) return false;
|
||||
if (midx == 0) {
|
||||
return SLS.isnil(sval);
|
||||
}
|
||||
int sidx = get_table_number(SLS, sval, stnmap);
|
||||
if (sidx == 0) return false;
|
||||
return midx == sidx;
|
||||
}
|
||||
case LUA_TT_CLASS: {
|
||||
@@ -95,8 +96,13 @@ static void transmit_value(LuaStack &MLS, LuaSlot mval, LuaSlot mtnmap, StreamBu
|
||||
return;
|
||||
}
|
||||
case LUA_TT_GENERAL: {
|
||||
sb->write_uint8(LUA_TT_GENERAL);
|
||||
sb->write_uint32(get_table_number(MLS, mval, mtnmap));
|
||||
int midx = get_table_number(MLS, mval, mtnmap);
|
||||
if (midx == 0) {
|
||||
sb->write_uint8(LUA_TNIL);
|
||||
} else {
|
||||
sb->write_uint8(LUA_TT_GENERAL);
|
||||
sb->write_uint32(midx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case LUA_TT_CLASS: {
|
||||
@@ -160,7 +166,7 @@ static void transmit_value_debug_string(StreamBuffer *sb, std::ostringstream &os
|
||||
}
|
||||
}
|
||||
|
||||
static bool compare_tables(lua_State *synch, lua_State *master, bool cmeta, StreamBuffer *sb) {
|
||||
static bool diff_tables(lua_State *synch, lua_State *master, bool cmeta, StreamBuffer *sb) {
|
||||
LuaArg mtnmap, mtab, stnmap, stab;
|
||||
LuaVar skey, mkey, sval, mval, mnil;
|
||||
LuaStack SLS(synch, stnmap, stab, skey, sval);
|
||||
@@ -212,7 +218,7 @@ static bool compare_tables(lua_State *synch, lua_State *master, bool cmeta, Stre
|
||||
return (nupdates > 0);
|
||||
}
|
||||
|
||||
static std::string compare_tables_debug_string(StreamBuffer *sb) {
|
||||
static std::string diff_tables_debug_string(StreamBuffer *sb) {
|
||||
std::vector<std::string> sorted;
|
||||
std::ostringstream oss;
|
||||
int ndiffs = sb->read_int32();
|
||||
@@ -230,7 +236,65 @@ static std::string compare_tables_debug_string(StreamBuffer *sb) {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void World::diff_lua_tables(lua_State *master, StreamBuffer *sb) {
|
||||
static void set_transmitted_value(LuaStack &LS, LuaSlot tangibles, LuaSlot ntmap, LuaSlot target, StreamBuffer *sb) {
|
||||
int kind = sb->read_uint8();
|
||||
switch (kind) {
|
||||
case LUA_TBOOLEAN: {
|
||||
LS.set(target, sb->read_bool());
|
||||
return;
|
||||
}
|
||||
case LUA_TNUMBER: {
|
||||
LS.set(target, sb->read_double());
|
||||
return;
|
||||
}
|
||||
case LUA_TSTRING: {
|
||||
LS.set(target, sb->read_string());
|
||||
return;
|
||||
}
|
||||
case LUA_TT_GENERAL: {
|
||||
LS.rawgeti(target, ntmap, sb->read_int32());
|
||||
return;
|
||||
}
|
||||
case LUA_TT_CLASS: {
|
||||
LS.makeclass(target, sb->read_string());
|
||||
return;
|
||||
}
|
||||
case LUA_TT_TANGIBLE: {
|
||||
int64_t id = sb->read_int64();
|
||||
LS.rawgeti(target, tangibles, id);
|
||||
if (LS.isnil(target)) {
|
||||
World *w = World::fetch_global_pointer(LS.state());
|
||||
w->tangible_make(LS.state(), id, true);
|
||||
lua_replace(LS.state(), target.index());
|
||||
}
|
||||
return;
|
||||
}
|
||||
case LUA_TT_GLOBALENV: {
|
||||
LS.getglobaltable(target);
|
||||
return;
|
||||
}
|
||||
case LUA_TNIL: {
|
||||
LS.set(target, LuaNil);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
assert(false); // Should not get here.
|
||||
}
|
||||
}
|
||||
|
||||
static void patch_table(LuaStack &LS0, LuaSlot tangibles, LuaSlot ntmap, LuaSlot tab, StreamBuffer *sb) {
|
||||
LuaVar key, val;
|
||||
LuaStack LS(LS0.state(), key, val);
|
||||
int ndiffs = sb->read_int32();
|
||||
for (int i = 0; i < ndiffs; i++) {
|
||||
set_transmitted_value(LS, tangibles, ntmap, key, sb);
|
||||
set_transmitted_value(LS, tangibles, ntmap, val, sb);
|
||||
LS.rawset(tab, key, val);
|
||||
}
|
||||
LS.result();
|
||||
}
|
||||
|
||||
void World::diff_numbered_tables(lua_State *master, StreamBuffer *sb) {
|
||||
lua_State *synch = state();
|
||||
LuaVar sntmap, mntmap, stnmap, mtnmap;
|
||||
LuaStack SLS(synch, sntmap, stnmap);
|
||||
@@ -257,7 +321,7 @@ void World::diff_lua_tables(lua_State *master, StreamBuffer *sb) {
|
||||
int tw = sb->total_writes();
|
||||
sb->write_int32(id);
|
||||
nmodified += 1;
|
||||
if (!compare_tables(synch, master, true, sb)) {
|
||||
if (!diff_tables(synch, master, true, sb)) {
|
||||
sb->unwrite_to(tw);
|
||||
nmodified -= 1;
|
||||
}
|
||||
@@ -294,7 +358,7 @@ void World::diff_tangible_databases(const IdVector &basis, lua_State *master, St
|
||||
int tw = sb->total_writes();
|
||||
sb->write_int64(id);
|
||||
nmodified += 1;
|
||||
if (!compare_tables(synch, master, false, sb)) {
|
||||
if (!diff_tables(synch, master, false, sb)) {
|
||||
sb->unwrite_to(tw);
|
||||
nmodified -= 1;
|
||||
}
|
||||
@@ -309,6 +373,11 @@ LuaDefine(table_diffcompare, "c") {
|
||||
LuaRet dbgstring;
|
||||
LuaVar tthread;
|
||||
LuaStack LS(L, mtnmap, mtab, stnmap, stab, dbgstring, tthread);
|
||||
// Check the arguments.
|
||||
LS.checktable(mtnmap);
|
||||
LS.checktable(stnmap);
|
||||
LS.checktable(mtab);
|
||||
LS.checktable(stab);
|
||||
// Create a temporary thread to be the 'synch model'. We'll use the
|
||||
// existing thread as the 'master model'.
|
||||
lua_State *synch = lua_newthread(L);
|
||||
@@ -320,9 +389,56 @@ LuaDefine(table_diffcompare, "c") {
|
||||
lua_xmove(L, synch, 2);
|
||||
lua_pushvalue(L, mtnmap.index());
|
||||
lua_pushvalue(L, mtab.index());
|
||||
compare_tables(synch, L, true, &sb);
|
||||
diff_tables(synch, L, true, &sb);
|
||||
// Convert the output to a debug string.
|
||||
LS.set(dbgstring, compare_tables_debug_string(&sb));
|
||||
LS.set(dbgstring, diff_tables_debug_string(&sb));
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
LuaDefine(table_diffapply, "c") {
|
||||
LuaArg tnmap, mtab, stab;
|
||||
LuaRet eql, eqlstr, rtab;
|
||||
LuaVar tthread, tangibles, ntmap, key, val;
|
||||
LuaStack LS(L, tnmap, mtab, stab, eql, eqlstr, rtab, tthread, tangibles, ntmap, key, val);
|
||||
// Check the arguments.
|
||||
LS.checktable(tnmap);
|
||||
LS.checktable(mtab);
|
||||
LS.checktable(stab);
|
||||
|
||||
// Get the tangibles map.
|
||||
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
||||
|
||||
// Invert the tnmap to make the ntmap.
|
||||
LS.set(ntmap, LuaNewTable);
|
||||
LS.set(key, LuaNil);
|
||||
while (LS.next(tnmap, key, val)) {
|
||||
LS.rawset(ntmap, val, key);
|
||||
}
|
||||
|
||||
// Create a temporary thread to be the 'synch model'. We'll use the
|
||||
// existing thread as the 'master model'.
|
||||
lua_State *synch = lua_newthread(L);
|
||||
lua_replace(L, tthread.index());
|
||||
// Call tablecmp_diff.
|
||||
StreamBuffer sb;
|
||||
lua_pushvalue(L, tnmap.index());
|
||||
lua_pushvalue(L, stab.index());
|
||||
lua_xmove(L, synch, 2);
|
||||
lua_pushvalue(L, tnmap.index());
|
||||
lua_pushvalue(L, mtab.index());
|
||||
diff_tables(synch, L, true, &sb);
|
||||
|
||||
patch_table(LS, tangibles, ntmap, stab, &sb);
|
||||
|
||||
LS.call(eql, table_equal, stab, mtab);
|
||||
bool e = LS.ckboolean(eql);
|
||||
if (e) {
|
||||
LS.set(eqlstr, "tables equal");
|
||||
} else {
|
||||
LS.set(eqlstr, "tables were supposed to be equal");
|
||||
}
|
||||
LS.set(rtab, stab);
|
||||
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user