From 05f5c01ba6b609f8b15574412fd874adda322590 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 25 Aug 2012 10:58:53 +0100 Subject: CLOD: Simple list methods with simple algorithm for replacement strategy --- lib/clod.lua | 42 ++++++++++++++++++++++++++++++++++++++ test/test-clod.lua | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/lib/clod.lua b/lib/clod.lua index 7696d5e..4114fd6 100644 --- a/lib/clod.lua +++ b/lib/clod.lua @@ -177,6 +177,16 @@ function settings_mt:__newindex(subkey, value) if last.key then insert_blank = true end + else + -- Starting at longest_prefix_found_at, iterate + -- until it no longer matches the prefix + local entry = longest_prefix_found_at + while entry.next and (entry.next.key and + (entry.next.key:sub(1, longest_prefix) == + longest_prefix_found_at.key:sub(1, longest_prefix))) do + entry = entry.next + end + longest_prefix_found_at = entry end local before = longest_prefix_found_at if insert_blank then @@ -242,6 +252,38 @@ function methods:each(prefix) return iterator, metadata[self], nil end +function methods:get_list(prefix) + local ret = {} + local map = {} + for k, v in self:each(prefix) do + ret[#ret+1] = k + map[k] = v + end + table.sort(ret) + for i = 1, #ret do + ret[i] = map[ret[i]] + end + return ret +end + +function methods:set_list(prefix, list) + -- This algorithm isn't perfect, but it'll do in the face of + -- lazy apps devs who don't look after keys/value pairs themselves + local old_list = self:get_list(prefix) + -- Step one is to update all extant entries + for i = 1, #list do + local key = ("%s.i_%d"):format(prefix, i) + self.settings[key] = list[i] + end + -- If the new list is shorter, delete trailing entries + if #list < #old_list then + for i = #list + 1, #old_list do + local key = ("%s.i_%d"):format(prefix, i) + self.settings[key] = nil + end + end +end + -- Metamethods for clod instances function clod_mt:__index(key) if key == "settings" then diff --git a/test/test-clod.lua b/test/test-clod.lua index f8baa77..7fc05cd 100644 --- a/test/test-clod.lua +++ b/test/test-clod.lua @@ -256,6 +256,65 @@ owner.name "Daniel" assert(not had_owner) end +function suite.get_list() + local input_str = [[ +foo["*"] "Hello" +foo["*"] "World" +]] + local conf = clod.parse(input_str) + local list = conf:get_list('foo') + assert(#list == 2) + assert(list[1] == "Hello") + assert(list[2] == "World") +end + +function suite.set_list_same_length() + local input_str = [[ +foo["*"] "Hello" +foo["*"] "World" +]] + local conf = clod.parse(input_str) + local list = { "Yeesh", "Gawd" } + conf:set_list("foo", list) + local output_str = [[ +foo["*"] "Yeesh" +foo["*"] "Gawd" +]] + assert(conf:serialise() == output_str) +end + +function suite.set_list_longer_length() + local input_str = [[ +foo["*"] "Hello" +foo["*"] "World" +]] + local conf = clod.parse(input_str) + local list = { "Yeesh", "Gawd", "Cripes" } + conf:set_list("foo", list) + local output_str = [[ +foo["*"] "Yeesh" +foo["*"] "Gawd" +foo["*"] "Cripes" +]] + assert(conf:serialise() == output_str) +end + +function suite.set_list_shorter_length() + local input_str = [[ +foo["*"] "Hello" +foo["*"] "World" +foo["*"] "Badger" +]] + local conf = clod.parse(input_str) + local list = { "Yeesh", "Gawd" } + conf:set_list("foo", list) + local output_str = [[ +foo["*"] "Yeesh" +foo["*"] "Gawd" +]] + assert(conf:serialise() == output_str) +end + local count_ok = 0 for _, testname in ipairs(testnames) do -- print("Run: " .. testname) -- cgit v1.2.1