Diff

plugins/mod_storage_memory.lua @ 9832:96d9c121547b 0.11

mod_storage_memory: Replace query function with one based on storage_internal (fixes #1322) The :find method in storage_internal works and is easier to read and understand. Future changes should be simpler to apply to both modules.
author Kim Alvefur <zash@zash.se>
date Wed, 27 Feb 2019 10:20:38 +0100
parent 9609:1dfcea523200
child 9834:a657df70cc31
child 9838:40ed04014b97
line wrap: on
line diff
--- a/plugins/mod_storage_memory.lua	Fri Feb 22 07:33:23 2019 +0100
+++ b/plugins/mod_storage_memory.lua	Wed Feb 27 10:20:38 2019 +0100
@@ -68,46 +68,66 @@
 	return key;
 end
 
-local function archive_iter (a, start, stop, step, limit, when_start, when_end, match_with)
-	local item, when, with;
-	local count = 0;
-	coroutine.yield(true); -- Ready
-	for i = start, stop, step do
-		item = a[i];
-		when, with = item.when, item.with;
-		if when >= when_start and when_end >= when and (not match_with or match_with == with) then
-			coroutine.yield(item.key, item.value(), when, with);
-			count = count + 1;
-			if limit and count >= limit then return end
+function archive_store:find(username, query)
+	local items = self.store[username or NULL];
+	if not items then
+		return function () end, 0;
+	end
+	local count = #items;
+	local i = 0;
+	if query then
+		items = array():append(items);
+		if query.key then
+			items:filter(function (item)
+				return item.key == query.key;
+			end);
+		end
+		if query.with then
+			items:filter(function (item)
+				return item.with == query.with;
+			end);
+		end
+		if query.start then
+			items:filter(function (item)
+				return item.when >= query.start;
+			end);
+		end
+		if query["end"] then
+			items:filter(function (item)
+				return item.when <= query["end"];
+			end);
+		end
+		count = #items;
+		if query.reverse then
+			items:reverse();
+			if query.before then
+				for j = 1, count do
+					if (items[j].key or tostring(j)) == query.before then
+						i = j;
+						break;
+					end
+				end
+			end
+		elseif query.after then
+			for j = 1, count do
+				if (items[j].key or tostring(j)) == query.after then
+					i = j;
+					break;
+				end
+			end
+		end
+		if query.limit and #items - i > query.limit then
+			items[i+query.limit+1] = nil;
 		end
 	end
+	return function ()
+		i = i + 1;
+		local item = items[i];
+		if not item then return; end
+		return item.key, item.value(), item.when, item.with;
+	end, count;
 end
 
-function archive_store:find(username, query)
-	local a = self.store[username or NULL] or {};
-	local start, stop, step = 1, #a, 1;
-	local qstart, qend, qwith = -math.huge, math.huge;
-	local limit;
-	if query then
-		module:log("debug", "query included")
-		if query.reverse then
-			start, stop, step = stop, start, -1;
-			if query.before then
-				start = a[query.before];
-			end
-		elseif query.after then
-			start = a[query.after];
-		end
-		limit = query.limit;
-		qstart = query.start or qstart;
-		qend = query["end"] or qend;
-		qwith = query.with;
-	end
-	if not start then return nil, "invalid-key"; end
-	local iter = coroutine.wrap(archive_iter);
-	iter(a, start, stop, step, limit, qstart, qend, qwith);
-	return iter;
-end
 
 function archive_store:delete(username, query)
 	if not query or next(query) == nil then