Posted 09 August 2012 - 06:35 PM
Hi,
although I think of myself as a descent programmer I'm struggling with a strange Lua-Error at the moment.
I implemented my one "Serializer - Deserializer - Combo" to turn any of the major lua objects into strings for storage.
Everything's working fine except both uses of the find method from the string API return always wrong values.
In the screenshot you see a simple test of my api functions in the lua interpreter.
The error or wrong result occurs only within my deserializer function, but not on it's own when directly tested on a string literal. I looked at the code multiple times and checked if variable "p2" gets changed at any point, but it has the wrong value (very often 7 or 8 regardless of the length of "ms", but sometimes the same or near that) directly after the API call.
I have no clue what else to look for. There aren't any parallel processes, so I can't think of any side effects.
Anyone a clue?
Screenshot from test
[attachment=377:Bug - Deserialize.gif]
– SEE WORKAROUND IN POST 4 –
You can look at all the relevant code and maybe test it on system as well. Maybe it's a memory issue?! I don't know…
Useful code would be:
This tests both methods (serializer should work fine!) and should output the readable serialized result.
In my last test case I skipped the last serialization as the error stops the code in the deserialization step anyways.
If you need more information to understand the code feel free to ask. I just don't want to explain everything in advance.
The test works fine with any other object (number, string, boolean) except tables.
Tables (with unlimited nesting, except empty tables) should work,
if the statement "p2 = ms:find("=",1,true);" results in a correct value for the position of the equal sign (others chars already tested!). Also tested "p2 = string.find(ms,"=",1,true);" as an alternative, but with same result!
Serializer - Function:
Deserializer - Function
although I think of myself as a descent programmer I'm struggling with a strange Lua-Error at the moment.
I implemented my one "Serializer - Deserializer - Combo" to turn any of the major lua objects into strings for storage.
Everything's working fine except both uses of the find method from the string API return always wrong values.
In the screenshot you see a simple test of my api functions in the lua interpreter.
The error or wrong result occurs only within my deserializer function, but not on it's own when directly tested on a string literal. I looked at the code multiple times and checked if variable "p2" gets changed at any point, but it has the wrong value (very often 7 or 8 regardless of the length of "ms", but sometimes the same or near that) directly after the API call.
I have no clue what else to look for. There aren't any parallel processes, so I can't think of any side effects.
Anyone a clue?
Screenshot from test
[attachment=377:Bug - Deserialize.gif]
– SEE WORKAROUND IN POST 4 –
You can look at all the relevant code and maybe test it on system as well. Maybe it's a memory issue?! I don't know…
Useful code would be:
os.unloadAPI("move")
os.loadAPI("move")
move.serialize(move.deserialize(move.serialize({m="asd"})))
(the code is included in an API for turtle movement, so the file is called move atm)This tests both methods (serializer should work fine!) and should output the readable serialized result.
In my last test case I skipped the last serialization as the error stops the code in the deserialization step anyways.
If you need more information to understand the code feel free to ask. I just don't want to explain everything in advance.
The test works fine with any other object (number, string, boolean) except tables.
Tables (with unlimited nesting, except empty tables) should work,
if the statement "p2 = ms:find("=",1,true);" results in a correct value for the position of the equal sign (others chars already tested!). Also tested "p2 = string.find(ms,"=",1,true);" as an alternative, but with same result!
Serializer - Function:
Spoiler
function serialize(obj)
local s = "";
if type(obj) == "string" then
return "s"..":"..tostring(#obj)..":"..obj;
elseif type(obj) == "number" then
s = tostring(obj);
return "n"..":"..tostring(#s)..":"..s;
elseif type(obj) == "boolean" then
s = tostring(obj);
return "b"..":"..tostring(#s)..":"..s;
elseif type(obj) == "table" then
if next(obj) == nil then
error("serialize - cannot convert empty table");
end;
local k,v;
for k,v in pairs(obj) do
local m = k.."="..serialize(v);
s = s..",m"..":"..tostring(#m)..":"..m;
end;
return "t"..":"..tostring(#s-1)..":"..s:sub(2);
else
error("serialize - cannot convert function, thread or userdata to string");
end;
end;
Deserializer - Function
Spoiler
function deserialize(s)
local p, p2, p3;
local t,os,ms,mn,mos,obj;
local success;
local function dechunk(c,from)
local p = from;
local t,sz,os,p2;
t = c:sub(p,p);
p = p + 1;
if c:sub(p,p) ~= ":" then return false; end;
p = p + 1;
p2 = c:find(":",p,true);
if p2 == nil then return false; end;
sz = tonumber(c:sub(p,p2-1));
if sz == nil then return false; end;
os = c:sub(p2+1,p2+sz);
p = p2+sz;
if p > #c then return false; end;
p = p + 1
return true,t,os,p;
end;
success, t, os = dechunk(s,1);
if not success then
error("deserialize - unable to dechunk input string:"..s:sub(1,10).."...");
end;
if t == "s" then
obj = os;
elseif t == "n" then
obj = tonumber(os);
if type(obj) ~= "number" then
error("deserialize - not a valid number format:"..os);
end;
elseif t == "b" then
if #os ~= 4 and #os ~= 5 then
error("deserialize - not a valid boolean format:"..os);
end;
obj = (os == "true");
elseif t == "t" then
obj = {};
os = ","..os;
p = 1;
repeat
if os:sub(p,p) ~= "," then
error("deserialize - comma-leaded member expected:"..os:sub(p,10).."...");
end;
p = p + 1;
success, t, ms, p2 = dechunk(os,p);
if not success or t ~= "m" then
error("deserialize - unable to dechunk table member:"..os:sub(p,p+15).."...");
end;
p = p2;
p2 = ms:find("=",1,true);
if p2 == nil then
error("deserialize - invalid member string:"..ms);
end;
mn = ms:sub(1,p2-1);
mos = ms:sub(p2+1);
term.write("ms="..ms..", p2="..p2..", mn="..mn..", mos="..mos);
obj[mn] = deserialize(mos);
until p > #s;
else
error("deserialize - unknown chunk type:"..t);
end;
return obj;
end;