Lots of things, idk o_0

This commit is contained in:
Dendy 2023-02-24 09:38:14 +01:00
parent 4f59f87fbf
commit 3e85bcde6c
6 changed files with 107 additions and 83 deletions

View File

@ -12,7 +12,6 @@ pub fn build(b: *std.build.Builder) void {
const mode = b.standardReleaseOptions();
const exe = b.addExecutable("mgtzm", "src/main.zig");
exe.use_stage1 = true; // for sqlite
// Add dependencies
exe.linkSystemLibrary("json-c");

View File

@ -41,7 +41,7 @@ const SubtagIterator = struct {
const opt_i = std.mem.indexOfScalarPos(u8, self.orig_tag, index, ':');
if (opt_i) |i| {
defer self.index = i+1;
defer self.index = i + 1;
return self.orig_tag[0..i];
}
@ -87,7 +87,7 @@ pub fn persist(self: *Self, db: *Db, allocator: std.mem.Allocator) !void {
var iter = SubtagIterator.init(tag);
while (iter.next()) |subtag| {
// allocate "tag:<tagname>"
var tagkey = try std.mem.concat(allocator, u8, &[_][]const u8{"tag:", subtag});
var tagkey = try std.mem.concat(allocator, u8, &[_][]const u8{ "tag:", subtag });
defer allocator.free(tagkey);
// Append the tag to the total of tags if it doesn't exist
@ -215,7 +215,7 @@ pub fn fromJson(jobj: json.Obj, allocator: std.mem.Allocator) !Self {
};
}
pub fn tagsFromJson(jobj: *json.Obj, allocator: std.mem.Allocator) ![]Tag {
pub fn tagsFromJson(jobj: *const json.Obj, allocator: std.mem.Allocator) ![]Tag {
// Reserve space for slice of tags
const len = @intCast(usize, jobj.arrayLen());
var tags = try allocator.alloc(Tag, len);

View File

@ -4,7 +4,7 @@ pub const c = @cImport({
const std = @import("std");
const Type = enum(c.json_type) {
@"null" = c.json_type_null,
null = c.json_type_null,
boolean = c.json_type_boolean,
double = c.json_type_double,
int = c.json_type_int,
@ -36,8 +36,14 @@ pub const Obj = struct {
pub fn newInt64(i: i64) Obj {
return Obj{ .obj = c.json_object_new_int64(i).? };
}
pub fn newFromString(s: [*c]const u8) Obj {
return Obj{ .obj = c.json_tokener_parse(s).? };
pub fn newFromString(s: [*c]const u8) !Obj {
const FromStringError = error{
MalformedString,
};
return Obj{
.obj = c.json_tokener_parse(s) orelse return FromStringError.MalformedString,
};
}
pub fn deinit(self: *Obj) void {
@ -48,7 +54,7 @@ pub const Obj = struct {
// ** General functions **
/////////////////////////////////
const TypeError = error {
const TypeError = error{
TypeMismatch, // Tried to use a function on the wrong JSON format
};
@ -58,7 +64,7 @@ pub const Obj = struct {
}
// Not *const Obj because the json_object retains ownership of the string
pub fn toString(self: *Obj) []const u8 {
pub fn toString(self: *const Obj) []const u8 {
// TODO: Allow passing of flags as an enum like the SDL2 binding
return std.mem.sliceTo(c.json_object_to_json_string(self.obj), 0);
}
@ -68,7 +74,7 @@ pub const Obj = struct {
/////////////////////////////////
// Not *const Obj because the json_object retains ownership of the string
pub fn getString(self: *Obj) []const u8 {
pub fn getString(self: *const Obj) []const u8 {
// TODO: Check type to not allow other types
return std.mem.sliceTo(c.json_object_get_string(self.obj), 0);
}
@ -94,17 +100,17 @@ pub const Obj = struct {
// Everything went alright
if (obj) |ret| {
return Obj{ .obj = c.json_object_get(ret).? };
} else if (obj == null and succ != 0){
} else if (obj == null and succ != 0) {
// The actual value is just null
return Obj{ .obj = null };
} else if (self.getType() != Type.object){
} else if (self.getType() != Type.object) {
return GetError.TypeMismatch;
} else {
return GetError.KeyNotFound;
}
}
pub fn objectAdd(self: *Obj, key: [*c]const u8, value: ?*Obj) void {
pub fn objectAdd(self: *Obj, key: [*c]const u8, value: ?*const Obj) void {
// TODO: Check type and error return
// We need the json-c object or null, not the zig object
@ -113,6 +119,10 @@ pub const Obj = struct {
_ = c.json_object_object_add(self.obj, key, o);
}
pub fn objectAddString(self: *Obj, key: [*c]const u8, value: [*c]const u8) void {
_ = c.json_object_object_add(self.obj, key, newString(value).obj);
}
pub fn objectLen(self: *const Obj) c_int {
return c.json_object_object_length(self.obj);
}
@ -161,7 +171,7 @@ pub const Obj = struct {
// ** Array functions **
/////////////////////////////////
pub fn arrayAdd(self: *Obj, value: ?*Obj) void {
pub fn arrayAdd(self: *Obj, value: ?*const Obj) void {
// TODO: Check type and error return
// We need the json-c object or null, not the zig object
@ -173,7 +183,7 @@ pub const Obj = struct {
return c.json_object_array_length(self.obj);
}
pub fn arrayGet(self: *Obj, idx: usize) ?Obj {
pub fn arrayGet(self: *const Obj, idx: usize) ?Obj {
// Sould the .? be there?
if (c.json_object_array_get_idx(self.obj, idx)) |obj| {
return Obj{ .obj = c.json_object_get(obj).? };
@ -182,12 +192,12 @@ pub const Obj = struct {
}
}
pub fn arrayGetIterator (self: *Obj) ArrayIterator {
pub fn arrayGetIterator(self: *const Obj) ArrayIterator {
return ArrayIterator{ .obj = self, .idx = 0 };
}
pub const ArrayIterator = struct {
obj: *Obj,
obj: *const Obj,
idx: usize = 0,
pub fn next(self: *ArrayIterator) ?Obj {

View File

@ -5,66 +5,64 @@ const Item = @import("Item.zig");
const Tag = @import("Tag.zig");
const json = @import("json.zig");
const request = @import("request.zig");
const util = @import("util.zig");
pub fn main() !void {
var db = Db.open("test.tkh", true, "");
const sock_path = "/tmp/mgtzm.sock";
// ---------------------- ADD ---------------------------
// Remove the socket file if it exists
std.fs.deleteFileAbsolute(sock_path) catch |err| {
switch (err) {
// Do not error out if the file doesn't exist
error.FileNotFound => {},
else => unreachable,
}
};
const jsonText: [:0]const u8 =
\\{ "add" : [
\\ [
\\ "task:uned:led",
\\ "fur:dusk",
\\ "made_with:krita",
\\ "date:2022:10:01",
\\ "alunya"
\\ ],[
\\ "fur:lara",
\\ "made_with:krita",
\\ "date:2022:04:08",
\\ "cell-shading"
\\ ],[
\\ "made_with:ballpoint_pen",
\\ "date:2022:11:04",
\\ "practice",
\\ "pose_practice"
\\ ],[
\\ "fur:lidiarock1",
\\ "made_with:krita",
\\ "date:2022:10:15",
\\ "niko_(oneshot)"
\\ ]
\\] }
;
var server = std.net.StreamServer.init(.{});
defer server.deinit();
const addr = try std.net.Address.initUnix(sock_path);
var jobj = json.Obj.newFromString(jsonText);
defer jobj.deinit();
try server.listen(addr);
try request.process(&jobj, &db);
while (true) {
std.debug.print("\n\n", .{});
// Initialization
// ----------------
// -------------------- DELETE --------------------------
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
const jsonDelete: [:0]const u8 =
\\{ "delete" : [ "0000", "0003" ] }
;
const connection = try server.accept();
defer connection.stream.close();
var jdelete = json.Obj.newFromString(jsonDelete);
defer jdelete.deinit();
// Receive and process message
// ----------------
try request.process(&jdelete, &db);
const read = connection.stream.reader();
// -------------------- QUERY ---------------------------
var msg = util.readUntilDelimiterAllocZ(read, allocator, 0, 1024) catch |err| {
std.debug.print("Failed to read from connection: {any}\n", .{err});
continue;
};
defer allocator.free(msg);
const jsonQuery: [:0]const u8 =
\\{ "query" : "" }
;
var jobj = json.Obj.newFromString(msg) catch {
var errorObj = json.Obj.newObject();
errorObj.objectAddString("error", "Invalid JSON request.");
var jquery = json.Obj.newFromString(jsonQuery);
defer jquery.deinit();
_ = connection.stream.write(errorObj.toString()) catch {};
continue;
};
defer jobj.deinit();
try request.process(&jquery, &db);
const answer = try request.process(&jobj, &db, allocator);
defer allocator.free(answer);
// Reply
// ----------------
_ = try connection.stream.write(answer);
}
}

View File

@ -6,34 +6,38 @@ const Tag = @import("Tag.zig");
const json = @import("json.zig");
const util = @import("util.zig");
pub fn process(jobj: *json.Obj, db: *Db) !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
pub fn process(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) ![]const u8 {
var jret = json.Obj.newObject();
defer jret.deinit();
// Test the action to carry and pass the object
if (jobj.objectGet("add") catch null) |*jaction| {
// TODO: Change to { "type" : "<action>", "data" : <data> }
// TODO: Automatize this, give a list of actions and autobuild the checks in comptime
if (jobj.objectGet("add")) |*jaction| {
var ret = try add(jaction, db, allocator);
jret.objectAdd("added", &ret);
}
// TODO: Maybe change all of these to "affected"?
jret.objectAddString("type", "added");
jret.objectAdd("data", &ret);
} else |_| {}
if (jobj.objectGet("query") catch null) |*jaction| {
if (jobj.objectGet("query")) |*jaction| {
var ret = try query(jaction, db, allocator);
jret.objectAdd("queried", &ret);
}
jret.objectAddString("type", "queried");
jret.objectAdd("data", &ret);
} else |_| {}
if (jobj.objectGet("delete") catch null) |*jaction| {
if (jobj.objectGet("delete")) |*jaction| {
var ret = try delete(jaction, db, allocator);
jret.objectAdd("deleted", &ret);
}
jret.objectAddString("type", "deleted");
jret.objectAdd("data", &ret);
} else |_| {}
std.debug.print("{s}\n", .{jret.toString()});
const ret_str = std.mem.sliceTo(jret.toString(), 0);
return allocator.dupe(u8, ret_str);
}
pub fn add(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
pub fn add(jobj: *const json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
// TODO: Maybe return error when no items in the array?
// Freed by the caller
@ -57,7 +61,7 @@ pub fn add(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
return jret;
}
pub fn query(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
pub fn query(jobj: *const json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
// TODO: Have into account limits so it is scalable
// TODO: Do not fetch EVERY id at once, iterate where possible
const query_str = jobj.getString();
@ -100,7 +104,7 @@ pub fn query(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
return jret;
}
pub fn delete(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
pub fn delete(jobj: *const json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
var jret = json.Obj.newArray();
// Go over each tag

View File

@ -1,12 +1,11 @@
const std = @import("std");
pub const IntersectionIterator = struct {
ref: std.mem.TokenIterator(u8),
rest: []const []const u8,
/// Returns the next occurrence or null. Returned value is owned by originally passed slice
pub fn next(self: *IntersectionIterator) ?[]const u8{
pub fn next(self: *IntersectionIterator) ?[]const u8 {
// If this returns null, there's no more items to check. We're finished.
const needle = self.ref.next() orelse return null;
@ -40,3 +39,17 @@ pub fn intersection(slices: []const []const u8) IntersectionIterator {
.rest = slices[1..],
};
}
pub fn readUntilDelimiterAllocZ(
reader: anytype, // TODO: Fix this and set the correct type, I got no clue rn
allocator: std.mem.Allocator,
delimiter: u8,
max_size: usize,
) ![:0]u8 {
var array_list = std.ArrayList(u8).init(allocator);
defer array_list.deinit();
try reader.readUntilDelimiterArrayList(&array_list, delimiter, max_size);
return array_list.toOwnedSliceSentinel(0);
}