From 9774a017a3baadd3caf3b442f4a22a0bf151d4c9 Mon Sep 17 00:00:00 2001 From: OpportunityLiu Date: Wed, 24 Jul 2019 18:36:49 +0800 Subject: Improve string.serialize; add unit test --- tests/modules/string/serialize/test.lua | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/modules/string/serialize/test.lua (limited to 'tests/modules/string') diff --git a/tests/modules/string/serialize/test.lua b/tests/modules/string/serialize/test.lua new file mode 100644 index 000000000..8d13f6fee --- /dev/null +++ b/tests/modules/string/serialize/test.lua @@ -0,0 +1,36 @@ + +function roundtrip(v) + return string.serialize(v):deserialize() +end + +function test_number(t) + t:are_equal(roundtrip(12), 12) + t:are_equal(roundtrip(0), 0) + t:are_equal(roundtrip(-1), -1) + t:are_equal(roundtrip(7.25), 7.25) + t:are_equal(roundtrip(math.huge), math.huge) + t:are_equal(roundtrip(-math.huge), -math.huge) + t:are_equal(roundtrip(math.nan), math.nan) +end + +function test_boolean(t) + t:are_equal(roundtrip(true), true) + t:are_equal(roundtrip(false), false) +end + +function test_nil(t) + t:are_equal(roundtrip(nil), nil) +end + +function test_table(t) + t:are_equal(roundtrip({}), {}) + t:are_equal(roundtrip({1, 2, 3}), {1, 2, 3}) + t:are_equal(roundtrip({1, "", 3}), {1, "", 3}) + --t:are_equal(roundtrip({{1, 2, 3, nil, 4}}), {{1, 2, 3, nil, 4}}) +end + +function test_function(t) + t:are_equal(roundtrip(function() return {} end)(), {}) + t:are_equal(roundtrip(function() return {1, 2, 3} end)(), {1, 2, 3}) + t:are_equal(roundtrip(function() return {{1, 2, 3, nil, 4}} end)(), {{1, 2, 3, nil, 4}}) +end -- cgit v1.3.1 From 95169f0ec740f0466dfab97424e3c72460764f17 Mon Sep 17 00:00:00 2001 From: OpportunityLiu Date: Thu, 25 Jul 2019 15:25:38 +0800 Subject: add some tests --- tests/modules/string/serialize/test.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tests/modules/string') diff --git a/tests/modules/string/serialize/test.lua b/tests/modules/string/serialize/test.lua index 8d13f6fee..1e1484f98 100644 --- a/tests/modules/string/serialize/test.lua +++ b/tests/modules/string/serialize/test.lua @@ -26,7 +26,8 @@ function test_table(t) t:are_equal(roundtrip({}), {}) t:are_equal(roundtrip({1, 2, 3}), {1, 2, 3}) t:are_equal(roundtrip({1, "", 3}), {1, "", 3}) - --t:are_equal(roundtrip({{1, 2, 3, nil, 4}}), {{1, 2, 3, nil, 4}}) + t:are_equal(roundtrip({{1, 2, 3, nil, 4}}), {{1, 2, 3, nil, 4}}) + t:are_equal(roundtrip({{a=1, b=2, c=3, nil, 4}}), {{a=1, b=2, c=3, nil, 4}}) end function test_function(t) -- cgit v1.3.1 From 5e8049c85f976305206ed2117b71168b1972704c Mon Sep 17 00:00:00 2001 From: OpportunityLiu Date: Thu, 25 Jul 2019 18:31:53 +0800 Subject: add some tests --- tests/modules/string/serialize/test.lua | 3 +++ xmake/core/base/serialize.lua | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'tests/modules/string') diff --git a/tests/modules/string/serialize/test.lua b/tests/modules/string/serialize/test.lua index 1e1484f98..a85868e7e 100644 --- a/tests/modules/string/serialize/test.lua +++ b/tests/modules/string/serialize/test.lua @@ -27,6 +27,7 @@ function test_table(t) t:are_equal(roundtrip({1, 2, 3}), {1, 2, 3}) t:are_equal(roundtrip({1, "", 3}), {1, "", 3}) t:are_equal(roundtrip({{1, 2, 3, nil, 4}}), {{1, 2, 3, nil, 4}}) + t:are_equal(roundtrip({{1, 2, 3, nil, 4, [100]=5}}), {{1, 2, 3, nil, 4, [100]=5}}) t:are_equal(roundtrip({{a=1, b=2, c=3, nil, 4}}), {{a=1, b=2, c=3, nil, 4}}) end @@ -34,4 +35,6 @@ function test_function(t) t:are_equal(roundtrip(function() return {} end)(), {}) t:are_equal(roundtrip(function() return {1, 2, 3} end)(), {1, 2, 3}) t:are_equal(roundtrip(function() return {{1, 2, 3, nil, 4}} end)(), {{1, 2, 3, nil, 4}}) + t:are_equal(roundtrip({function() return {{1, 2, 3, nil, 4}} end})[1](), {{1, 2, 3, nil, 4}}) + t:are_equal(roundtrip({{function() return {{1, 2, 3, nil, 4}} end}})[1][1](), {{1, 2, 3, nil, 4}}) end diff --git a/xmake/core/base/serialize.lua b/xmake/core/base/serialize.lua index 2582daae6..84c74cd34 100644 --- a/xmake/core/base/serialize.lua +++ b/xmake/core/base/serialize.lua @@ -129,7 +129,7 @@ function serialize._maketable(object, opt, level) if type(k) == "string" and not k:match("^[%a_][%w_]*$") then k = string.format("[%q]", k) elseif type(k) == "number" then - local nval, err = serialize._makenumber(v, opt, childlevel) + local nval, err = serialize._makenumber(k, opt, childlevel) if err ~= nil then return nil, err end -- cgit v1.3.1 From 68f96b225c4da758a87a90f5723025be7b2fafc1 Mon Sep 17 00:00:00 2001 From: OpportunityLiu Date: Thu, 25 Jul 2019 19:15:32 +0800 Subject: add binary mode --- tests/modules/string/serialize/test.lua | 7 ++++-- xmake/core/base/serialize.lua | 43 ++++++++++++++++++++++++++++++--- xmake/core/base/string.lua | 8 +++--- 3 files changed, 48 insertions(+), 10 deletions(-) (limited to 'tests/modules/string') diff --git a/tests/modules/string/serialize/test.lua b/tests/modules/string/serialize/test.lua index a85868e7e..1ab3852ba 100644 --- a/tests/modules/string/serialize/test.lua +++ b/tests/modules/string/serialize/test.lua @@ -1,6 +1,9 @@ -function roundtrip(v) - return string.serialize(v):deserialize() +function roundtrip(round0) + local round1 = string.serialize(round0, false):deserialize() + local round2 = string.serialize(round1, true):deserialize() + local round3 = string.serialize(round2, {binary=true}):deserialize() + return round3 end function test_number(t) diff --git a/xmake/core/base/serialize.lua b/xmake/core/base/serialize.lua index 84c74cd34..8b5b233b1 100644 --- a/xmake/core/base/serialize.lua +++ b/xmake/core/base/serialize.lua @@ -138,6 +138,10 @@ function serialize._maketable(object, opt, level) table.insert(s, indent .. k .. con .. v) end end + + if #s == 0 then + return opt.indent and "{ }" or "{}" + end return headstr .. table.concat(s, opt.indent and ",\n" or ",") .. tailstr end @@ -189,7 +193,11 @@ end function serialize.save(object, opt) -- init options - opt = opt or {} + if opt == true then + opt = { strip = true, binary = false, indent = false } + elseif opt == false or opt == nil then + opt = { strip = false, binary = false, indent = true } + end -- make string local result, errors = serialize._make(object, opt, 0) @@ -198,7 +206,19 @@ function serialize.save(object, opt) if errors ~= nil then return nil, errors end - return result + + if not opt.binary then + return result + end + + -- binary mode + local dump, lerr = serialize._dump(loadstring("return " .. result), true) + if lerr ~= nil then + return nil, lerr + end + + -- return shorter representation + return (#dump < #result) and dump or result end -- load table from string in table @@ -206,7 +226,14 @@ function serialize._load(str) -- load table as script local result = nil - local script, errors = loadstring("return " .. str, str) + + local binary = str:startswith("\27LJ") + + if not binary then + str = "return " .. str + end + + local script, errors = loadstring(str) if script then -- load object @@ -217,8 +244,16 @@ function serialize._load(str) -- error errors = object else + local data + if binary then + data = "" + elseif #str > 20 then + data = str:sub(8, 17) .. "..." + else + data = str:sub(8) + end -- error - errors = string.format("cannot deserialize string: %s", str) + errors = string.format("cannot deserialize string: %s", data) end end diff --git a/xmake/core/base/string.lua b/xmake/core/base/string.lua index 30c374def..6579ef7de 100644 --- a/xmake/core/base/string.lua +++ b/xmake/core/base/string.lua @@ -203,13 +203,13 @@ end -- serialize to string from the given object -- --- @param deflate deflate empty characters +-- @param opt serialize options +-- e.g. { strip = true, binary = false, indent = true } -- -- @return string, errors -- -function string.serialize(object, deflate) - deflate = not not deflate - return serialize.save(object, { strip = deflate, indent = not deflate }) +function string.serialize(object, opt) + return serialize.save(object, opt) end -- deserialize string to object -- cgit v1.3.1 From b724d37e01b4a12d1b5eea3a9a866ba4b8c4e46d Mon Sep 17 00:00:00 2001 From: OpportunityLiu Date: Thu, 25 Jul 2019 19:45:45 +0800 Subject: fix style --- tests/modules/string/serialize/test.lua | 4 +++- xmake/core/base/serialize.lua | 30 ++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'tests/modules/string') diff --git a/tests/modules/string/serialize/test.lua b/tests/modules/string/serialize/test.lua index 1ab3852ba..567bee87f 100644 --- a/tests/modules/string/serialize/test.lua +++ b/tests/modules/string/serialize/test.lua @@ -3,7 +3,9 @@ function roundtrip(round0) local round1 = string.serialize(round0, false):deserialize() local round2 = string.serialize(round1, true):deserialize() local round3 = string.serialize(round2, {binary=true}):deserialize() - return round3 + local round4 = string.serialize(round3, {indent=16}):deserialize() + local round5 = string.serialize(round4, {indent=" \r\n\t"}):deserialize() + return round5 end function test_number(t) diff --git a/xmake/core/base/serialize.lua b/xmake/core/base/serialize.lua index 8b5b233b1..4a9392ebe 100644 --- a/xmake/core/base/serialize.lua +++ b/xmake/core/base/serialize.lua @@ -86,16 +86,12 @@ function serialize._maketable(object, opt, level) -- make indent local indent = "" if opt.indent then - indent = string.rep(" ", level) + indent = string.rep(opt.indent, level) end -- make head - local headstr - if opt.indent then - headstr = (level > 0 and "\n" or "") .. indent .. "{\n" - else - headstr = "{" - end + local headstr = opt.indent and "{\n" or "{" + -- make tail local tailstr if opt.indent then @@ -107,7 +103,7 @@ function serialize._maketable(object, opt, level) -- make body local s = {} if opt.indent then - indent = indent .. " " + indent = string.rep(opt.indent, level + 1) end if isarr then @@ -199,6 +195,24 @@ function serialize.save(object, opt) opt = { strip = false, binary = false, indent = true } end + if not opt.indent then + opt.indent = false + elseif type(opt.indent) == "boolean" then + opt.indent = " " + elseif type(opt.indent) == "number" then + if opt.indent < 0 then + opt.indent = false + else + opt.indent = string.rep(" ", opt.indent) + end + elseif type(opt.indent) == "string" then + if not opt.indent:match("^%s+$") then + return nil, "invalid opt.indent, only whitespaces are accepted" + end + else + return nil, "invalid opt.indent, should be boolean, number or string" + end + -- make string local result, errors = serialize._make(object, opt, 0) -- cgit v1.3.1