| 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 | |
| 3 | const std = @import("std"); |
| 4 | const nfs = @import("nfs"); |
| 5 | const nio = @import("nio"); |
| 6 | const extras = @import("extras"); |
| 7 | |
| 8 | const deps = @import("./deps.zig"); |
| 9 | |
| 10 | pub 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 | |
| 73 | const 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 | }; |