Implement tag creation
This commit is contained in:
parent
6b5c5aefdc
commit
45747f6069
40
src/Item.zig
40
src/Item.zig
|
@ -23,8 +23,10 @@ pub fn deinit(self: *Self) void {
|
|||
|
||||
// Free each tag
|
||||
for (tags) |*tag| {
|
||||
// Free name
|
||||
allocator.free(tag.name);
|
||||
|
||||
// Free value
|
||||
if (tag.value) |value| {
|
||||
allocator.free(value);
|
||||
}
|
||||
|
@ -49,7 +51,8 @@ pub fn persist(self: *Self, db: *sqlite.Db) !void {
|
|||
// Create new tags if they don't exist
|
||||
// TODO: Do the "if they don't exist" part.
|
||||
for (tags) |*tags_i| {
|
||||
const name_query = "INSERT INTO tag (name) VALUES (?)";
|
||||
const name_query = "INSERT OR IGNORE INTO tag (name) VALUES (?)";
|
||||
// TODO: This does work but doesn't prevent SQLite3 from crying on stdout
|
||||
try db.exec(name_query, .{}, .{ .name = tags_i.name });
|
||||
const rel_query = "INSERT INTO item_tag (item, tag, value) VALUES (?, ?, ?);";
|
||||
try db.exec(rel_query, .{}, .{ .item = self.id, .tag = tags_i.name, .value = tags_i.value });
|
||||
|
@ -110,21 +113,7 @@ pub fn fromJson(jobj: json.Obj, allocator: std.mem.Allocator) !Self {
|
|||
|
||||
if (jobj.objectGet("tags") catch null) |*jtags| {
|
||||
defer jtags.deinit();
|
||||
|
||||
// Reserve space for slice of tags
|
||||
const len = @intCast(usize, jtags.objectLen());
|
||||
tags = try allocator.alloc(Tag, len);
|
||||
|
||||
var iter = jtags.objectGetIterator();
|
||||
|
||||
var i: usize = 0;
|
||||
while (iter.next()) |*tag| {
|
||||
// Whe know it's not null at this point
|
||||
tags.?[i].name = try allocator.dupeZ(u8, tag.key);
|
||||
tags.?[i].value = if (tag.value) |*value| try allocator.dupeZ(u8, value.getString()) else null;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
tags = try tagsFromJson(jobj, allocator);
|
||||
}
|
||||
|
||||
var id: ?i64 = null;
|
||||
|
@ -144,3 +133,22 @@ pub fn fromJson(jobj: json.Obj, allocator: std.mem.Allocator) !Self {
|
|||
.allocator = allocator,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn tagsFromJson(jobj: *json.Obj, allocator: std.mem.Allocator) ![]Tag {
|
||||
// Reserve space for slice of tags
|
||||
const len = @intCast(usize, jobj.objectLen());
|
||||
var tags = try allocator.alloc(Tag, len);
|
||||
|
||||
var iter = jobj.objectGetIterator();
|
||||
|
||||
var i: usize = 0;
|
||||
while (iter.next()) |*tag| {
|
||||
// Whe know it's not null at this point
|
||||
tags[i].name = try allocator.dupeZ(u8, tag.key);
|
||||
tags[i].value = if (tag.value) |*value| try allocator.dupeZ(u8, value.getString()) else null;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
|
88
src/json.zig
88
src/json.zig
|
@ -17,10 +17,8 @@ pub const Obj = struct {
|
|||
// Option because a null value is treated as the C value NULL in json-c
|
||||
obj: ?*c.json_object,
|
||||
|
||||
// TODO: Port type attribute to a zig enum and assign it upon creation
|
||||
|
||||
///////////////////////////////////
|
||||
// ** General functions **
|
||||
// ** Object creation **
|
||||
/////////////////////////////////
|
||||
|
||||
pub fn newObject() Obj {
|
||||
|
@ -42,6 +40,14 @@ pub const Obj = struct {
|
|||
return Obj{ .obj = c.json_tokener_parse(s).? };
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Obj) void {
|
||||
_ = c.json_object_put(self.obj);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// ** General functions **
|
||||
/////////////////////////////////
|
||||
|
||||
const TypeError = error {
|
||||
TypeMismatch, // Tried to use a function on the wrong JSON format
|
||||
};
|
||||
|
@ -51,6 +57,16 @@ pub const Obj = struct {
|
|||
return @intToEnum(Type, c.json_object_get_type(self.obj));
|
||||
}
|
||||
|
||||
// Not *const Obj because the json_object retains ownership of the string
|
||||
pub fn toString(self: *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);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// ** Getters **
|
||||
/////////////////////////////////
|
||||
|
||||
// Not *const Obj because the json_object retains ownership of the string
|
||||
pub fn getString(self: *Obj) []const u8 {
|
||||
// TODO: Check type to not allow other types
|
||||
|
@ -61,16 +77,6 @@ pub const Obj = struct {
|
|||
return c.json_object_get_int64(self.obj);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Obj) void {
|
||||
_ = c.json_object_put(self.obj);
|
||||
}
|
||||
|
||||
// Not *const Obj because the json_object retains ownership of the string
|
||||
pub fn toString(self: *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);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// ** Object functions **
|
||||
/////////////////////////////////
|
||||
|
@ -98,18 +104,6 @@ pub const Obj = struct {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn objectLen(self: *const Obj) c_int {
|
||||
return c.json_object_object_length(self.obj);
|
||||
}
|
||||
|
||||
pub fn objectGetIterator(self: *Obj) ObjectIterator {
|
||||
// TODO: Check errors
|
||||
return ObjectIterator{
|
||||
.it = c.json_object_iter_begin(self.obj),
|
||||
.end = c.json_object_iter_end(self.obj),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn objectAdd(self: *Obj, key: [*c]const u8, value: ?*Obj) void {
|
||||
// TODO: Check type and error return
|
||||
|
||||
|
@ -119,6 +113,18 @@ pub const Obj = struct {
|
|||
_ = c.json_object_object_add(self.obj, key, o);
|
||||
}
|
||||
|
||||
pub fn objectLen(self: *const Obj) c_int {
|
||||
return c.json_object_object_length(self.obj);
|
||||
}
|
||||
|
||||
pub fn objectGetIterator(self: *Obj) ObjectIterator {
|
||||
// TODO: Check errors and check it is a JSON Object
|
||||
return ObjectIterator{
|
||||
.it = c.json_object_iter_begin(self.obj),
|
||||
.end = c.json_object_iter_end(self.obj),
|
||||
};
|
||||
}
|
||||
|
||||
pub const ObjectIterator = struct {
|
||||
it: c.json_object_iterator,
|
||||
end: c.json_object_iterator,
|
||||
|
@ -157,14 +163,36 @@ pub const Obj = struct {
|
|||
|
||||
pub fn arrayAdd(self: *Obj, value: ?*Obj) void {
|
||||
// TODO: Check type and error return
|
||||
// TODO: Check if it can accept a null value
|
||||
|
||||
// We need the json-c object or null, not the zig object
|
||||
const o = if (value) |i| i.obj else null;
|
||||
|
||||
_ = c.json_object_array_add(self.obj, o);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Create wrapper types that statically check and know there
|
||||
// won't be any problems
|
||||
pub fn arrayLen(self: Obj) usize {
|
||||
return c.json_object_array_length(self.obj);
|
||||
}
|
||||
|
||||
pub fn arrayGet(self: *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).? };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arrayGetIterator (self: *Obj) ArrayIterator {
|
||||
return ArrayIterator{ .obj = self, .idx = 0 };
|
||||
}
|
||||
|
||||
pub const ArrayIterator = struct {
|
||||
obj: *Obj,
|
||||
idx: usize = 0,
|
||||
|
||||
pub fn next(self: *ArrayIterator) ?Obj {
|
||||
defer self.idx += 1;
|
||||
return self.obj.arrayGet(self.idx);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
59
src/main.zig
59
src/main.zig
|
@ -5,49 +5,38 @@ const Db = @import("Db.zig");
|
|||
const Item = @import("Item.zig");
|
||||
const Tag = @import("Tag.zig");
|
||||
const json = @import("json.zig");
|
||||
const request = @import("request.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
var db = try Db.init();
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
const jsonText: [:0]const u8 =
|
||||
\\{ "add" : [
|
||||
\\ {
|
||||
\\ "tags": {
|
||||
\\ "title": "Programar sistema de TODO",
|
||||
\\ "programming" : "zig",
|
||||
\\ "due" : "2023-01-01"
|
||||
\\ }
|
||||
\\ "fur": "dusk",
|
||||
\\ "made_with": "krita",
|
||||
\\ "date": "2022-10-01",
|
||||
\\ "alunya": null
|
||||
\\ },{
|
||||
\\ "fur": "lara",
|
||||
\\ "made_with": "krita",
|
||||
\\ "date": "2022-04-08",
|
||||
\\ "cell-shading": null
|
||||
\\ },{
|
||||
\\ "made_with": "ballpoint_pen",
|
||||
\\ "date": "2022-11-04",
|
||||
\\ "practice": "",
|
||||
\\ "pose_practice": null
|
||||
\\ },{
|
||||
\\ "fur": "lidiarock1",
|
||||
\\ "made_with": "krita",
|
||||
\\ "date": "2022-02-15",
|
||||
\\ "niko_(oneshot)": null
|
||||
\\ }
|
||||
\\] }
|
||||
;
|
||||
|
||||
var jsonItem = json.Obj.newFromString(jsonText);
|
||||
defer jsonItem.deinit();
|
||||
var jobj = json.Obj.newFromString(jsonText);
|
||||
|
||||
var item = try Item.fromJson(jsonItem, allocator);
|
||||
defer item.deinit();
|
||||
|
||||
try item.persist(&db);
|
||||
|
||||
// ----------
|
||||
|
||||
const jsonText2: [:0]const u8 =
|
||||
\\{ "id" : 1 }
|
||||
;
|
||||
|
||||
var jsonItem2 = json.Obj.newFromString(jsonText2);
|
||||
defer jsonItem2.deinit();
|
||||
|
||||
var item2 = try Item.fromJson(jsonItem2, allocator);
|
||||
defer item2.deinit();
|
||||
|
||||
var jobj = item2.toJson();
|
||||
defer jobj.deinit();
|
||||
|
||||
const tags = try Item.getTagsById(item2.id.?, &db, allocator);
|
||||
std.debug.print("{any}\n", .{tags});
|
||||
|
||||
std.debug.print("{s}\n", .{jobj.toString()});
|
||||
try request.process(&jobj, &db);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
const std = @import("std");
|
||||
const sqlite = @import("sqlite");
|
||||
|
||||
const Db = @import("Db.zig");
|
||||
const Item = @import("Item.zig");
|
||||
const Tag = @import("Tag.zig");
|
||||
const json = @import("json.zig");
|
||||
|
||||
pub fn process(jobj: *json.Obj, db: *sqlite.Db) !void {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
// Test the action to carry and pass the object
|
||||
if (jobj.objectGet("add") catch null) |*jadd| {
|
||||
try add(jadd, db, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(jobj: *json.Obj, db: *sqlite.Db, allocator: std.mem.Allocator) !void {
|
||||
// TODO: Maybe return error when no items in the array?
|
||||
|
||||
var iter = jobj.arrayGetIterator();
|
||||
while(iter.next()) |*jtags| {
|
||||
var item = Item {
|
||||
.id = null,
|
||||
.tags = try Item.tagsFromJson(jtags, allocator),
|
||||
};
|
||||
defer item.deinit();
|
||||
|
||||
// TODO: Return the things that have been added with ID
|
||||
try item.persist(db);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue