talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

root.zig (2873B)


      1 const std = @import("std");
      2 const tlds = @import("tlds.zig");
      3 const testing = std.testing;
      4 
      5 export fn fence_is_top_level_domain(dom: [*:0]const u8) bool {
      6     return isTopLevelDomain(std.mem.span(dom));
      7 }
      8 
      9 fn isTopLevelDomain(dom: []const u8) bool {
     10     for (tlds.tab) |tld| {
     11         if (std.mem.eql(u8, dom, tld)) return true;
     12     }
     13     return false;
     14 }
     15 
     16 fn isRfc822Char(c: u8) bool {
     17     if (!std.ascii.isAscii(c)) return false;
     18     switch (c) {
     19         0...32, 127 => return false,
     20         '(', ')', ',', ';', '<', '>', '"' => return false,
     21     }
     22     return true;
     23 }
     24 
     25 fn quoteDepth(line: []const u8) u8 {
     26     const ln = std.mem.trim(u8, line, &std.ascii.whitespace);
     27     const first = std.mem.indexOfScalar(u8, ln, '>') orelse return 0;
     28     if (first != 0) return 0;
     29 
     30     var depth: u8 = 0;
     31     const last = std.mem.lastIndexOfScalar(u8, ln, '>') orelse return 1;
     32     for (line[first .. last + 1]) |c| {
     33         if (c == '>') {
     34             if (depth == 0xff) return depth;
     35             depth += 1;
     36             continue;
     37         }
     38         if (std.ascii.isWhitespace(c)) continue;
     39         break;
     40     }
     41     return depth;
     42 }
     43 
     44 export fn quote_depth(line: [*:0]const u8) c_int {
     45     const n = quoteDepth(std.mem.span(line));
     46     return @as(c_int, n);
     47 }
     48 
     49 fn copyAfterLine(dst: std.fs.File, src: std.fs.File, key: []const u8) !usize {
     50     var rbuf: [8192]u8 = undefined;
     51     var rd = std.fs.File.reader(src, &rbuf).interface;
     52     var wbuf: [8192]u8 = undefined;
     53     var wr = std.fs.File.writer(dst, &wbuf).interface;
     54     while (true) {
     55         const line = try rd.takeDelimiterInclusive('\n');
     56         if (std.mem.startsWith(u8, line, key)) {
     57             break;
     58         }
     59     }
     60     const n = try rd.streamRemaining(&wr);
     61     try wr.flush();
     62     return n;
     63 }
     64 
     65 export fn fence_copy_after_line(dst: [*:0]const u8, src: [*:0]const u8, line: [*:0]const u8) usize {
     66     const fdst = std.fs.cwd().createFile(std.mem.span(dst), .{}) catch return 0;
     67     defer fdst.close();
     68     const fsrc = std.fs.cwd().openFile(std.mem.span(src), .{}) catch return 0;
     69     defer fsrc.close();
     70     return copyAfterLine(fdst, fsrc, std.mem.span(line)) catch 0;
     71 }
     72 
     73 test "quote depth" {
     74     const tests = [_]struct { []const u8, u8 }{
     75         .{ ">>> hello", 3 },
     76         .{ ">    >> hello", 3 },
     77         .{ "     > hello >", 1 },
     78         .{ "hello>>", 0 },
     79         .{ ">> hello >>", 2 },
     80         .{ ">  \t> hello", 2 },
     81         .{ ">", 1 },
     82         .{ "xxx > hello >>", 0 },
     83     };
     84     for (tests) |t| {
     85         const got = quoteDepth(t[0]);
     86         errdefer std.debug.print("quote depth for \"{s}\"\n", .{t[0]});
     87         try testing.expectEqual(t[1], got);
     88     }
     89 }
     90 
     91 test "check domains" {
     92     try testing.expect(isTopLevelDomain("com"));
     93     try testing.expect(isTopLevelDomain("69yamum") == false);
     94 
     95     const str = [_:0]u8{ 'c', 'o', 'm', 0 };
     96     try testing.expect(fence_is_top_level_domain(str[0..]));
     97 }