aboutsummaryrefslogtreecommitdiff
path: root/src/storage/image-manager/root.zig
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2025-11-19 09:15:49 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2025-11-19 09:15:49 +0100
commit4c06eb64cbed3562e428ce59857d1763098638f3 (patch)
treecc9c8164e76cd48e1dd4ef963329dcfa3c1b152f /src/storage/image-manager/root.zig
parent6201307fecf8398a1b53bf276bc08bfbb3524899 (diff)
allow images to upload and sort if according to their datetime
Diffstat (limited to 'src/storage/image-manager/root.zig')
-rw-r--r--src/storage/image-manager/root.zig79
1 files changed, 60 insertions, 19 deletions
diff --git a/src/storage/image-manager/root.zig b/src/storage/image-manager/root.zig
index 7742df2..7fa1607 100644
--- a/src/storage/image-manager/root.zig
+++ b/src/storage/image-manager/root.zig
@@ -1,24 +1,30 @@
const std = @import("std");
-const Storage = @import("../root.zig");
+const memora = @import("memora");
+const Storage = memora.Storage;
pub const Image = @import("image.zig");
const Self = @This();
pub const empty: Self = .{};
-items: std.ArrayList(Image) = .empty,
-rw_lock: std.Thread.RwLock = .{},
+const Timestamp = struct {
+ index: usize,
+ node: std.DoublyLinkedList.Node,
-pub const LockedImages = struct {
- images: []Image,
- rw_lock: *std.Thread.RwLock,
+ pub fn next(self: *Timestamp) ?*Timestamp {
+ return @fieldParentPtr("node", self.node.next orelse return null);
+ }
- pub fn deinit(self: *const @This()) void {
- self.rw_lock.unlockShared();
+ pub fn prev(self: *Timestamp) ?*Timestamp {
+ return @fieldParentPtr("node", self.node.prev orelse return null);
}
};
+items: std.ArrayList(Image) = .empty,
+rw_lock: std.Thread.RwLock = .{},
+timestamp_order: std.DoublyLinkedList = .{},
+
pub fn init(
self: *Self,
storage: *Storage,
@@ -35,32 +41,67 @@ pub fn init(
while (try iterator.next()) |entry| {
if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".jpg")) {
- try self.items.append(
+ try self.add(
storage.allocator,
- try .init(storage.allocator, entry.name[0..entry.name.len - 4])
+ try .init(storage, entry.name[0..entry.name.len - 4])
);
}
}
}
-pub fn add(
+pub fn add(self: *Self, allocator: std.mem.Allocator, image: Image) !void {
+ self.rw_lock.lock();
+ defer self.rw_lock.unlock();
+
+ try self.items.append(
+ allocator,
+ image,
+ );
+
+ var current = self.timestamp_order.first;
+
+ if (current == null) {
+ const timestamp = try allocator.create(Timestamp);
+ timestamp.index = self.items.items.len - 1;
+ self.timestamp_order.append(&timestamp.node);
+ return;
+ }
+
+ while (current) |c| {
+ const index = @as(*Timestamp, @fieldParentPtr("node", c)).index;
+ if (image.timestamp orelse 0 > self.items.items[index].timestamp orelse 0) {
+ const timestamp = try allocator.create(Timestamp);
+ timestamp.index = self.items.items.len - 1;
+ self.timestamp_order.insertBefore(c, &timestamp.node);
+ break;
+ }
+
+ current = c.next;
+ }
+}
+
+pub fn save(
self: *Self,
storage: *Storage,
reader: *std.Io.Reader,
size: usize,
) !void {
- self.rw_lock.lock();
- defer self.rw_lock.unlock();
+ return self.add(storage.allocator, try Image.new(storage, reader, size));
+}
- try self.items.append(
- storage.allocator,
- try Image.new(storage, reader, size),
- );
+pub fn list(self: *Self) memora.locked.Shared([]Image) {
+ self.rw_lock.lockShared();
+ return .{
+ .value = self.items.items,
+ .rw_lock = &self.rw_lock,
+ };
}
-pub fn list(self: *Self) LockedImages {
+pub fn first_by_timestamp(self: *Self) memora.locked.Shared(?*Timestamp) {
+ self.rw_lock.lockShared();
return .{
- .images = self.items.items,
+ .value = if (self.timestamp_order.first) |first| @fieldParentPtr("node", first)
+ else null,
.rw_lock = &self.rw_lock,
};
}