1// grep '^Zone' africa antarctica asia australasia europe northamerica southamerica etcetera factory backward | cut -d':' -f2- | awk '{$1=$1}1' | cut -d' ' -f2 | sort | grep -e '/'
2
3const std = @import("std");
4const nfs = @import("nfs");
5const nio = @import("nio");
6const extras = @import("extras");
7
8const deps = @import("./deps.zig");
9
10pub fn main() !void {
11 const sources = [_][:0]const u8{
12 "africa",
13 "antarctica",
14 "asia",
15 "australasia",
16 "europe",
17 "northamerica",
18 "southamerica",
19 "etcetera",
20 "factory",
21 "backward",
22 };
23
24 const path = deps.dirs._xw6xua7fqgft;
25 const allocator = std.heap.c_allocator;
26
27 var dir = try nfs.cwd().openDir(path, .{});
28 defer dir.close();
29
30 var zones: std.ArrayList([]const u8) = .empty;
31 defer zones.deinit(allocator);
32
33 for (&sources) |nm| {
34 var file = try dir.openFile(nm, .{});
35 defer file.close();
36
37 const content = try file.mmap();
38 defer nfs.munmap(content);
39
40 var iter = std.mem.splitScalar(u8, content, '\n');
41 while (iter.next()) |line| {
42 if (!std.mem.startsWith(u8, line, "Zone")) continue;
43
44 var jter = std.mem.tokenizeAny(u8, line, " \t");
45 _ = jter.next().?;
46 const name = jter.next().?;
47 if (std.mem.countScalar(u8, name, '/') != 1) continue;
48 try zones.append(allocator, try allocator.dupe(u8, name));
49 }
50 }
51
52 std.mem.sort([]const u8, zones.items, {}, extras.lessThanSlice([]const u8));
53
54 var out_file = try nfs.cwd().createFile("zone.zig", .{});
55 defer out_file.close();
56 var out_w: nio.BufferedWriter(4096, nfs.File) = .init(out_file);
57
58 try out_w.writeAll("pub const Zone = enum {\n");
59 for (zones.items) |z| {
60 try out_w.print(" {},\n", .{FormatId{ .bytes = z }});
61 }
62 try out_w.writeAll("\n");
63 try out_w.writeAll(" pub const BaseType = []const u8;\n");
64 try out_w.writeAll(" pub const default: @This() = .@\"Etc/UTC\";\n");
65 try out_w.writeAll("\n");
66 try out_w.writeAll(" pub fn nprint(self: Zone, writer: anytype) !void {\n");
67 try out_w.writeAll(" return writer.writeAll(@tagName(self));\n");
68 try out_w.writeAll(" }\n");
69 try out_w.writeAll("};\n");
70 try out_w.flush();
71}
72
73const FormatId = struct {
74 bytes: []const u8,
75
76 /// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.
77 pub fn nprint(ctx: FormatId, writer: anytype) !void {
78 const bytes = ctx.bytes;
79 if (std.zig.isValidId(bytes) and (!std.zig.isPrimitive(bytes)) and (!std.zig.isUnderscore(bytes))) {
80 return writer.writeAll(bytes);
81 }
82 try writer.writeAll("@\"");
83 try stringEscape(bytes, writer);
84 try writer.writeAll("\"");
85 }
86
87 fn stringEscape(bytes: []const u8, w: anytype) !void {
88 for (bytes) |byte| switch (byte) {
89 '\n' => try w.writeAll("\\n"),
90 '\r' => try w.writeAll("\\r"),
91 '\t' => try w.writeAll("\\t"),
92 '\\' => try w.writeAll("\\\\"),
93 '"' => try w.writeAll("\\\""),
94 '\'' => try w.writeAll("'"),
95 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeAll(&.{byte}),
96 else => {
97 try w.writeAll("\\x");
98 try w.print("{x:2>0}", .{byte});
99 },
100 };
101 }
102};