Changes
4 changed files (+227/-0)
-
-
@@ -652,6 +652,209 @@ exportActionGetter(MessageAction, .message, "get_message_action");} }; const LabelParser = struct { const State = enum { non_link, id, label_text, }; pub fn parse(allocator: std.mem.Allocator, src: []const u8) std.mem.Allocator.Error![:0]const u8 { const dst = try allocator.allocSentinel(u8, src.len, 0); errdefer allocator.free(dst); @memset(dst, 0); var src_i: usize = 0; var dst_i: usize = 0; state: switch (State.non_link) { .non_link => { if (src_i >= src.len) { break :state; } if (std.mem.startsWith(u8, src[src_i..], "[[")) { src_i += 2; continue :state .id; } dst[dst_i] = src[src_i]; src_i += 1; dst_i += 1; continue :state .non_link; }, .id => { if (src_i >= src.len) { break :state; } defer src_i += 1; if (src[src_i] == '|') { continue :state .label_text; } continue :state .id; }, .label_text => { if (src_i >= src.len) { break :state; } if (std.mem.startsWith(u8, src[src_i..], "]]")) { src_i += 2; continue :state .non_link; } dst[dst_i] = src[src_i]; src_i += 1; dst_i += 1; continue :state .label_text; }, } return dst; } }; test LabelParser { { const x = try LabelParser.parse(std.testing.allocator, "Foo [[123|Bar]] Baz"); defer std.testing.allocator.free(x); try std.testing.expectEqualStrings("Foo Bar Baz", std.mem.span(x.ptr)); } { const x = try LabelParser.parse(std.testing.allocator, "[[123|Bar]]"); defer std.testing.allocator.free(x); try std.testing.expectEqualStrings("Bar", std.mem.span(x.ptr)); } { const x = try LabelParser.parse(std.testing.allocator, "[123|Bar]"); defer std.testing.allocator.free(x); try std.testing.expectEqualStrings("[123|Bar]", std.mem.span(x.ptr)); } { const x = try LabelParser.parse(std.testing.allocator, "[[]]"); defer std.testing.allocator.free(x); try std.testing.expectEqualStrings("", std.mem.span(x.ptr)); } { const x = try LabelParser.parse(std.testing.allocator, "[[|]]Foo"); defer std.testing.allocator.free(x); try std.testing.expectEqualStrings("Foo", std.mem.span(x.ptr)); } { const x = try LabelParser.parse(std.testing.allocator, "Foo Bar"); defer std.testing.allocator.free(x); try std.testing.expectEqualStrings("Foo Bar", std.mem.span(x.ptr)); } { const global = struct { fn testOne(_: void, input: []const u8) anyerror!void { const x = try LabelParser.parse(std.testing.allocator, input); defer std.testing.allocator.free(x); } }; try std.testing.fuzz(void{}, global.testOne, .{}); } } const Label = extern struct { const cname = "plac_browse_label"; const allocator = std.heap.c_allocator; internal: *Internal, plain_text: [*:0]const u8, const Internal = struct { arc: Arc = .{}, plain_text: [:0]const u8, const ParseState = enum { non_link, id, label_text, }; pub fn init(src: []const u8) std.mem.Allocator.Error!@This() { return .{ .plain_text = try LabelParser.parse(allocator, src) }; } pub fn deinit(self: *const Internal) void { allocator.free(self.plain_text); } }; fn make(src: []const u8) std.mem.Allocator.Error!*@This() { const internal = try allocator.create(Internal); errdefer allocator.destroy(internal); internal.* = try Internal.init(src); errdefer internal.deinit(); const self = try allocator.create(@This()); errdefer allocator.destroy(self); self.* = .{ .internal = internal, .plain_text = internal.plain_text, }; return self; } fn makeRetained(src: [*:0]const u8) callconv(.C) ?*@This() { const result = make(std.mem.span(src)) catch { return null; }; return result.retain(); } fn retain(ptr: ?*@This()) callconv(.C) *@This() { var self = ptr orelse @panic( std.fmt.comptimePrint("Received null pointer on {s}_{s}", .{ cname, @src().fn_name }), ); self.internal.arc.ref(); return self; } fn release(ptr: ?*@This()) callconv(.C) void { var self = ptr orelse @panic( std.fmt.comptimePrint("Received null pointer on {s}_{s}", .{ cname, @src().fn_name }), ); if (self.internal.arc.unref()) { freelog(self); self.internal.deinit(); allocator.destroy(self.internal); allocator.destroy(self); } } pub fn export_capi() void { @export(&makeRetained, .{ .name = std.fmt.comptimePrint("{s}_from_string", .{cname}) }); @export(&retain, .{ .name = std.fmt.comptimePrint("{s}_retain", .{cname}) }); @export(&release, .{ .name = std.fmt.comptimePrint("{s}_release", .{cname}) }); } }; pub fn export_capi() void { InputPrompt.export_capi(); Item.export_capi();
-
@@ -660,4 +863,5 @@ ListAction.export_capi();ErrorMessageAction.export_capi(); MessageAction.export_capi(); Result.export_capi(); Label.export_capi(); }
-
-
-
@@ -29,6 +29,7 @@ transport.export_capi();} test { _ = @import("./browse.zig"); _ = @import("./connection.zig"); _ = @import("./image.zig"); _ = @import("./services/ImageService.zig");
-
-
-
@@ -274,6 +274,15 @@ plac_browse_list_action *plac_browse_result_get_list_action(plac_browse_result*);plac_browse_error_message_action *plac_browse_result_get_error_message_action(plac_browse_result*); plac_browse_message_action *plac_browse_result_get_message_action(plac_browse_result*); // browse.Label typedef struct { void *__pri; const char* plain_text; } plac_browse_label; plac_browse_label *plac_browse_label_from_string(const char*); plac_browse_label *plac_browse_label_retain(plac_browse_label*); void plac_browse_label_release(plac_browse_label*); // image.ScalingMethod typedef enum { PLAC_IMAGE_SCALING_METHOD_FIT = 0,
-
-
-
@@ -385,6 +385,19 @@ public ListAction get_list_action();public ErrorMessageAction get_error_message_action(); public MessageAction get_message_action(); } [CCode ( cname = "plac_browse_label", ref_function = "plac_browse_label_retain", unref_function = "plac_browse_label_release" )] [Compact] public class Label { public string plain_text; [CCode (cname = "plac_browse_label_from_string")] public Label(string src); } } namespace Image {
-