| author | |
| committer | |
| log | 8af59d1f98266bd70b3afb44d196bbd151cedf22 |
| tree | 64b0c48f2b2d222629acbd5698c1f5310fdc708f |
| parent | fefdbca6e62145a20777789961262f15c2bf6cbe |
this patch renames ComptimeStringMap to StaticStringMap, makes it
accept only a single type parameter, and return a known struct type
instead of an anonymous struct. initial motivation for these changes
was to reduce the 'very long type names' issue described here
https://github.com/ziglang/zig/pull/19682.
this breaks the previous API. users will now need to write:
`const map = std.StaticStringMap(T).initComptime(kvs_list);`
* move `kvs_list` param from type param to an `initComptime()` param
* new public methods
* `keys()`, `values()` helpers
* `init(allocator)`, `deinit(allocator)` for runtime data
* `getLongestPrefix(str)`, `getLongestPrefixIndex(str)` - i'm not sure
these belong but have left in for now incase they are deemed useful
* performance notes:
* i posted some benchmarking results here:
https://github.com/travisstaloch/comptime-string-map-revised/issues/1
* i noticed a speedup reducing the size of the struct from 48 to 32
bytes and thus use u32s instead of usize for all length fields
* i noticed speedup storing KVs as a struct of arrays
* latest benchmark shows these wall_time improvements for
debug/safe/small/fast builds: -6.6% / -10.2% / -19.1% / -8.9%. full
output in link above.25 files changed, 608 insertions(+), 387 deletions(-)
CMakeLists.txt+1-1| ... | ... | @@ -222,7 +222,7 @@ set(ZIG_STAGE2_SOURCES |
| 222 | 222 | "${CMAKE_SOURCE_DIR}/lib/std/c/linux.zig" |
| 223 | 223 | "${CMAKE_SOURCE_DIR}/lib/std/child_process.zig" |
| 224 | 224 | "${CMAKE_SOURCE_DIR}/lib/std/coff.zig" |
| 225 | "${CMAKE_SOURCE_DIR}/lib/std/comptime_string_map.zig" | |
| 225 | "${CMAKE_SOURCE_DIR}/lib/std/static_string_map.zig" | |
| 226 | 226 | "${CMAKE_SOURCE_DIR}/lib/std/crypto.zig" |
| 227 | 227 | "${CMAKE_SOURCE_DIR}/lib/std/crypto/blake3.zig" |
| 228 | 228 | "${CMAKE_SOURCE_DIR}/lib/std/crypto/siphash.zig" |
lib/compiler/aro/aro/LangOpts.zig+1-1| ... | ... | @@ -47,7 +47,7 @@ pub const Standard = enum { |
| 47 | 47 | /// Working Draft for ISO C23 with GNU extensions |
| 48 | 48 | gnu23, |
| 49 | 49 | |
| 50 | const NameMap = std.ComptimeStringMap(Standard, .{ | |
| 50 | const NameMap = std.StaticStringMap(Standard).initComptime(.{ | |
| 51 | 51 | .{ "c89", .c89 }, .{ "c90", .c89 }, .{ "iso9899:1990", .c89 }, |
| 52 | 52 | .{ "iso9899:199409", .iso9899 }, .{ "gnu89", .gnu89 }, .{ "gnu90", .gnu89 }, |
| 53 | 53 | .{ "c99", .c99 }, .{ "iso9899:1999", .c99 }, .{ "c9x", .c99 }, |
lib/compiler/aro/aro/Preprocessor.zig+1-1| ... | ... | @@ -1709,7 +1709,7 @@ fn expandFuncMacro( |
| 1709 | 1709 | } |
| 1710 | 1710 | if (!pp.comp.langopts.standard.atLeast(.c23)) break :res not_found; |
| 1711 | 1711 | |
| 1712 | const attrs = std.ComptimeStringMap([]const u8, .{ | |
| 1712 | const attrs = std.StaticStringMap([]const u8).initComptime(.{ | |
| 1713 | 1713 | .{ "deprecated", "201904L\n" }, |
| 1714 | 1714 | .{ "fallthrough", "201904L\n" }, |
| 1715 | 1715 | .{ "maybe_unused", "201904L\n" }, |
lib/compiler/aro/aro/Tokenizer.zig+1-1| ... | ... | @@ -872,7 +872,7 @@ pub const Token = struct { |
| 872 | 872 | }; |
| 873 | 873 | } |
| 874 | 874 | |
| 875 | const all_kws = std.ComptimeStringMap(Id, .{ | |
| 875 | const all_kws = std.StaticStringMap(Id).initComptime(.{ | |
| 876 | 876 | .{ "auto", auto: { |
| 877 | 877 | @setEvalBranchQuota(3000); |
| 878 | 878 | break :auto .keyword_auto; |
lib/compiler/resinator/errors.zig+1-1| ... | ... | @@ -240,7 +240,7 @@ pub const ErrorDetails = struct { |
| 240 | 240 | // see https://github.com/ziglang/zig/issues/15395 |
| 241 | 241 | _: u26 = 0, |
| 242 | 242 | |
| 243 | pub const strings = std.ComptimeStringMap([]const u8, .{ | |
| 243 | pub const strings = std.StaticStringMap([]const u8).initComptime(.{ | |
| 244 | 244 | .{ "number", "number" }, |
| 245 | 245 | .{ "number_expression", "number expression" }, |
| 246 | 246 | .{ "string_literal", "quoted string literal" }, |
lib/compiler/resinator/rc.zig+65-26| ... | ... | @@ -47,7 +47,10 @@ pub const Resource = enum { |
| 47 | 47 | fontdir_num, |
| 48 | 48 | manifest_num, |
| 49 | 49 | |
| 50 | const map = std.ComptimeStringMapWithEql(Resource, .{ | |
| 50 | const map = std.StaticStringMapWithEql( | |
| 51 | Resource, | |
| 52 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 53 | ).initComptime(.{ | |
| 51 | 54 | .{ "ACCELERATORS", .accelerators }, |
| 52 | 55 | .{ "BITMAP", .bitmap }, |
| 53 | 56 | .{ "CURSOR", .cursor }, |
| ... | ... | @@ -67,7 +70,7 @@ pub const Resource = enum { |
| 67 | 70 | .{ "TOOLBAR", .toolbar }, |
| 68 | 71 | .{ "VERSIONINFO", .versioninfo }, |
| 69 | 72 | .{ "VXD", .vxd }, |
| 70 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 73 | }); | |
| 71 | 74 | |
| 72 | 75 | pub fn fromString(bytes: SourceBytes) Resource { |
| 73 | 76 | const maybe_ordinal = res.NameOrOrdinal.maybeOrdinalFromString(bytes); |
| ... | ... | @@ -157,20 +160,26 @@ pub const OptionalStatements = enum { |
| 157 | 160 | menu, |
| 158 | 161 | style, |
| 159 | 162 | |
| 160 | pub const map = std.ComptimeStringMapWithEql(OptionalStatements, .{ | |
| 163 | pub const map = std.StaticStringMapWithEql( | |
| 164 | OptionalStatements, | |
| 165 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 166 | ).initComptime(.{ | |
| 161 | 167 | .{ "CHARACTERISTICS", .characteristics }, |
| 162 | 168 | .{ "LANGUAGE", .language }, |
| 163 | 169 | .{ "VERSION", .version }, |
| 164 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 170 | }); | |
| 165 | 171 | |
| 166 | pub const dialog_map = std.ComptimeStringMapWithEql(OptionalStatements, .{ | |
| 172 | pub const dialog_map = std.StaticStringMapWithEql( | |
| 173 | OptionalStatements, | |
| 174 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 175 | ).initComptime(.{ | |
| 167 | 176 | .{ "CAPTION", .caption }, |
| 168 | 177 | .{ "CLASS", .class }, |
| 169 | 178 | .{ "EXSTYLE", .exstyle }, |
| 170 | 179 | .{ "FONT", .font }, |
| 171 | 180 | .{ "MENU", .menu }, |
| 172 | 181 | .{ "STYLE", .style }, |
| 173 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 182 | }); | |
| 174 | 183 | }; |
| 175 | 184 | |
| 176 | 185 | pub const Control = enum { |
| ... | ... | @@ -197,7 +206,10 @@ pub const Control = enum { |
| 197 | 206 | state3, |
| 198 | 207 | userbutton, |
| 199 | 208 | |
| 200 | pub const map = std.ComptimeStringMapWithEql(Control, .{ | |
| 209 | pub const map = std.StaticStringMapWithEql( | |
| 210 | Control, | |
| 211 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 212 | ).initComptime(.{ | |
| 201 | 213 | .{ "AUTO3STATE", .auto3state }, |
| 202 | 214 | .{ "AUTOCHECKBOX", .autocheckbox }, |
| 203 | 215 | .{ "AUTORADIOBUTTON", .autoradiobutton }, |
| ... | ... | @@ -220,7 +232,7 @@ pub const Control = enum { |
| 220 | 232 | .{ "SCROLLBAR", .scrollbar }, |
| 221 | 233 | .{ "STATE3", .state3 }, |
| 222 | 234 | .{ "USERBUTTON", .userbutton }, |
| 223 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 235 | }); | |
| 224 | 236 | |
| 225 | 237 | pub fn hasTextParam(control: Control) bool { |
| 226 | 238 | switch (control) { |
| ... | ... | @@ -231,14 +243,17 @@ pub const Control = enum { |
| 231 | 243 | }; |
| 232 | 244 | |
| 233 | 245 | pub const ControlClass = struct { |
| 234 | pub const map = std.ComptimeStringMapWithEql(res.ControlClass, .{ | |
| 246 | pub const map = std.StaticStringMapWithEql( | |
| 247 | res.ControlClass, | |
| 248 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 249 | ).initComptime(.{ | |
| 235 | 250 | .{ "BUTTON", .button }, |
| 236 | 251 | .{ "EDIT", .edit }, |
| 237 | 252 | .{ "STATIC", .static }, |
| 238 | 253 | .{ "LISTBOX", .listbox }, |
| 239 | 254 | .{ "SCROLLBAR", .scrollbar }, |
| 240 | 255 | .{ "COMBOBOX", .combobox }, |
| 241 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 256 | }); | |
| 242 | 257 | |
| 243 | 258 | /// Like `map.get` but works on WTF16 strings, for use with parsed |
| 244 | 259 | /// string literals ("BUTTON", or even "\x42UTTON") |
| ... | ... | @@ -280,10 +295,13 @@ pub const MenuItem = enum { |
| 280 | 295 | menuitem, |
| 281 | 296 | popup, |
| 282 | 297 | |
| 283 | pub const map = std.ComptimeStringMapWithEql(MenuItem, .{ | |
| 298 | pub const map = std.StaticStringMapWithEql( | |
| 299 | MenuItem, | |
| 300 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 301 | ).initComptime(.{ | |
| 284 | 302 | .{ "MENUITEM", .menuitem }, |
| 285 | 303 | .{ "POPUP", .popup }, |
| 286 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 304 | }); | |
| 287 | 305 | |
| 288 | 306 | pub fn isSeparator(bytes: []const u8) bool { |
| 289 | 307 | return std.ascii.eqlIgnoreCase(bytes, "SEPARATOR"); |
| ... | ... | @@ -297,14 +315,17 @@ pub const MenuItem = enum { |
| 297 | 315 | menubarbreak, |
| 298 | 316 | menubreak, |
| 299 | 317 | |
| 300 | pub const map = std.ComptimeStringMapWithEql(Option, .{ | |
| 318 | pub const map = std.StaticStringMapWithEql( | |
| 319 | Option, | |
| 320 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 321 | ).initComptime(.{ | |
| 301 | 322 | .{ "CHECKED", .checked }, |
| 302 | 323 | .{ "GRAYED", .grayed }, |
| 303 | 324 | .{ "HELP", .help }, |
| 304 | 325 | .{ "INACTIVE", .inactive }, |
| 305 | 326 | .{ "MENUBARBREAK", .menubarbreak }, |
| 306 | 327 | .{ "MENUBREAK", .menubreak }, |
| 307 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 328 | }); | |
| 308 | 329 | }; |
| 309 | 330 | }; |
| 310 | 331 | |
| ... | ... | @@ -312,10 +333,13 @@ pub const ToolbarButton = enum { |
| 312 | 333 | button, |
| 313 | 334 | separator, |
| 314 | 335 | |
| 315 | pub const map = std.ComptimeStringMapWithEql(ToolbarButton, .{ | |
| 336 | pub const map = std.StaticStringMapWithEql( | |
| 337 | ToolbarButton, | |
| 338 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 339 | ).initComptime(.{ | |
| 316 | 340 | .{ "BUTTON", .button }, |
| 317 | 341 | .{ "SEPARATOR", .separator }, |
| 318 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 342 | }); | |
| 319 | 343 | }; |
| 320 | 344 | |
| 321 | 345 | pub const VersionInfo = enum { |
| ... | ... | @@ -327,7 +351,10 @@ pub const VersionInfo = enum { |
| 327 | 351 | file_type, |
| 328 | 352 | file_subtype, |
| 329 | 353 | |
| 330 | pub const map = std.ComptimeStringMapWithEql(VersionInfo, .{ | |
| 354 | pub const map = std.StaticStringMapWithEql( | |
| 355 | VersionInfo, | |
| 356 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 357 | ).initComptime(.{ | |
| 331 | 358 | .{ "FILEVERSION", .file_version }, |
| 332 | 359 | .{ "PRODUCTVERSION", .product_version }, |
| 333 | 360 | .{ "FILEFLAGSMASK", .file_flags_mask }, |
| ... | ... | @@ -335,17 +362,20 @@ pub const VersionInfo = enum { |
| 335 | 362 | .{ "FILEOS", .file_os }, |
| 336 | 363 | .{ "FILETYPE", .file_type }, |
| 337 | 364 | .{ "FILESUBTYPE", .file_subtype }, |
| 338 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 365 | }); | |
| 339 | 366 | }; |
| 340 | 367 | |
| 341 | 368 | pub const VersionBlock = enum { |
| 342 | 369 | block, |
| 343 | 370 | value, |
| 344 | 371 | |
| 345 | pub const map = std.ComptimeStringMapWithEql(VersionBlock, .{ | |
| 372 | pub const map = std.StaticStringMapWithEql( | |
| 373 | VersionBlock, | |
| 374 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 375 | ).initComptime(.{ | |
| 346 | 376 | .{ "BLOCK", .block }, |
| 347 | 377 | .{ "VALUE", .value }, |
| 348 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 378 | }); | |
| 349 | 379 | }; |
| 350 | 380 | |
| 351 | 381 | /// Keywords that are be the first token in a statement and (if so) dictate how the rest |
| ... | ... | @@ -356,12 +386,15 @@ pub const TopLevelKeywords = enum { |
| 356 | 386 | characteristics, |
| 357 | 387 | stringtable, |
| 358 | 388 | |
| 359 | pub const map = std.ComptimeStringMapWithEql(TopLevelKeywords, .{ | |
| 389 | pub const map = std.StaticStringMapWithEql( | |
| 390 | TopLevelKeywords, | |
| 391 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 392 | ).initComptime(.{ | |
| 360 | 393 | .{ "LANGUAGE", .language }, |
| 361 | 394 | .{ "VERSION", .version }, |
| 362 | 395 | .{ "CHARACTERISTICS", .characteristics }, |
| 363 | 396 | .{ "STRINGTABLE", .stringtable }, |
| 364 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 397 | }); | |
| 365 | 398 | }; |
| 366 | 399 | |
| 367 | 400 | pub const CommonResourceAttributes = enum { |
| ... | ... | @@ -375,7 +408,10 @@ pub const CommonResourceAttributes = enum { |
| 375 | 408 | shared, |
| 376 | 409 | nonshared, |
| 377 | 410 | |
| 378 | pub const map = std.ComptimeStringMapWithEql(CommonResourceAttributes, .{ | |
| 411 | pub const map = std.StaticStringMapWithEql( | |
| 412 | CommonResourceAttributes, | |
| 413 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 414 | ).initComptime(.{ | |
| 379 | 415 | .{ "PRELOAD", .preload }, |
| 380 | 416 | .{ "LOADONCALL", .loadoncall }, |
| 381 | 417 | .{ "FIXED", .fixed }, |
| ... | ... | @@ -385,7 +421,7 @@ pub const CommonResourceAttributes = enum { |
| 385 | 421 | .{ "IMPURE", .impure }, |
| 386 | 422 | .{ "SHARED", .shared }, |
| 387 | 423 | .{ "NONSHARED", .nonshared }, |
| 388 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 424 | }); | |
| 389 | 425 | }; |
| 390 | 426 | |
| 391 | 427 | pub const AcceleratorTypeAndOptions = enum { |
| ... | ... | @@ -396,12 +432,15 @@ pub const AcceleratorTypeAndOptions = enum { |
| 396 | 432 | shift, |
| 397 | 433 | control, |
| 398 | 434 | |
| 399 | pub const map = std.ComptimeStringMapWithEql(AcceleratorTypeAndOptions, .{ | |
| 435 | pub const map = std.StaticStringMapWithEql( | |
| 436 | AcceleratorTypeAndOptions, | |
| 437 | std.static_string_map.eqlAsciiIgnoreCase, | |
| 438 | ).initComptime(.{ | |
| 400 | 439 | .{ "VIRTKEY", .virtkey }, |
| 401 | 440 | .{ "ASCII", .ascii }, |
| 402 | 441 | .{ "NOINVERT", .noinvert }, |
| 403 | 442 | .{ "ALT", .alt }, |
| 404 | 443 | .{ "SHIFT", .shift }, |
| 405 | 444 | .{ "CONTROL", .control }, |
| 406 | }, std.comptime_string_map.eqlAsciiIgnoreCase); | |
| 445 | }); | |
| 407 | 446 | }; |
lib/std/comptime_string_map.zig deleted-320| ... | ... | @@ -1,320 +0,0 @@ |
| 1 | const std = @import("std.zig"); | |
| 2 | const mem = std.mem; | |
| 3 | ||
| 4 | /// Comptime string map optimized for small sets of disparate string keys. | |
| 5 | /// Works by separating the keys by length at comptime and only checking strings of | |
| 6 | /// equal length at runtime. | |
| 7 | /// | |
| 8 | /// `kvs_list` expects a list of `struct { []const u8, V }` (key-value pair) tuples. | |
| 9 | /// You can pass `struct { []const u8 }` (only keys) tuples if `V` is `void`. | |
| 10 | pub fn ComptimeStringMap( | |
| 11 | comptime V: type, | |
| 12 | comptime kvs_list: anytype, | |
| 13 | ) type { | |
| 14 | return ComptimeStringMapWithEql(V, kvs_list, defaultEql); | |
| 15 | } | |
| 16 | ||
| 17 | /// Like `std.mem.eql`, but takes advantage of the fact that the lengths | |
| 18 | /// of `a` and `b` are known to be equal. | |
| 19 | pub fn defaultEql(a: []const u8, b: []const u8) bool { | |
| 20 | if (a.ptr == b.ptr) return true; | |
| 21 | for (a, b) |a_elem, b_elem| { | |
| 22 | if (a_elem != b_elem) return false; | |
| 23 | } | |
| 24 | return true; | |
| 25 | } | |
| 26 | ||
| 27 | /// Like `std.ascii.eqlIgnoreCase` but takes advantage of the fact that | |
| 28 | /// the lengths of `a` and `b` are known to be equal. | |
| 29 | pub fn eqlAsciiIgnoreCase(a: []const u8, b: []const u8) bool { | |
| 30 | if (a.ptr == b.ptr) return true; | |
| 31 | for (a, b) |a_c, b_c| { | |
| 32 | if (std.ascii.toLower(a_c) != std.ascii.toLower(b_c)) return false; | |
| 33 | } | |
| 34 | return true; | |
| 35 | } | |
| 36 | ||
| 37 | /// ComptimeStringMap, but accepts an equality function (`eql`). | |
| 38 | /// The `eql` function is only called to determine the equality | |
| 39 | /// of equal length strings. Any strings that are not equal length | |
| 40 | /// are never compared using the `eql` function. | |
| 41 | pub fn ComptimeStringMapWithEql( | |
| 42 | comptime V: type, | |
| 43 | comptime kvs_list: anytype, | |
| 44 | comptime eql: fn (a: []const u8, b: []const u8) bool, | |
| 45 | ) type { | |
| 46 | const empty_list = kvs_list.len == 0; | |
| 47 | const precomputed = blk: { | |
| 48 | @setEvalBranchQuota(1500); | |
| 49 | const KV = struct { | |
| 50 | key: []const u8, | |
| 51 | value: V, | |
| 52 | }; | |
| 53 | if (empty_list) | |
| 54 | break :blk .{}; | |
| 55 | var sorted_kvs: [kvs_list.len]KV = undefined; | |
| 56 | for (kvs_list, 0..) |kv, i| { | |
| 57 | if (V != void) { | |
| 58 | sorted_kvs[i] = .{ .key = kv.@"0", .value = kv.@"1" }; | |
| 59 | } else { | |
| 60 | sorted_kvs[i] = .{ .key = kv.@"0", .value = {} }; | |
| 61 | } | |
| 62 | } | |
| 63 | ||
| 64 | const SortContext = struct { | |
| 65 | kvs: []KV, | |
| 66 | ||
| 67 | pub fn lessThan(ctx: @This(), a: usize, b: usize) bool { | |
| 68 | return ctx.kvs[a].key.len < ctx.kvs[b].key.len; | |
| 69 | } | |
| 70 | ||
| 71 | pub fn swap(ctx: @This(), a: usize, b: usize) void { | |
| 72 | return std.mem.swap(KV, &ctx.kvs[a], &ctx.kvs[b]); | |
| 73 | } | |
| 74 | }; | |
| 75 | mem.sortUnstableContext(0, sorted_kvs.len, SortContext{ .kvs = &sorted_kvs }); | |
| 76 | ||
| 77 | const min_len = sorted_kvs[0].key.len; | |
| 78 | const max_len = sorted_kvs[sorted_kvs.len - 1].key.len; | |
| 79 | var len_indexes: [max_len + 1]usize = undefined; | |
| 80 | var len: usize = 0; | |
| 81 | var i: usize = 0; | |
| 82 | while (len <= max_len) : (len += 1) { | |
| 83 | // find the first keyword len == len | |
| 84 | while (len > sorted_kvs[i].key.len) { | |
| 85 | i += 1; | |
| 86 | } | |
| 87 | len_indexes[len] = i; | |
| 88 | } | |
| 89 | break :blk .{ | |
| 90 | .min_len = min_len, | |
| 91 | .max_len = max_len, | |
| 92 | .sorted_kvs = sorted_kvs, | |
| 93 | .len_indexes = len_indexes, | |
| 94 | }; | |
| 95 | }; | |
| 96 | ||
| 97 | return struct { | |
| 98 | /// Array of `struct { key: []const u8, value: V }` where `value` is `void{}` if `V` is `void`. | |
| 99 | /// Sorted by `key` length. | |
| 100 | pub const kvs = precomputed.sorted_kvs; | |
| 101 | ||
| 102 | /// Checks if the map has a value for the key. | |
| 103 | pub fn has(str: []const u8) bool { | |
| 104 | return get(str) != null; | |
| 105 | } | |
| 106 | ||
| 107 | /// Returns the value for the key if any, else null. | |
| 108 | pub fn get(str: []const u8) ?V { | |
| 109 | if (empty_list) | |
| 110 | return null; | |
| 111 | ||
| 112 | return precomputed.sorted_kvs[getIndex(str) orelse return null].value; | |
| 113 | } | |
| 114 | ||
| 115 | pub fn getIndex(str: []const u8) ?usize { | |
| 116 | if (empty_list) | |
| 117 | return null; | |
| 118 | ||
| 119 | if (str.len < precomputed.min_len or str.len > precomputed.max_len) | |
| 120 | return null; | |
| 121 | ||
| 122 | var i = precomputed.len_indexes[str.len]; | |
| 123 | while (true) { | |
| 124 | const kv = precomputed.sorted_kvs[i]; | |
| 125 | if (kv.key.len != str.len) | |
| 126 | return null; | |
| 127 | if (eql(kv.key, str)) | |
| 128 | return i; | |
| 129 | i += 1; | |
| 130 | if (i >= precomputed.sorted_kvs.len) | |
| 131 | return null; | |
| 132 | } | |
| 133 | } | |
| 134 | }; | |
| 135 | } | |
| 136 | ||
| 137 | const TestEnum = enum { | |
| 138 | A, | |
| 139 | B, | |
| 140 | C, | |
| 141 | D, | |
| 142 | E, | |
| 143 | }; | |
| 144 | ||
| 145 | test "list literal of list literals" { | |
| 146 | const map = ComptimeStringMap(TestEnum, .{ | |
| 147 | .{ "these", .D }, | |
| 148 | .{ "have", .A }, | |
| 149 | .{ "nothing", .B }, | |
| 150 | .{ "incommon", .C }, | |
| 151 | .{ "samelen", .E }, | |
| 152 | }); | |
| 153 | ||
| 154 | try testMap(map); | |
| 155 | ||
| 156 | // Default comparison is case sensitive | |
| 157 | try std.testing.expect(null == map.get("NOTHING")); | |
| 158 | } | |
| 159 | ||
| 160 | test "array of structs" { | |
| 161 | const KV = struct { []const u8, TestEnum }; | |
| 162 | const map = ComptimeStringMap(TestEnum, [_]KV{ | |
| 163 | .{ "these", .D }, | |
| 164 | .{ "have", .A }, | |
| 165 | .{ "nothing", .B }, | |
| 166 | .{ "incommon", .C }, | |
| 167 | .{ "samelen", .E }, | |
| 168 | }); | |
| 169 | ||
| 170 | try testMap(map); | |
| 171 | } | |
| 172 | ||
| 173 | test "slice of structs" { | |
| 174 | const KV = struct { []const u8, TestEnum }; | |
| 175 | const slice: []const KV = &[_]KV{ | |
| 176 | .{ "these", .D }, | |
| 177 | .{ "have", .A }, | |
| 178 | .{ "nothing", .B }, | |
| 179 | .{ "incommon", .C }, | |
| 180 | .{ "samelen", .E }, | |
| 181 | }; | |
| 182 | const map = ComptimeStringMap(TestEnum, slice); | |
| 183 | ||
| 184 | try testMap(map); | |
| 185 | } | |
| 186 | ||
| 187 | fn testMap(comptime map: anytype) !void { | |
| 188 | try std.testing.expectEqual(TestEnum.A, map.get("have").?); | |
| 189 | try std.testing.expectEqual(TestEnum.B, map.get("nothing").?); | |
| 190 | try std.testing.expect(null == map.get("missing")); | |
| 191 | try std.testing.expectEqual(TestEnum.D, map.get("these").?); | |
| 192 | try std.testing.expectEqual(TestEnum.E, map.get("samelen").?); | |
| 193 | ||
| 194 | try std.testing.expect(!map.has("missing")); | |
| 195 | try std.testing.expect(map.has("these")); | |
| 196 | ||
| 197 | try std.testing.expect(null == map.get("")); | |
| 198 | try std.testing.expect(null == map.get("averylongstringthathasnomatches")); | |
| 199 | } | |
| 200 | ||
| 201 | test "void value type, slice of structs" { | |
| 202 | const KV = struct { []const u8 }; | |
| 203 | const slice: []const KV = &[_]KV{ | |
| 204 | .{"these"}, | |
| 205 | .{"have"}, | |
| 206 | .{"nothing"}, | |
| 207 | .{"incommon"}, | |
| 208 | .{"samelen"}, | |
| 209 | }; | |
| 210 | const map = ComptimeStringMap(void, slice); | |
| 211 | ||
| 212 | try testSet(map); | |
| 213 | ||
| 214 | // Default comparison is case sensitive | |
| 215 | try std.testing.expect(null == map.get("NOTHING")); | |
| 216 | } | |
| 217 | ||
| 218 | test "void value type, list literal of list literals" { | |
| 219 | const map = ComptimeStringMap(void, .{ | |
| 220 | .{"these"}, | |
| 221 | .{"have"}, | |
| 222 | .{"nothing"}, | |
| 223 | .{"incommon"}, | |
| 224 | .{"samelen"}, | |
| 225 | }); | |
| 226 | ||
| 227 | try testSet(map); | |
| 228 | } | |
| 229 | ||
| 230 | fn testSet(comptime map: anytype) !void { | |
| 231 | try std.testing.expectEqual({}, map.get("have").?); | |
| 232 | try std.testing.expectEqual({}, map.get("nothing").?); | |
| 233 | try std.testing.expect(null == map.get("missing")); | |
| 234 | try std.testing.expectEqual({}, map.get("these").?); | |
| 235 | try std.testing.expectEqual({}, map.get("samelen").?); | |
| 236 | ||
| 237 | try std.testing.expect(!map.has("missing")); | |
| 238 | try std.testing.expect(map.has("these")); | |
| 239 | ||
| 240 | try std.testing.expect(null == map.get("")); | |
| 241 | try std.testing.expect(null == map.get("averylongstringthathasnomatches")); | |
| 242 | } | |
| 243 | ||
| 244 | test "ComptimeStringMapWithEql" { | |
| 245 | const map = ComptimeStringMapWithEql(TestEnum, .{ | |
| 246 | .{ "these", .D }, | |
| 247 | .{ "have", .A }, | |
| 248 | .{ "nothing", .B }, | |
| 249 | .{ "incommon", .C }, | |
| 250 | .{ "samelen", .E }, | |
| 251 | }, eqlAsciiIgnoreCase); | |
| 252 | ||
| 253 | try testMap(map); | |
| 254 | try std.testing.expectEqual(TestEnum.A, map.get("HAVE").?); | |
| 255 | try std.testing.expectEqual(TestEnum.E, map.get("SameLen").?); | |
| 256 | try std.testing.expect(null == map.get("SameLength")); | |
| 257 | ||
| 258 | try std.testing.expect(map.has("ThESe")); | |
| 259 | } | |
| 260 | ||
| 261 | test "empty" { | |
| 262 | const m1 = ComptimeStringMap(usize, .{}); | |
| 263 | try std.testing.expect(null == m1.get("anything")); | |
| 264 | ||
| 265 | const m2 = ComptimeStringMapWithEql(usize, .{}, eqlAsciiIgnoreCase); | |
| 266 | try std.testing.expect(null == m2.get("anything")); | |
| 267 | } | |
| 268 | ||
| 269 | test "redundant entries" { | |
| 270 | const map = ComptimeStringMap(TestEnum, .{ | |
| 271 | .{ "redundant", .D }, | |
| 272 | .{ "theNeedle", .A }, | |
| 273 | .{ "redundant", .B }, | |
| 274 | .{ "re" ++ "dundant", .C }, | |
| 275 | .{ "redun" ++ "dant", .E }, | |
| 276 | }); | |
| 277 | ||
| 278 | // No promises about which one you get: | |
| 279 | try std.testing.expect(null != map.get("redundant")); | |
| 280 | ||
| 281 | // Default map is not case sensitive: | |
| 282 | try std.testing.expect(null == map.get("REDUNDANT")); | |
| 283 | ||
| 284 | try std.testing.expectEqual(TestEnum.A, map.get("theNeedle").?); | |
| 285 | } | |
| 286 | ||
| 287 | test "redundant insensitive" { | |
| 288 | const map = ComptimeStringMapWithEql(TestEnum, .{ | |
| 289 | .{ "redundant", .D }, | |
| 290 | .{ "theNeedle", .A }, | |
| 291 | .{ "redundanT", .B }, | |
| 292 | .{ "RE" ++ "dundant", .C }, | |
| 293 | .{ "redun" ++ "DANT", .E }, | |
| 294 | }, eqlAsciiIgnoreCase); | |
| 295 | ||
| 296 | // No promises about which result you'll get ... | |
| 297 | try std.testing.expect(null != map.get("REDUNDANT")); | |
| 298 | try std.testing.expect(null != map.get("ReDuNdAnT")); | |
| 299 | ||
| 300 | try std.testing.expectEqual(TestEnum.A, map.get("theNeedle").?); | |
| 301 | } | |
| 302 | ||
| 303 | test "comptime-only value" { | |
| 304 | const map = std.ComptimeStringMap(type, .{ | |
| 305 | .{ "a", struct { | |
| 306 | pub const foo = 1; | |
| 307 | } }, | |
| 308 | .{ "b", struct { | |
| 309 | pub const foo = 2; | |
| 310 | } }, | |
| 311 | .{ "c", struct { | |
| 312 | pub const foo = 3; | |
| 313 | } }, | |
| 314 | }); | |
| 315 | ||
| 316 | try std.testing.expect(map.get("a").?.foo == 1); | |
| 317 | try std.testing.expect(map.get("b").?.foo == 2); | |
| 318 | try std.testing.expect(map.get("c").?.foo == 3); | |
| 319 | try std.testing.expect(map.get("d") == null); | |
| 320 | } |
lib/std/crypto/Certificate.zig+5-5| ... | ... | @@ -19,7 +19,7 @@ pub const Algorithm = enum { |
| 19 | 19 | md5WithRSAEncryption, |
| 20 | 20 | curveEd25519, |
| 21 | 21 | |
| 22 | pub const map = std.ComptimeStringMap(Algorithm, .{ | |
| 22 | pub const map = std.StaticStringMap(Algorithm).initComptime(.{ | |
| 23 | 23 | .{ &[_]u8{ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05 }, .sha1WithRSAEncryption }, |
| 24 | 24 | .{ &[_]u8{ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B }, .sha256WithRSAEncryption }, |
| 25 | 25 | .{ &[_]u8{ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C }, .sha384WithRSAEncryption }, |
| ... | ... | @@ -52,7 +52,7 @@ pub const AlgorithmCategory = enum { |
| 52 | 52 | X9_62_id_ecPublicKey, |
| 53 | 53 | curveEd25519, |
| 54 | 54 | |
| 55 | pub const map = std.ComptimeStringMap(AlgorithmCategory, .{ | |
| 55 | pub const map = std.StaticStringMap(AlgorithmCategory).initComptime(.{ | |
| 56 | 56 | .{ &[_]u8{ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }, .rsaEncryption }, |
| 57 | 57 | .{ &[_]u8{ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01 }, .X9_62_id_ecPublicKey }, |
| 58 | 58 | .{ &[_]u8{ 0x2B, 0x65, 0x70 }, .curveEd25519 }, |
| ... | ... | @@ -73,7 +73,7 @@ pub const Attribute = enum { |
| 73 | 73 | pkcs9_emailAddress, |
| 74 | 74 | domainComponent, |
| 75 | 75 | |
| 76 | pub const map = std.ComptimeStringMap(Attribute, .{ | |
| 76 | pub const map = std.StaticStringMap(Attribute).initComptime(.{ | |
| 77 | 77 | .{ &[_]u8{ 0x55, 0x04, 0x03 }, .commonName }, |
| 78 | 78 | .{ &[_]u8{ 0x55, 0x04, 0x05 }, .serialNumber }, |
| 79 | 79 | .{ &[_]u8{ 0x55, 0x04, 0x06 }, .countryName }, |
| ... | ... | @@ -94,7 +94,7 @@ pub const NamedCurve = enum { |
| 94 | 94 | secp521r1, |
| 95 | 95 | X9_62_prime256v1, |
| 96 | 96 | |
| 97 | pub const map = std.ComptimeStringMap(NamedCurve, .{ | |
| 97 | pub const map = std.StaticStringMap(NamedCurve).initComptime(.{ | |
| 98 | 98 | .{ &[_]u8{ 0x2B, 0x81, 0x04, 0x00, 0x22 }, .secp384r1 }, |
| 99 | 99 | .{ &[_]u8{ 0x2B, 0x81, 0x04, 0x00, 0x23 }, .secp521r1 }, |
| 100 | 100 | .{ &[_]u8{ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 }, .X9_62_prime256v1 }, |
| ... | ... | @@ -130,7 +130,7 @@ pub const ExtensionId = enum { |
| 130 | 130 | netscape_cert_type, |
| 131 | 131 | netscape_comment, |
| 132 | 132 | |
| 133 | pub const map = std.ComptimeStringMap(ExtensionId, .{ | |
| 133 | pub const map = std.StaticStringMap(ExtensionId).initComptime(.{ | |
| 134 | 134 | .{ &[_]u8{ 0x55, 0x04, 0x03 }, .commonName }, |
| 135 | 135 | .{ &[_]u8{ 0x55, 0x1D, 0x01 }, .authority_key_identifier }, |
| 136 | 136 | .{ &[_]u8{ 0x55, 0x1D, 0x07 }, .subject_alt_name }, |
lib/std/fs/test.zig+4-4| ... | ... | @@ -1641,7 +1641,7 @@ test "walker" { |
| 1641 | 1641 | |
| 1642 | 1642 | // iteration order of walker is undefined, so need lookup maps to check against |
| 1643 | 1643 | |
| 1644 | const expected_paths = std.ComptimeStringMap(void, .{ | |
| 1644 | const expected_paths = std.StaticStringMap(void).initComptime(.{ | |
| 1645 | 1645 | .{"dir1"}, |
| 1646 | 1646 | .{"dir2"}, |
| 1647 | 1647 | .{"dir3"}, |
| ... | ... | @@ -1651,7 +1651,7 @@ test "walker" { |
| 1651 | 1651 | .{"dir3" ++ fs.path.sep_str ++ "sub2" ++ fs.path.sep_str ++ "subsub1"}, |
| 1652 | 1652 | }); |
| 1653 | 1653 | |
| 1654 | const expected_basenames = std.ComptimeStringMap(void, .{ | |
| 1654 | const expected_basenames = std.StaticStringMap(void).initComptime(.{ | |
| 1655 | 1655 | .{"dir1"}, |
| 1656 | 1656 | .{"dir2"}, |
| 1657 | 1657 | .{"dir3"}, |
| ... | ... | @@ -1661,8 +1661,8 @@ test "walker" { |
| 1661 | 1661 | .{"subsub1"}, |
| 1662 | 1662 | }); |
| 1663 | 1663 | |
| 1664 | for (expected_paths.kvs) |kv| { | |
| 1665 | try tmp.dir.makePath(kv.key); | |
| 1664 | for (expected_paths.keys()) |key| { | |
| 1665 | try tmp.dir.makePath(key); | |
| 1666 | 1666 | } |
| 1667 | 1667 | |
| 1668 | 1668 | var walker = try tmp.dir.walk(testing.allocator); |
lib/std/http/Client.zig+1-1| ... | ... | @@ -1570,7 +1570,7 @@ pub const RequestOptions = struct { |
| 1570 | 1570 | }; |
| 1571 | 1571 | |
| 1572 | 1572 | fn validateUri(uri: Uri, arena: Allocator) !struct { Connection.Protocol, Uri } { |
| 1573 | const protocol_map = std.ComptimeStringMap(Connection.Protocol, .{ | |
| 1573 | const protocol_map = std.StaticStringMap(Connection.Protocol).initComptime(.{ | |
| 1574 | 1574 | .{ "http", .plain }, |
| 1575 | 1575 | .{ "ws", .plain }, |
| 1576 | 1576 | .{ "https", .tls }, |
lib/std/meta.zig+2-2| ... | ... | @@ -19,7 +19,7 @@ pub const isTag = @compileError("deprecated; use 'tagged_value == @field(E, tag_ |
| 19 | 19 | |
| 20 | 20 | /// Returns the variant of an enum type, `T`, which is named `str`, or `null` if no such variant exists. |
| 21 | 21 | pub fn stringToEnum(comptime T: type, str: []const u8) ?T { |
| 22 | // Using ComptimeStringMap here is more performant, but it will start to take too | |
| 22 | // Using StaticStringMap here is more performant, but it will start to take too | |
| 23 | 23 | // long to compile if the enum is large enough, due to the current limits of comptime |
| 24 | 24 | // performance when doing things like constructing lookup maps at comptime. |
| 25 | 25 | // TODO The '100' here is arbitrary and should be increased when possible: |
| ... | ... | @@ -34,7 +34,7 @@ pub fn stringToEnum(comptime T: type, str: []const u8) ?T { |
| 34 | 34 | } |
| 35 | 35 | break :build_kvs kvs_array[0..]; |
| 36 | 36 | }; |
| 37 | const map = std.ComptimeStringMap(T, kvs); | |
| 37 | const map = std.StaticStringMap(T).initComptime(kvs); | |
| 38 | 38 | return map.get(str); |
| 39 | 39 | } else { |
| 40 | 40 | inline for (@typeInfo(T).Enum.fields) |enumField| { |
lib/std/static_string_map.zig created+502| ... | ... | @@ -0,0 +1,502 @@ |
| 1 | const std = @import("std.zig"); | |
| 2 | const mem = std.mem; | |
| 3 | ||
| 4 | /// Static string map optimized for small sets of disparate string keys. | |
| 5 | /// Works by separating the keys by length at initialization and only checking | |
| 6 | /// strings of equal length at runtime. | |
| 7 | pub fn StaticStringMap(comptime V: type) type { | |
| 8 | return StaticStringMapWithEql(V, defaultEql); | |
| 9 | } | |
| 10 | ||
| 11 | /// Like `std.mem.eql`, but takes advantage of the fact that the lengths | |
| 12 | /// of `a` and `b` are known to be equal. | |
| 13 | pub fn defaultEql(a: []const u8, b: []const u8) bool { | |
| 14 | if (a.ptr == b.ptr) return true; | |
| 15 | for (a, b) |a_elem, b_elem| { | |
| 16 | if (a_elem != b_elem) return false; | |
| 17 | } | |
| 18 | return true; | |
| 19 | } | |
| 20 | ||
| 21 | /// Like `std.ascii.eqlIgnoreCase` but takes advantage of the fact that | |
| 22 | /// the lengths of `a` and `b` are known to be equal. | |
| 23 | pub fn eqlAsciiIgnoreCase(a: []const u8, b: []const u8) bool { | |
| 24 | if (a.ptr == b.ptr) return true; | |
| 25 | for (a, b) |a_c, b_c| { | |
| 26 | if (std.ascii.toLower(a_c) != std.ascii.toLower(b_c)) return false; | |
| 27 | } | |
| 28 | return true; | |
| 29 | } | |
| 30 | ||
| 31 | /// StaticStringMap, but accepts an equality function (`eql`). | |
| 32 | /// The `eql` function is only called to determine the equality | |
| 33 | /// of equal length strings. Any strings that are not equal length | |
| 34 | /// are never compared using the `eql` function. | |
| 35 | pub fn StaticStringMapWithEql( | |
| 36 | comptime V: type, | |
| 37 | comptime eql: fn (a: []const u8, b: []const u8) bool, | |
| 38 | ) type { | |
| 39 | return struct { | |
| 40 | kvs: *const KVs = &empty_kvs, | |
| 41 | len_indexes: [*]const u32 = &empty_len_indexes, | |
| 42 | len_indexes_len: u32 = 0, | |
| 43 | min_len: u32 = std.math.maxInt(u32), | |
| 44 | max_len: u32 = 0, | |
| 45 | ||
| 46 | pub const KV = struct { | |
| 47 | key: []const u8, | |
| 48 | value: V, | |
| 49 | }; | |
| 50 | ||
| 51 | const Self = @This(); | |
| 52 | const KVs = struct { | |
| 53 | keys: [*]const []const u8, | |
| 54 | values: [*]const V, | |
| 55 | len: u32, | |
| 56 | }; | |
| 57 | const empty_kvs = KVs{ | |
| 58 | .keys = &empty_keys, | |
| 59 | .values = &empty_vals, | |
| 60 | .len = 0, | |
| 61 | }; | |
| 62 | const empty_len_indexes = [0]u32{}; | |
| 63 | const empty_keys = [0][]const u8{}; | |
| 64 | const empty_vals = [0]V{}; | |
| 65 | ||
| 66 | /// Returns a map backed by static, comptime allocated memory. | |
| 67 | /// | |
| 68 | /// `kvs_list` must be either a list of `struct { []const u8, V }` | |
| 69 | /// (key-value pair) tuples, or a list of `struct { []const u8 }` | |
| 70 | /// (only keys) tuples if `V` is `void`. | |
| 71 | pub inline fn initComptime(comptime kvs_list: anytype) Self { | |
| 72 | comptime { | |
| 73 | @setEvalBranchQuota(30 * kvs_list.len); | |
| 74 | var self = Self{}; | |
| 75 | if (kvs_list.len == 0) | |
| 76 | return self; | |
| 77 | ||
| 78 | var sorted_keys: [kvs_list.len][]const u8 = undefined; | |
| 79 | var sorted_vals: [kvs_list.len]V = undefined; | |
| 80 | ||
| 81 | self.initSortedKVs(kvs_list, &sorted_keys, &sorted_vals); | |
| 82 | const final_keys = sorted_keys; | |
| 83 | const final_vals = sorted_vals; | |
| 84 | self.kvs = &.{ | |
| 85 | .keys = &final_keys, | |
| 86 | .values = &final_vals, | |
| 87 | .len = @intCast(kvs_list.len), | |
| 88 | }; | |
| 89 | ||
| 90 | var len_indexes: [self.max_len + 1]u32 = undefined; | |
| 91 | self.initLenIndexes(&len_indexes); | |
| 92 | const final_len_indexes = len_indexes; | |
| 93 | self.len_indexes = &final_len_indexes; | |
| 94 | self.len_indexes_len = @intCast(len_indexes.len); | |
| 95 | return self; | |
| 96 | } | |
| 97 | } | |
| 98 | ||
| 99 | /// Returns a map backed by memory allocated with `allocator`. | |
| 100 | /// | |
| 101 | /// Handles `kvs_list` the same way as `initComptime()`. | |
| 102 | pub fn init(kvs_list: anytype, allocator: mem.Allocator) !Self { | |
| 103 | var self = Self{}; | |
| 104 | if (kvs_list.len == 0) | |
| 105 | return self; | |
| 106 | ||
| 107 | const sorted_keys = try allocator.alloc([]const u8, kvs_list.len); | |
| 108 | errdefer allocator.free(sorted_keys); | |
| 109 | const sorted_vals = try allocator.alloc(V, kvs_list.len); | |
| 110 | errdefer allocator.free(sorted_vals); | |
| 111 | const kvs = try allocator.create(KVs); | |
| 112 | errdefer allocator.destroy(kvs); | |
| 113 | ||
| 114 | self.initSortedKVs(kvs_list, sorted_keys, sorted_vals); | |
| 115 | kvs.* = .{ | |
| 116 | .keys = sorted_keys.ptr, | |
| 117 | .values = sorted_vals.ptr, | |
| 118 | .len = kvs_list.len, | |
| 119 | }; | |
| 120 | self.kvs = kvs; | |
| 121 | ||
| 122 | const len_indexes = try allocator.alloc(u32, self.max_len + 1); | |
| 123 | self.initLenIndexes(len_indexes); | |
| 124 | self.len_indexes = len_indexes.ptr; | |
| 125 | self.len_indexes_len = @intCast(len_indexes.len); | |
| 126 | return self; | |
| 127 | } | |
| 128 | ||
| 129 | /// this method should only be used with init() and not with initComptime(). | |
| 130 | pub fn deinit(self: Self, allocator: mem.Allocator) void { | |
| 131 | allocator.free(self.len_indexes[0..self.len_indexes_len]); | |
| 132 | allocator.free(self.kvs.keys[0..self.kvs.len]); | |
| 133 | allocator.free(self.kvs.values[0..self.kvs.len]); | |
| 134 | allocator.destroy(self.kvs); | |
| 135 | } | |
| 136 | ||
| 137 | const SortContext = struct { | |
| 138 | keys: [][]const u8, | |
| 139 | vals: []V, | |
| 140 | ||
| 141 | pub fn lessThan(ctx: @This(), a: usize, b: usize) bool { | |
| 142 | return ctx.keys[a].len < ctx.keys[b].len; | |
| 143 | } | |
| 144 | ||
| 145 | pub fn swap(ctx: @This(), a: usize, b: usize) void { | |
| 146 | std.mem.swap([]const u8, &ctx.keys[a], &ctx.keys[b]); | |
| 147 | std.mem.swap(V, &ctx.vals[a], &ctx.vals[b]); | |
| 148 | } | |
| 149 | }; | |
| 150 | ||
| 151 | fn initSortedKVs( | |
| 152 | self: *Self, | |
| 153 | kvs_list: anytype, | |
| 154 | sorted_keys: [][]const u8, | |
| 155 | sorted_vals: []V, | |
| 156 | ) void { | |
| 157 | for (kvs_list, 0..) |kv, i| { | |
| 158 | sorted_keys[i] = kv.@"0"; | |
| 159 | sorted_vals[i] = if (V == void) {} else kv.@"1"; | |
| 160 | self.min_len = @intCast(@min(self.min_len, kv.@"0".len)); | |
| 161 | self.max_len = @intCast(@max(self.max_len, kv.@"0".len)); | |
| 162 | } | |
| 163 | mem.sortUnstableContext(0, sorted_keys.len, SortContext{ | |
| 164 | .keys = sorted_keys, | |
| 165 | .vals = sorted_vals, | |
| 166 | }); | |
| 167 | } | |
| 168 | ||
| 169 | fn initLenIndexes(self: Self, len_indexes: []u32) void { | |
| 170 | var len: usize = 0; | |
| 171 | var i: u32 = 0; | |
| 172 | while (len <= self.max_len) : (len += 1) { | |
| 173 | // find the first keyword len == len | |
| 174 | while (len > self.kvs.keys[i].len) { | |
| 175 | i += 1; | |
| 176 | } | |
| 177 | len_indexes[len] = i; | |
| 178 | } | |
| 179 | } | |
| 180 | ||
| 181 | /// Checks if the map has a value for the key. | |
| 182 | pub fn has(self: Self, str: []const u8) bool { | |
| 183 | return self.get(str) != null; | |
| 184 | } | |
| 185 | ||
| 186 | /// Returns the value for the key if any, else null. | |
| 187 | pub fn get(self: Self, str: []const u8) ?V { | |
| 188 | if (self.kvs.len == 0) | |
| 189 | return null; | |
| 190 | ||
| 191 | return self.kvs.values[self.getIndex(str) orelse return null]; | |
| 192 | } | |
| 193 | ||
| 194 | pub fn getIndex(self: Self, str: []const u8) ?usize { | |
| 195 | const kvs = self.kvs.*; | |
| 196 | if (kvs.len == 0) | |
| 197 | return null; | |
| 198 | ||
| 199 | if (str.len < self.min_len or str.len > self.max_len) | |
| 200 | return null; | |
| 201 | ||
| 202 | var i = self.len_indexes[str.len]; | |
| 203 | while (true) { | |
| 204 | const key = kvs.keys[i]; | |
| 205 | if (key.len != str.len) | |
| 206 | return null; | |
| 207 | if (eql(key, str)) | |
| 208 | return i; | |
| 209 | i += 1; | |
| 210 | if (i >= kvs.len) | |
| 211 | return null; | |
| 212 | } | |
| 213 | } | |
| 214 | ||
| 215 | /// Returns the longest key, value pair where key is a prefix of `str` | |
| 216 | /// else null. | |
| 217 | pub fn getLongestPrefix(self: Self, str: []const u8) ?KV { | |
| 218 | if (self.kvs.len == 0) | |
| 219 | return null; | |
| 220 | const i = self.getLongestPrefixIndex(str) orelse return null; | |
| 221 | const kvs = self.kvs.*; | |
| 222 | return .{ | |
| 223 | .key = kvs.keys[i], | |
| 224 | .value = kvs.values[i], | |
| 225 | }; | |
| 226 | } | |
| 227 | ||
| 228 | pub fn getLongestPrefixIndex(self: Self, str: []const u8) ?usize { | |
| 229 | if (self.kvs.len == 0) | |
| 230 | return null; | |
| 231 | ||
| 232 | if (str.len < self.min_len) | |
| 233 | return null; | |
| 234 | ||
| 235 | var len = @min(self.max_len, str.len); | |
| 236 | while (len >= self.min_len) : (len -= 1) { | |
| 237 | if (self.getIndex(str[0..len])) |i| | |
| 238 | return i; | |
| 239 | } | |
| 240 | return null; | |
| 241 | } | |
| 242 | ||
| 243 | pub fn keys(self: Self) []const []const u8 { | |
| 244 | const kvs = self.kvs.*; | |
| 245 | return kvs.keys[0..kvs.len]; | |
| 246 | } | |
| 247 | ||
| 248 | pub fn values(self: Self) []const V { | |
| 249 | const kvs = self.kvs.*; | |
| 250 | return kvs.values[0..kvs.len]; | |
| 251 | } | |
| 252 | }; | |
| 253 | } | |
| 254 | ||
| 255 | const TestEnum = enum { A, B, C, D, E }; | |
| 256 | const TestMap = StaticStringMap(TestEnum); | |
| 257 | const TestKV = struct { []const u8, TestEnum }; | |
| 258 | const TestMapVoid = StaticStringMap(void); | |
| 259 | const TestKVVoid = struct { []const u8 }; | |
| 260 | const TestMapWithEql = StaticStringMapWithEql(TestEnum, eqlAsciiIgnoreCase); | |
| 261 | const testing = std.testing; | |
| 262 | const test_alloc = testing.allocator; | |
| 263 | ||
| 264 | test "list literal of list literals" { | |
| 265 | const slice = [_]TestKV{ | |
| 266 | .{ "these", .D }, | |
| 267 | .{ "have", .A }, | |
| 268 | .{ "nothing", .B }, | |
| 269 | .{ "incommon", .C }, | |
| 270 | .{ "samelen", .E }, | |
| 271 | }; | |
| 272 | const map = TestMap.initComptime(slice); | |
| 273 | try testMap(map); | |
| 274 | // Default comparison is case sensitive | |
| 275 | try testing.expect(null == map.get("NOTHING")); | |
| 276 | ||
| 277 | // runtime init(), deinit() | |
| 278 | const map_rt = try TestMap.init(slice, test_alloc); | |
| 279 | defer map_rt.deinit(test_alloc); | |
| 280 | try testMap(map_rt); | |
| 281 | // Default comparison is case sensitive | |
| 282 | try testing.expect(null == map_rt.get("NOTHING")); | |
| 283 | } | |
| 284 | ||
| 285 | test "array of structs" { | |
| 286 | const slice = [_]TestKV{ | |
| 287 | .{ "these", .D }, | |
| 288 | .{ "have", .A }, | |
| 289 | .{ "nothing", .B }, | |
| 290 | .{ "incommon", .C }, | |
| 291 | .{ "samelen", .E }, | |
| 292 | }; | |
| 293 | ||
| 294 | try testMap(TestMap.initComptime(slice)); | |
| 295 | } | |
| 296 | ||
| 297 | test "slice of structs" { | |
| 298 | const slice = [_]TestKV{ | |
| 299 | .{ "these", .D }, | |
| 300 | .{ "have", .A }, | |
| 301 | .{ "nothing", .B }, | |
| 302 | .{ "incommon", .C }, | |
| 303 | .{ "samelen", .E }, | |
| 304 | }; | |
| 305 | ||
| 306 | try testMap(TestMap.initComptime(slice)); | |
| 307 | } | |
| 308 | ||
| 309 | fn testMap(map: anytype) !void { | |
| 310 | try testing.expectEqual(TestEnum.A, map.get("have").?); | |
| 311 | try testing.expectEqual(TestEnum.B, map.get("nothing").?); | |
| 312 | try testing.expect(null == map.get("missing")); | |
| 313 | try testing.expectEqual(TestEnum.D, map.get("these").?); | |
| 314 | try testing.expectEqual(TestEnum.E, map.get("samelen").?); | |
| 315 | ||
| 316 | try testing.expect(!map.has("missing")); | |
| 317 | try testing.expect(map.has("these")); | |
| 318 | ||
| 319 | try testing.expect(null == map.get("")); | |
| 320 | try testing.expect(null == map.get("averylongstringthathasnomatches")); | |
| 321 | } | |
| 322 | ||
| 323 | test "void value type, slice of structs" { | |
| 324 | const slice = [_]TestKVVoid{ | |
| 325 | .{"these"}, | |
| 326 | .{"have"}, | |
| 327 | .{"nothing"}, | |
| 328 | .{"incommon"}, | |
| 329 | .{"samelen"}, | |
| 330 | }; | |
| 331 | const map = TestMapVoid.initComptime(slice); | |
| 332 | try testSet(map); | |
| 333 | // Default comparison is case sensitive | |
| 334 | try testing.expect(null == map.get("NOTHING")); | |
| 335 | } | |
| 336 | ||
| 337 | test "void value type, list literal of list literals" { | |
| 338 | const slice = [_]TestKVVoid{ | |
| 339 | .{"these"}, | |
| 340 | .{"have"}, | |
| 341 | .{"nothing"}, | |
| 342 | .{"incommon"}, | |
| 343 | .{"samelen"}, | |
| 344 | }; | |
| 345 | ||
| 346 | try testSet(TestMapVoid.initComptime(slice)); | |
| 347 | } | |
| 348 | ||
| 349 | fn testSet(map: TestMapVoid) !void { | |
| 350 | try testing.expectEqual({}, map.get("have").?); | |
| 351 | try testing.expectEqual({}, map.get("nothing").?); | |
| 352 | try testing.expect(null == map.get("missing")); | |
| 353 | try testing.expectEqual({}, map.get("these").?); | |
| 354 | try testing.expectEqual({}, map.get("samelen").?); | |
| 355 | ||
| 356 | try testing.expect(!map.has("missing")); | |
| 357 | try testing.expect(map.has("these")); | |
| 358 | ||
| 359 | try testing.expect(null == map.get("")); | |
| 360 | try testing.expect(null == map.get("averylongstringthathasnomatches")); | |
| 361 | } | |
| 362 | ||
| 363 | fn testStaticStringMapWithEql(map: TestMapWithEql) !void { | |
| 364 | try testMap(map); | |
| 365 | try testing.expectEqual(TestEnum.A, map.get("HAVE").?); | |
| 366 | try testing.expectEqual(TestEnum.E, map.get("SameLen").?); | |
| 367 | try testing.expect(null == map.get("SameLength")); | |
| 368 | try testing.expect(map.has("ThESe")); | |
| 369 | } | |
| 370 | ||
| 371 | test "StaticStringMapWithEql" { | |
| 372 | const slice = [_]TestKV{ | |
| 373 | .{ "these", .D }, | |
| 374 | .{ "have", .A }, | |
| 375 | .{ "nothing", .B }, | |
| 376 | .{ "incommon", .C }, | |
| 377 | .{ "samelen", .E }, | |
| 378 | }; | |
| 379 | ||
| 380 | try testStaticStringMapWithEql(TestMapWithEql.initComptime(slice)); | |
| 381 | } | |
| 382 | ||
| 383 | test "empty" { | |
| 384 | const m1 = StaticStringMap(usize).initComptime(.{}); | |
| 385 | try testing.expect(null == m1.get("anything")); | |
| 386 | ||
| 387 | const m2 = StaticStringMapWithEql(usize, eqlAsciiIgnoreCase).initComptime(.{}); | |
| 388 | try testing.expect(null == m2.get("anything")); | |
| 389 | ||
| 390 | const m3 = try StaticStringMap(usize).init(.{}, test_alloc); | |
| 391 | try testing.expect(null == m3.get("anything")); | |
| 392 | ||
| 393 | const m4 = try StaticStringMapWithEql(usize, eqlAsciiIgnoreCase).init(.{}, test_alloc); | |
| 394 | try testing.expect(null == m4.get("anything")); | |
| 395 | } | |
| 396 | ||
| 397 | test "redundant entries" { | |
| 398 | const slice = [_]TestKV{ | |
| 399 | .{ "redundant", .D }, | |
| 400 | .{ "theNeedle", .A }, | |
| 401 | .{ "redundant", .B }, | |
| 402 | .{ "re" ++ "dundant", .C }, | |
| 403 | .{ "redun" ++ "dant", .E }, | |
| 404 | }; | |
| 405 | const map = TestMap.initComptime(slice); | |
| 406 | ||
| 407 | // No promises about which one you get: | |
| 408 | try testing.expect(null != map.get("redundant")); | |
| 409 | ||
| 410 | // Default map is not case sensitive: | |
| 411 | try testing.expect(null == map.get("REDUNDANT")); | |
| 412 | ||
| 413 | try testing.expectEqual(TestEnum.A, map.get("theNeedle").?); | |
| 414 | } | |
| 415 | ||
| 416 | test "redundant insensitive" { | |
| 417 | const slice = [_]TestKV{ | |
| 418 | .{ "redundant", .D }, | |
| 419 | .{ "theNeedle", .A }, | |
| 420 | .{ "redundanT", .B }, | |
| 421 | .{ "RE" ++ "dundant", .C }, | |
| 422 | .{ "redun" ++ "DANT", .E }, | |
| 423 | }; | |
| 424 | ||
| 425 | const map = TestMapWithEql.initComptime(slice); | |
| 426 | ||
| 427 | // No promises about which result you'll get ... | |
| 428 | try testing.expect(null != map.get("REDUNDANT")); | |
| 429 | try testing.expect(null != map.get("ReDuNdAnT")); | |
| 430 | try testing.expectEqual(TestEnum.A, map.get("theNeedle").?); | |
| 431 | } | |
| 432 | ||
| 433 | test "comptime-only value" { | |
| 434 | const map = StaticStringMap(type).initComptime(.{ | |
| 435 | .{ "a", struct { | |
| 436 | pub const foo = 1; | |
| 437 | } }, | |
| 438 | .{ "b", struct { | |
| 439 | pub const foo = 2; | |
| 440 | } }, | |
| 441 | .{ "c", struct { | |
| 442 | pub const foo = 3; | |
| 443 | } }, | |
| 444 | }); | |
| 445 | ||
| 446 | try testing.expect(map.get("a").?.foo == 1); | |
| 447 | try testing.expect(map.get("b").?.foo == 2); | |
| 448 | try testing.expect(map.get("c").?.foo == 3); | |
| 449 | try testing.expect(map.get("d") == null); | |
| 450 | } | |
| 451 | ||
| 452 | test "getLongestPrefix" { | |
| 453 | const slice = [_]TestKV{ | |
| 454 | .{ "a", .A }, | |
| 455 | .{ "aa", .B }, | |
| 456 | .{ "aaa", .C }, | |
| 457 | .{ "aaaa", .D }, | |
| 458 | }; | |
| 459 | ||
| 460 | const map = TestMap.initComptime(slice); | |
| 461 | ||
| 462 | try testing.expectEqual(null, map.getLongestPrefix("")); | |
| 463 | try testing.expectEqual(null, map.getLongestPrefix("bar")); | |
| 464 | try testing.expectEqualStrings("aaaa", map.getLongestPrefix("aaaabar").?.key); | |
| 465 | try testing.expectEqualStrings("aaa", map.getLongestPrefix("aaabar").?.key); | |
| 466 | } | |
| 467 | ||
| 468 | test "getLongestPrefix2" { | |
| 469 | const slice = [_]struct { []const u8, u8 }{ | |
| 470 | .{ "one", 1 }, | |
| 471 | .{ "two", 2 }, | |
| 472 | .{ "three", 3 }, | |
| 473 | .{ "four", 4 }, | |
| 474 | .{ "five", 5 }, | |
| 475 | .{ "six", 6 }, | |
| 476 | .{ "seven", 7 }, | |
| 477 | .{ "eight", 8 }, | |
| 478 | .{ "nine", 9 }, | |
| 479 | }; | |
| 480 | const map = StaticStringMap(u8).initComptime(slice); | |
| 481 | ||
| 482 | try testing.expectEqual(1, map.get("one")); | |
| 483 | try testing.expectEqual(null, map.get("o")); | |
| 484 | try testing.expectEqual(null, map.get("onexxx")); | |
| 485 | try testing.expectEqual(9, map.get("nine")); | |
| 486 | try testing.expectEqual(null, map.get("n")); | |
| 487 | try testing.expectEqual(null, map.get("ninexxx")); | |
| 488 | try testing.expectEqual(null, map.get("xxx")); | |
| 489 | ||
| 490 | try testing.expectEqual(1, map.getLongestPrefix("one").?.value); | |
| 491 | try testing.expectEqual(1, map.getLongestPrefix("onexxx").?.value); | |
| 492 | try testing.expectEqual(null, map.getLongestPrefix("o")); | |
| 493 | try testing.expectEqual(null, map.getLongestPrefix("on")); | |
| 494 | try testing.expectEqual(9, map.getLongestPrefix("nine").?.value); | |
| 495 | try testing.expectEqual(9, map.getLongestPrefix("ninexxx").?.value); | |
| 496 | try testing.expectEqual(null, map.getLongestPrefix("n")); | |
| 497 | try testing.expectEqual(null, map.getLongestPrefix("xxx")); | |
| 498 | } | |
| 499 | ||
| 500 | test "long kvs_list doesn't exceed @setEvalBranchQuota" { | |
| 501 | _ = TestMapVoid.initComptime([1]TestKVVoid{.{"x"}} ** 1_000); | |
| 502 | } |
lib/std/std.zig+3-3| ... | ... | @@ -16,8 +16,8 @@ pub const BufMap = @import("buf_map.zig").BufMap; |
| 16 | 16 | pub const BufSet = @import("buf_set.zig").BufSet; |
| 17 | 17 | /// Deprecated: use `process.Child`. |
| 18 | 18 | pub const ChildProcess = @import("child_process.zig").ChildProcess; |
| 19 | pub const ComptimeStringMap = comptime_string_map.ComptimeStringMap; | |
| 20 | pub const ComptimeStringMapWithEql = comptime_string_map.ComptimeStringMapWithEql; | |
| 19 | pub const StaticStringMap = static_string_map.StaticStringMap; | |
| 20 | pub const StaticStringMapWithEql = static_string_map.StaticStringMapWithEql; | |
| 21 | 21 | pub const DoublyLinkedList = @import("linked_list.zig").DoublyLinkedList; |
| 22 | 22 | pub const DynLib = @import("dynamic_library.zig").DynLib; |
| 23 | 23 | pub const DynamicBitSet = bit_set.DynamicBitSet; |
| ... | ... | @@ -62,7 +62,7 @@ pub const builtin = @import("builtin.zig"); |
| 62 | 62 | pub const c = @import("c.zig"); |
| 63 | 63 | pub const coff = @import("coff.zig"); |
| 64 | 64 | pub const compress = @import("compress.zig"); |
| 65 | pub const comptime_string_map = @import("comptime_string_map.zig"); | |
| 65 | pub const static_string_map = @import("static_string_map.zig"); | |
| 66 | 66 | pub const crypto = @import("crypto.zig"); |
| 67 | 67 | pub const debug = @import("debug.zig"); |
| 68 | 68 | pub const dwarf = @import("dwarf.zig"); |
lib/std/zig/AstGen.zig+7-7| ... | ... | @@ -10125,7 +10125,7 @@ fn calleeExpr( |
| 10125 | 10125 | } |
| 10126 | 10126 | } |
| 10127 | 10127 | |
| 10128 | const primitive_instrs = std.ComptimeStringMap(Zir.Inst.Ref, .{ | |
| 10128 | const primitive_instrs = std.StaticStringMap(Zir.Inst.Ref).initComptime(.{ | |
| 10129 | 10129 | .{ "anyerror", .anyerror_type }, |
| 10130 | 10130 | .{ "anyframe", .anyframe_type }, |
| 10131 | 10131 | .{ "anyopaque", .anyopaque_type }, |
| ... | ... | @@ -10173,14 +10173,14 @@ const primitive_instrs = std.ComptimeStringMap(Zir.Inst.Ref, .{ |
| 10173 | 10173 | comptime { |
| 10174 | 10174 | // These checks ensure that std.zig.primitives stays in sync with the primitive->Zir map. |
| 10175 | 10175 | const primitives = std.zig.primitives; |
| 10176 | for (primitive_instrs.kvs) |kv| { | |
| 10177 | if (!primitives.isPrimitive(kv.key)) { | |
| 10178 | @compileError("std.zig.isPrimitive() is not aware of Zir instr '" ++ @tagName(kv.value) ++ "'"); | |
| 10176 | for (primitive_instrs.keys(), primitive_instrs.values()) |key, value| { | |
| 10177 | if (!primitives.isPrimitive(key)) { | |
| 10178 | @compileError("std.zig.isPrimitive() is not aware of Zir instr '" ++ @tagName(value) ++ "'"); | |
| 10179 | 10179 | } |
| 10180 | 10180 | } |
| 10181 | for (primitives.names.kvs) |kv| { | |
| 10182 | if (primitive_instrs.get(kv.key) == null) { | |
| 10183 | @compileError("std.zig.primitives entry '" ++ kv.key ++ "' does not have a corresponding Zir instr"); | |
| 10181 | for (primitives.names.keys()) |key| { | |
| 10182 | if (primitive_instrs.get(key) == null) { | |
| 10183 | @compileError("std.zig.primitives entry '" ++ key ++ "' does not have a corresponding Zir instr"); | |
| 10184 | 10184 | } |
| 10185 | 10185 | } |
| 10186 | 10186 | } |
lib/std/zig/BuiltinFn.zig+1-1| ... | ... | @@ -160,7 +160,7 @@ param_count: ?u8, |
| 160 | 160 | |
| 161 | 161 | pub const list = list: { |
| 162 | 162 | @setEvalBranchQuota(3000); |
| 163 | break :list std.ComptimeStringMap(@This(), .{ | |
| 163 | break :list std.StaticStringMap(@This()).initComptime(.{ | |
| 164 | 164 | .{ |
| 165 | 165 | "@addWithOverflow", |
| 166 | 166 | .{ |
lib/std/zig/primitives.zig+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | /// Set of primitive type and value names. |
| 4 | 4 | /// Does not include `_` or integer type names. |
| 5 | pub const names = std.ComptimeStringMap(void, .{ | |
| 5 | pub const names = std.StaticStringMap(void).initComptime(.{ | |
| 6 | 6 | .{"anyerror"}, |
| 7 | 7 | .{"anyframe"}, |
| 8 | 8 | .{"anyopaque"}, |
lib/std/zig/render.zig+4-4| ... | ... | @@ -2886,11 +2886,11 @@ fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote |
| 2886 | 2886 | // If we read the whole thing, we have to do further checks. |
| 2887 | 2887 | const longest_keyword_or_primitive_len = comptime blk: { |
| 2888 | 2888 | var longest = 0; |
| 2889 | for (primitives.names.kvs) |kv| { | |
| 2890 | if (kv.key.len > longest) longest = kv.key.len; | |
| 2889 | for (primitives.names.keys()) |key| { | |
| 2890 | if (key.len > longest) longest = key.len; | |
| 2891 | 2891 | } |
| 2892 | for (std.zig.Token.keywords.kvs) |kv| { | |
| 2893 | if (kv.key.len > longest) longest = kv.key.len; | |
| 2892 | for (std.zig.Token.keywords.keys()) |key| { | |
| 2893 | if (key.len > longest) longest = key.len; | |
| 2894 | 2894 | } |
| 2895 | 2895 | break :blk longest; |
| 2896 | 2896 | }; |
lib/std/zig/tokenizer.zig+1-1| ... | ... | @@ -9,7 +9,7 @@ pub const Token = struct { |
| 9 | 9 | end: usize, |
| 10 | 10 | }; |
| 11 | 11 | |
| 12 | pub const keywords = std.ComptimeStringMap(Tag, .{ | |
| 12 | pub const keywords = std.StaticStringMap(Tag).initComptime(.{ | |
| 13 | 13 | .{ "addrspace", .keyword_addrspace }, |
| 14 | 14 | .{ "align", .keyword_align }, |
| 15 | 15 | .{ "allowzero", .keyword_allowzero }, |
src/Compilation.zig+1-1| ... | ... | @@ -265,7 +265,7 @@ pub const CRTFile = struct { |
| 265 | 265 | |
| 266 | 266 | /// Supported languages for "zig clang -x <lang>". |
| 267 | 267 | /// Loosely based on llvm-project/clang/include/clang/Driver/Types.def |
| 268 | pub const LangToExt = std.ComptimeStringMap(FileExt, .{ | |
| 268 | pub const LangToExt = std.StaticStringMap(FileExt).initComptime(.{ | |
| 269 | 269 | .{ "c", .c }, |
| 270 | 270 | .{ "c-header", .h }, |
| 271 | 271 | .{ "c++", .cpp }, |
src/codegen/c.zig+1-1| ... | ... | @@ -116,7 +116,7 @@ const ValueRenderLocation = enum { |
| 116 | 116 | |
| 117 | 117 | const BuiltinInfo = enum { none, bits }; |
| 118 | 118 | |
| 119 | const reserved_idents = std.ComptimeStringMap(void, .{ | |
| 119 | const reserved_idents = std.StaticStringMap(void).initComptime(.{ | |
| 120 | 120 | // C language |
| 121 | 121 | .{ "alignas", { |
| 122 | 122 | @setEvalBranchQuota(4000); |
src/link/Wasm/types.zig+1-1| ... | ... | @@ -244,7 +244,7 @@ pub const Feature = struct { |
| 244 | 244 | } |
| 245 | 245 | }; |
| 246 | 246 | |
| 247 | pub const known_features = std.ComptimeStringMap(Feature.Tag, .{ | |
| 247 | pub const known_features = std.StaticStringMap(Feature.Tag).initComptime(.{ | |
| 248 | 248 | .{ "atomics", .atomics }, |
| 249 | 249 | .{ "bulk-memory", .bulk_memory }, |
| 250 | 250 | .{ "exception-handling", .exception_handling }, |
src/translate_c.zig+1-1| ... | ... | @@ -671,7 +671,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co |
| 671 | 671 | return addTopLevelDecl(c, var_name, node); |
| 672 | 672 | } |
| 673 | 673 | |
| 674 | const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{ | |
| 674 | const builtin_typedef_map = std.StaticStringMap([]const u8).initComptime(.{ | |
| 675 | 675 | .{ "uint8_t", "u8" }, |
| 676 | 676 | .{ "int8_t", "i8" }, |
| 677 | 677 | .{ "uint16_t", "u16" }, |
test/src/Cases.zig+1-1| ... | ... | @@ -993,7 +993,7 @@ const TestManifest = struct { |
| 993 | 993 | config_map: std.StringHashMap([]const u8), |
| 994 | 994 | trailing_bytes: []const u8 = "", |
| 995 | 995 | |
| 996 | const valid_keys = std.ComptimeStringMap(void, .{ | |
| 996 | const valid_keys = std.StaticStringMap(void).initComptime(.{ | |
| 997 | 997 | .{ "is_test", {} }, |
| 998 | 998 | .{ "output_mode", {} }, |
| 999 | 999 | .{ "target", {} }, |
tools/gen_spirv_spec.zig+1-1| ... | ... | @@ -45,7 +45,7 @@ const OperandKindMap = std.ArrayHashMap(StringPair, OperandKind, StringPairConte |
| 45 | 45 | /// Khronos made it so that these names are not defined explicitly, so |
| 46 | 46 | /// we need to hardcode it (like they did). |
| 47 | 47 | /// See https://github.com/KhronosGroup/SPIRV-Registry/ |
| 48 | const set_names = std.ComptimeStringMap([]const u8, .{ | |
| 48 | const set_names = std.StaticStringMap([]const u8).initComptime(.{ | |
| 49 | 49 | .{ "opencl.std.100", "OpenCL.std" }, |
| 50 | 50 | .{ "glsl.std.450", "GLSL.std.450" }, |
| 51 | 51 | .{ "opencl.debuginfo.100", "OpenCL.DebugInfo.100" }, |
tools/generate_linux_syscalls.zig+1-1| ... | ... | @@ -9,7 +9,7 @@ const fmt = std.fmt; |
| 9 | 9 | const zig = std.zig; |
| 10 | 10 | const fs = std.fs; |
| 11 | 11 | |
| 12 | const stdlib_renames = std.ComptimeStringMap([]const u8, .{ | |
| 12 | const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{ | |
| 13 | 13 | // Most 64-bit archs. |
| 14 | 14 | .{ "newfstatat", "fstatat64" }, |
| 15 | 15 | // POWER. |