| author | |
| committer | |
| log | 4787127cf6418f7a819c9d6f07a9046d76e0de65 |
| tree | 05e2a1d04722ec0a364a5c87278175c27ff7400d |
| parent | 6928badd850f9fcebdcc0b13287db2c81d2293c0 |
30 files changed, 1620 insertions(+), 1064 deletions(-)
std/atomic/queue.zig+7-5| ... | ... | @@ -70,7 +70,7 @@ test "std.atomic.queue" { |
| 70 | 70 | |
| 71 | 71 | var queue: Queue(i32) = undefined; |
| 72 | 72 | queue.init(); |
| 73 | var context = Context { | |
| 73 | var context = Context{ | |
| 74 | 74 | .allocator = a, |
| 75 | 75 | .queue = &queue, |
| 76 | 76 | .put_sum = 0, |
| ... | ... | @@ -81,16 +81,18 @@ test "std.atomic.queue" { |
| 81 | 81 | |
| 82 | 82 | var putters: [put_thread_count]&std.os.Thread = undefined; |
| 83 | 83 | for (putters) |*t| { |
| 84 | *t = try std.os.spawnThread(&context, startPuts); | |
| 84 | t.* = try std.os.spawnThread(&context, startPuts); | |
| 85 | 85 | } |
| 86 | 86 | var getters: [put_thread_count]&std.os.Thread = undefined; |
| 87 | 87 | for (getters) |*t| { |
| 88 | *t = try std.os.spawnThread(&context, startGets); | |
| 88 | t.* = try std.os.spawnThread(&context, startGets); | |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | for (putters) |t| t.wait(); | |
| 91 | for (putters) |t| | |
| 92 | t.wait(); | |
| 92 | 93 | _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); |
| 93 | for (getters) |t| t.wait(); | |
| 94 | for (getters) |t| | |
| 95 | t.wait(); | |
| 94 | 96 | |
| 95 | 97 | std.debug.assert(context.put_sum == context.get_sum); |
| 96 | 98 | std.debug.assert(context.get_count == puts_per_thread * put_thread_count); |
std/atomic/stack.zig+8-8| ... | ... | @@ -14,9 +14,7 @@ pub fn Stack(comptime T: type) type { |
| 14 | 14 | }; |
| 15 | 15 | |
| 16 | 16 | pub fn init() Self { |
| 17 | return Self { | |
| 18 | .root = null, | |
| 19 | }; | |
| 17 | return Self{ .root = null }; | |
| 20 | 18 | } |
| 21 | 19 | |
| 22 | 20 | /// push operation, but only if you are the first item in the stack. if you did not succeed in |
| ... | ... | @@ -75,7 +73,7 @@ test "std.atomic.stack" { |
| 75 | 73 | var a = &fixed_buffer_allocator.allocator; |
| 76 | 74 | |
| 77 | 75 | var stack = Stack(i32).init(); |
| 78 | var context = Context { | |
| 76 | var context = Context{ | |
| 79 | 77 | .allocator = a, |
| 80 | 78 | .stack = &stack, |
| 81 | 79 | .put_sum = 0, |
| ... | ... | @@ -86,16 +84,18 @@ test "std.atomic.stack" { |
| 86 | 84 | |
| 87 | 85 | var putters: [put_thread_count]&std.os.Thread = undefined; |
| 88 | 86 | for (putters) |*t| { |
| 89 | *t = try std.os.spawnThread(&context, startPuts); | |
| 87 | t.* = try std.os.spawnThread(&context, startPuts); | |
| 90 | 88 | } |
| 91 | 89 | var getters: [put_thread_count]&std.os.Thread = undefined; |
| 92 | 90 | for (getters) |*t| { |
| 93 | *t = try std.os.spawnThread(&context, startGets); | |
| 91 | t.* = try std.os.spawnThread(&context, startGets); | |
| 94 | 92 | } |
| 95 | 93 | |
| 96 | for (putters) |t| t.wait(); | |
| 94 | for (putters) |t| | |
| 95 | t.wait(); | |
| 97 | 96 | _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); |
| 98 | for (getters) |t| t.wait(); | |
| 97 | for (getters) |t| | |
| 98 | t.wait(); | |
| 99 | 99 | |
| 100 | 100 | std.debug.assert(context.put_sum == context.get_sum); |
| 101 | 101 | std.debug.assert(context.get_count == puts_per_thread * put_thread_count); |
std/buffer.zig+3-8| ... | ... | @@ -31,9 +31,7 @@ pub const Buffer = struct { |
| 31 | 31 | /// * ::replaceContentsBuffer |
| 32 | 32 | /// * ::resize |
| 33 | 33 | pub fn initNull(allocator: &Allocator) Buffer { |
| 34 | return Buffer { | |
| 35 | .list = ArrayList(u8).init(allocator), | |
| 36 | }; | |
| 34 | return Buffer{ .list = ArrayList(u8).init(allocator) }; | |
| 37 | 35 | } |
| 38 | 36 | |
| 39 | 37 | /// Must deinitialize with deinit. |
| ... | ... | @@ -45,9 +43,7 @@ pub const Buffer = struct { |
| 45 | 43 | /// allocated with `allocator`. |
| 46 | 44 | /// Must deinitialize with deinit. |
| 47 | 45 | pub fn fromOwnedSlice(allocator: &Allocator, slice: []u8) Buffer { |
| 48 | var self = Buffer { | |
| 49 | .list = ArrayList(u8).fromOwnedSlice(allocator, slice), | |
| 50 | }; | |
| 46 | var self = Buffer{ .list = ArrayList(u8).fromOwnedSlice(allocator, slice) }; | |
| 51 | 47 | self.list.append(0); |
| 52 | 48 | return self; |
| 53 | 49 | } |
| ... | ... | @@ -57,11 +53,10 @@ pub const Buffer = struct { |
| 57 | 53 | pub fn toOwnedSlice(self: &Buffer) []u8 { |
| 58 | 54 | const allocator = self.list.allocator; |
| 59 | 55 | const result = allocator.shrink(u8, self.list.items, self.len()); |
| 60 | *self = initNull(allocator); | |
| 56 | self.* = initNull(allocator); | |
| 61 | 57 | return result; |
| 62 | 58 | } |
| 63 | 59 | |
| 64 | ||
| 65 | 60 | pub fn deinit(self: &Buffer) void { |
| 66 | 61 | self.list.deinit(); |
| 67 | 62 | } |
std/build.zig+86-121| ... | ... | @@ -82,10 +82,8 @@ pub const Builder = struct { |
| 82 | 82 | description: []const u8, |
| 83 | 83 | }; |
| 84 | 84 | |
| 85 | pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8, | |
| 86 | cache_root: []const u8) Builder | |
| 87 | { | |
| 88 | var self = Builder { | |
| 85 | pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder { | |
| 86 | var self = Builder{ | |
| 89 | 87 | .zig_exe = zig_exe, |
| 90 | 88 | .build_root = build_root, |
| 91 | 89 | .cache_root = os.path.relative(allocator, build_root, cache_root) catch unreachable, |
| ... | ... | @@ -112,12 +110,12 @@ pub const Builder = struct { |
| 112 | 110 | .lib_dir = undefined, |
| 113 | 111 | .exe_dir = undefined, |
| 114 | 112 | .installed_files = ArrayList([]const u8).init(allocator), |
| 115 | .uninstall_tls = TopLevelStep { | |
| 113 | .uninstall_tls = TopLevelStep{ | |
| 116 | 114 | .step = Step.init("uninstall", allocator, makeUninstall), |
| 117 | 115 | .description = "Remove build artifacts from prefix path", |
| 118 | 116 | }, |
| 119 | 117 | .have_uninstall_step = false, |
| 120 | .install_tls = TopLevelStep { | |
| 118 | .install_tls = TopLevelStep{ | |
| 121 | 119 | .step = Step.initNoOp("install", allocator), |
| 122 | 120 | .description = "Copy build artifacts to prefix path", |
| 123 | 121 | }, |
| ... | ... | @@ -151,9 +149,7 @@ pub const Builder = struct { |
| 151 | 149 | return LibExeObjStep.createObject(self, name, root_src); |
| 152 | 150 | } |
| 153 | 151 | |
| 154 | pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8, | |
| 155 | ver: &const Version) &LibExeObjStep | |
| 156 | { | |
| 152 | pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8, ver: &const Version) &LibExeObjStep { | |
| 157 | 153 | return LibExeObjStep.createSharedLibrary(self, name, root_src, ver); |
| 158 | 154 | } |
| 159 | 155 | |
| ... | ... | @@ -163,7 +159,7 @@ pub const Builder = struct { |
| 163 | 159 | |
| 164 | 160 | pub fn addTest(self: &Builder, root_src: []const u8) &TestStep { |
| 165 | 161 | const test_step = self.allocator.create(TestStep) catch unreachable; |
| 166 | *test_step = TestStep.init(self, root_src); | |
| 162 | test_step.* = TestStep.init(self, root_src); | |
| 167 | 163 | return test_step; |
| 168 | 164 | } |
| 169 | 165 | |
| ... | ... | @@ -190,33 +186,31 @@ pub const Builder = struct { |
| 190 | 186 | } |
| 191 | 187 | |
| 192 | 188 | /// ::argv is copied. |
| 193 | pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, | |
| 194 | argv: []const []const u8) &CommandStep | |
| 195 | { | |
| 189 | pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) &CommandStep { | |
| 196 | 190 | return CommandStep.create(self, cwd, env_map, argv); |
| 197 | 191 | } |
| 198 | 192 | |
| 199 | 193 | pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) &WriteFileStep { |
| 200 | 194 | const write_file_step = self.allocator.create(WriteFileStep) catch unreachable; |
| 201 | *write_file_step = WriteFileStep.init(self, file_path, data); | |
| 195 | write_file_step.* = WriteFileStep.init(self, file_path, data); | |
| 202 | 196 | return write_file_step; |
| 203 | 197 | } |
| 204 | 198 | |
| 205 | 199 | pub fn addLog(self: &Builder, comptime format: []const u8, args: ...) &LogStep { |
| 206 | 200 | const data = self.fmt(format, args); |
| 207 | 201 | const log_step = self.allocator.create(LogStep) catch unreachable; |
| 208 | *log_step = LogStep.init(self, data); | |
| 202 | log_step.* = LogStep.init(self, data); | |
| 209 | 203 | return log_step; |
| 210 | 204 | } |
| 211 | 205 | |
| 212 | 206 | pub fn addRemoveDirTree(self: &Builder, dir_path: []const u8) &RemoveDirStep { |
| 213 | 207 | const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable; |
| 214 | *remove_dir_step = RemoveDirStep.init(self, dir_path); | |
| 208 | remove_dir_step.* = RemoveDirStep.init(self, dir_path); | |
| 215 | 209 | return remove_dir_step; |
| 216 | 210 | } |
| 217 | 211 | |
| 218 | 212 | pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) Version { |
| 219 | return Version { | |
| 213 | return Version{ | |
| 220 | 214 | .major = major, |
| 221 | 215 | .minor = minor, |
| 222 | 216 | .patch = patch, |
| ... | ... | @@ -254,8 +248,7 @@ pub const Builder = struct { |
| 254 | 248 | } |
| 255 | 249 | |
| 256 | 250 | pub fn getInstallStep(self: &Builder) &Step { |
| 257 | if (self.have_install_step) | |
| 258 | return &self.install_tls.step; | |
| 251 | if (self.have_install_step) return &self.install_tls.step; | |
| 259 | 252 | |
| 260 | 253 | self.top_level_steps.append(&self.install_tls) catch unreachable; |
| 261 | 254 | self.have_install_step = true; |
| ... | ... | @@ -263,8 +256,7 @@ pub const Builder = struct { |
| 263 | 256 | } |
| 264 | 257 | |
| 265 | 258 | pub fn getUninstallStep(self: &Builder) &Step { |
| 266 | if (self.have_uninstall_step) | |
| 267 | return &self.uninstall_tls.step; | |
| 259 | if (self.have_uninstall_step) return &self.uninstall_tls.step; | |
| 268 | 260 | |
| 269 | 261 | self.top_level_steps.append(&self.uninstall_tls) catch unreachable; |
| 270 | 262 | self.have_uninstall_step = true; |
| ... | ... | @@ -360,7 +352,7 @@ pub const Builder = struct { |
| 360 | 352 | |
| 361 | 353 | pub fn option(self: &Builder, comptime T: type, name: []const u8, description: []const u8) ?T { |
| 362 | 354 | const type_id = comptime typeToEnum(T); |
| 363 | const available_option = AvailableOption { | |
| 355 | const available_option = AvailableOption{ | |
| 364 | 356 | .name = name, |
| 365 | 357 | .type_id = type_id, |
| 366 | 358 | .description = description, |
| ... | ... | @@ -413,7 +405,7 @@ pub const Builder = struct { |
| 413 | 405 | |
| 414 | 406 | pub fn step(self: &Builder, name: []const u8, description: []const u8) &Step { |
| 415 | 407 | const step_info = self.allocator.create(TopLevelStep) catch unreachable; |
| 416 | *step_info = TopLevelStep { | |
| 408 | step_info.* = TopLevelStep{ | |
| 417 | 409 | .step = Step.initNoOp(name, self.allocator), |
| 418 | 410 | .description = description, |
| 419 | 411 | }; |
| ... | ... | @@ -446,9 +438,9 @@ pub const Builder = struct { |
| 446 | 438 | } |
| 447 | 439 | |
| 448 | 440 | pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) bool { |
| 449 | if (self.user_input_options.put(name, UserInputOption { | |
| 441 | if (self.user_input_options.put(name, UserInputOption{ | |
| 450 | 442 | .name = name, |
| 451 | .value = UserValue { .Scalar = value }, | |
| 443 | .value = UserValue{ .Scalar = value }, | |
| 452 | 444 | .used = false, |
| 453 | 445 | }) catch unreachable) |*prev_value| { |
| 454 | 446 | // option already exists |
| ... | ... | @@ -458,18 +450,18 @@ pub const Builder = struct { |
| 458 | 450 | var list = ArrayList([]const u8).init(self.allocator); |
| 459 | 451 | list.append(s) catch unreachable; |
| 460 | 452 | list.append(value) catch unreachable; |
| 461 | _ = self.user_input_options.put(name, UserInputOption { | |
| 453 | _ = self.user_input_options.put(name, UserInputOption{ | |
| 462 | 454 | .name = name, |
| 463 | .value = UserValue { .List = list }, | |
| 455 | .value = UserValue{ .List = list }, | |
| 464 | 456 | .used = false, |
| 465 | 457 | }) catch unreachable; |
| 466 | 458 | }, |
| 467 | 459 | UserValue.List => |*list| { |
| 468 | 460 | // append to the list |
| 469 | 461 | list.append(value) catch unreachable; |
| 470 | _ = self.user_input_options.put(name, UserInputOption { | |
| 462 | _ = self.user_input_options.put(name, UserInputOption{ | |
| 471 | 463 | .name = name, |
| 472 | .value = UserValue { .List = *list }, | |
| 464 | .value = UserValue{ .List = list.* }, | |
| 473 | 465 | .used = false, |
| 474 | 466 | }) catch unreachable; |
| 475 | 467 | }, |
| ... | ... | @@ -483,9 +475,9 @@ pub const Builder = struct { |
| 483 | 475 | } |
| 484 | 476 | |
| 485 | 477 | pub fn addUserInputFlag(self: &Builder, name: []const u8) bool { |
| 486 | if (self.user_input_options.put(name, UserInputOption { | |
| 478 | if (self.user_input_options.put(name, UserInputOption{ | |
| 487 | 479 | .name = name, |
| 488 | .value = UserValue {.Flag = {} }, | |
| 480 | .value = UserValue{ .Flag = {} }, | |
| 489 | 481 | .used = false, |
| 490 | 482 | }) catch unreachable) |*prev_value| { |
| 491 | 483 | switch (prev_value.value) { |
| ... | ... | @@ -556,9 +548,7 @@ pub const Builder = struct { |
| 556 | 548 | warn("\n"); |
| 557 | 549 | } |
| 558 | 550 | |
| 559 | fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, | |
| 560 | argv: []const []const u8) !void | |
| 561 | { | |
| 551 | fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) !void { | |
| 562 | 552 | if (self.verbose) { |
| 563 | 553 | printCmd(cwd, argv); |
| 564 | 554 | } |
| ... | ... | @@ -617,7 +607,7 @@ pub const Builder = struct { |
| 617 | 607 | self.pushInstalledFile(full_dest_path); |
| 618 | 608 | |
| 619 | 609 | const install_step = self.allocator.create(InstallFileStep) catch unreachable; |
| 620 | *install_step = InstallFileStep.init(self, src_path, full_dest_path); | |
| 610 | install_step.* = InstallFileStep.init(self, src_path, full_dest_path); | |
| 621 | 611 | return install_step; |
| 622 | 612 | } |
| 623 | 613 | |
| ... | ... | @@ -659,25 +649,23 @@ pub const Builder = struct { |
| 659 | 649 | if (builtin.environ == builtin.Environ.msvc) { |
| 660 | 650 | return "cl.exe"; |
| 661 | 651 | } else { |
| 662 | return os.getEnvVarOwned(self.allocator, "CC") catch |err| | |
| 652 | return os.getEnvVarOwned(self.allocator, "CC") catch |err| | |
| 663 | 653 | if (err == error.EnvironmentVariableNotFound) |
| 664 | 654 | ([]const u8)("cc") |
| 665 | 655 | else |
| 666 | debug.panic("Unable to get environment variable: {}", err) | |
| 667 | ; | |
| 656 | debug.panic("Unable to get environment variable: {}", err); | |
| 668 | 657 | } |
| 669 | 658 | } |
| 670 | 659 | |
| 671 | 660 | pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 { |
| 672 | 661 | // TODO report error for ambiguous situations |
| 673 | const exe_extension = (Target { .Native = {}}).exeFileExt(); | |
| 662 | const exe_extension = (Target{ .Native = {} }).exeFileExt(); | |
| 674 | 663 | for (self.search_prefixes.toSliceConst()) |search_prefix| { |
| 675 | 664 | for (names) |name| { |
| 676 | 665 | if (os.path.isAbsolute(name)) { |
| 677 | 666 | return name; |
| 678 | 667 | } |
| 679 | const full_path = try os.path.join(self.allocator, search_prefix, "bin", | |
| 680 | self.fmt("{}{}", name, exe_extension)); | |
| 668 | const full_path = try os.path.join(self.allocator, search_prefix, "bin", self.fmt("{}{}", name, exe_extension)); | |
| 681 | 669 | if (os.path.real(self.allocator, full_path)) |real_path| { |
| 682 | 670 | return real_path; |
| 683 | 671 | } else |_| { |
| ... | ... | @@ -761,7 +749,7 @@ pub const Target = union(enum) { |
| 761 | 749 | Cross: CrossTarget, |
| 762 | 750 | |
| 763 | 751 | pub fn oFileExt(self: &const Target) []const u8 { |
| 764 | const environ = switch (*self) { | |
| 752 | const environ = switch (self.*) { | |
| 765 | 753 | Target.Native => builtin.environ, |
| 766 | 754 | Target.Cross => |t| t.environ, |
| 767 | 755 | }; |
| ... | ... | @@ -786,7 +774,7 @@ pub const Target = union(enum) { |
| 786 | 774 | } |
| 787 | 775 | |
| 788 | 776 | pub fn getOs(self: &const Target) builtin.Os { |
| 789 | return switch (*self) { | |
| 777 | return switch (self.*) { | |
| 790 | 778 | Target.Native => builtin.os, |
| 791 | 779 | Target.Cross => |t| t.os, |
| 792 | 780 | }; |
| ... | ... | @@ -794,7 +782,8 @@ pub const Target = union(enum) { |
| 794 | 782 | |
| 795 | 783 | pub fn isDarwin(self: &const Target) bool { |
| 796 | 784 | return switch (self.getOs()) { |
| 797 | builtin.Os.ios, builtin.Os.macosx => true, | |
| 785 | builtin.Os.ios, | |
| 786 | builtin.Os.macosx => true, | |
| 798 | 787 | else => false, |
| 799 | 788 | }; |
| 800 | 789 | } |
| ... | ... | @@ -860,61 +849,57 @@ pub const LibExeObjStep = struct { |
| 860 | 849 | Obj, |
| 861 | 850 | }; |
| 862 | 851 | |
| 863 | pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8, | |
| 864 | ver: &const Version) &LibExeObjStep | |
| 865 | { | |
| 852 | pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8, ver: &const Version) &LibExeObjStep { | |
| 866 | 853 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 867 | *self = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver); | |
| 854 | self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver); | |
| 868 | 855 | return self; |
| 869 | 856 | } |
| 870 | 857 | |
| 871 | 858 | pub fn createCSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) &LibExeObjStep { |
| 872 | 859 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 873 | *self = initC(builder, name, Kind.Lib, version, false); | |
| 860 | self.* = initC(builder, name, Kind.Lib, version, false); | |
| 874 | 861 | return self; |
| 875 | 862 | } |
| 876 | 863 | |
| 877 | 864 | pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep { |
| 878 | 865 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 879 | *self = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0)); | |
| 866 | self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0)); | |
| 880 | 867 | return self; |
| 881 | 868 | } |
| 882 | 869 | |
| 883 | 870 | pub fn createCStaticLibrary(builder: &Builder, name: []const u8) &LibExeObjStep { |
| 884 | 871 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 885 | *self = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true); | |
| 872 | self.* = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true); | |
| 886 | 873 | return self; |
| 887 | 874 | } |
| 888 | 875 | |
| 889 | 876 | pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) &LibExeObjStep { |
| 890 | 877 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 891 | *self = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0)); | |
| 878 | self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0)); | |
| 892 | 879 | return self; |
| 893 | 880 | } |
| 894 | 881 | |
| 895 | 882 | pub fn createCObject(builder: &Builder, name: []const u8, src: []const u8) &LibExeObjStep { |
| 896 | 883 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 897 | *self = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false); | |
| 884 | self.* = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false); | |
| 898 | 885 | self.object_src = src; |
| 899 | 886 | return self; |
| 900 | 887 | } |
| 901 | 888 | |
| 902 | 889 | pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep { |
| 903 | 890 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 904 | *self = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0)); | |
| 891 | self.* = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0)); | |
| 905 | 892 | return self; |
| 906 | 893 | } |
| 907 | 894 | |
| 908 | 895 | pub fn createCExecutable(builder: &Builder, name: []const u8) &LibExeObjStep { |
| 909 | 896 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 910 | *self = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false); | |
| 897 | self.* = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false); | |
| 911 | 898 | return self; |
| 912 | 899 | } |
| 913 | 900 | |
| 914 | fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, | |
| 915 | static: bool, ver: &const Version) LibExeObjStep | |
| 916 | { | |
| 917 | var self = LibExeObjStep { | |
| 901 | fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, static: bool, ver: &const Version) LibExeObjStep { | |
| 902 | var self = LibExeObjStep{ | |
| 918 | 903 | .strip = false, |
| 919 | 904 | .builder = builder, |
| 920 | 905 | .verbose_link = false, |
| ... | ... | @@ -930,7 +915,7 @@ pub const LibExeObjStep = struct { |
| 930 | 915 | .step = Step.init(name, builder.allocator, make), |
| 931 | 916 | .output_path = null, |
| 932 | 917 | .output_h_path = null, |
| 933 | .version = *ver, | |
| 918 | .version = ver.*, | |
| 934 | 919 | .out_filename = undefined, |
| 935 | 920 | .out_h_filename = builder.fmt("{}.h", name), |
| 936 | 921 | .major_only_filename = undefined, |
| ... | ... | @@ -953,11 +938,11 @@ pub const LibExeObjStep = struct { |
| 953 | 938 | } |
| 954 | 939 | |
| 955 | 940 | fn initC(builder: &Builder, name: []const u8, kind: Kind, version: &const Version, static: bool) LibExeObjStep { |
| 956 | var self = LibExeObjStep { | |
| 941 | var self = LibExeObjStep{ | |
| 957 | 942 | .builder = builder, |
| 958 | 943 | .name = name, |
| 959 | 944 | .kind = kind, |
| 960 | .version = *version, | |
| 945 | .version = version.*, | |
| 961 | 946 | .static = static, |
| 962 | 947 | .target = Target.Native, |
| 963 | 948 | .cflags = ArrayList([]const u8).init(builder.allocator), |
| ... | ... | @@ -1005,9 +990,9 @@ pub const LibExeObjStep = struct { |
| 1005 | 990 | self.out_filename = self.builder.fmt("lib{}.a", self.name); |
| 1006 | 991 | } else { |
| 1007 | 992 | switch (self.target.getOs()) { |
| 1008 | builtin.Os.ios, builtin.Os.macosx => { | |
| 1009 | self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", | |
| 1010 | self.name, self.version.major, self.version.minor, self.version.patch); | |
| 993 | builtin.Os.ios, | |
| 994 | builtin.Os.macosx => { | |
| 995 | self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch); | |
| 1011 | 996 | self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major); |
| 1012 | 997 | self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name); |
| 1013 | 998 | }, |
| ... | ... | @@ -1015,8 +1000,7 @@ pub const LibExeObjStep = struct { |
| 1015 | 1000 | self.out_filename = self.builder.fmt("{}.dll", self.name); |
| 1016 | 1001 | }, |
| 1017 | 1002 | else => { |
| 1018 | self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", | |
| 1019 | self.name, self.version.major, self.version.minor, self.version.patch); | |
| 1003 | self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", self.name, self.version.major, self.version.minor, self.version.patch); | |
| 1020 | 1004 | self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major); |
| 1021 | 1005 | self.name_only_filename = self.builder.fmt("lib{}.so", self.name); |
| 1022 | 1006 | }, |
| ... | ... | @@ -1026,16 +1010,12 @@ pub const LibExeObjStep = struct { |
| 1026 | 1010 | } |
| 1027 | 1011 | } |
| 1028 | 1012 | |
| 1029 | pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, | |
| 1030 | target_environ: builtin.Environ) void | |
| 1031 | { | |
| 1032 | self.target = Target { | |
| 1033 | .Cross = CrossTarget { | |
| 1034 | .arch = target_arch, | |
| 1035 | .os = target_os, | |
| 1036 | .environ = target_environ, | |
| 1037 | } | |
| 1038 | }; | |
| 1013 | pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void { | |
| 1014 | self.target = Target{ .Cross = CrossTarget{ | |
| 1015 | .arch = target_arch, | |
| 1016 | .os = target_os, | |
| 1017 | .environ = target_environ, | |
| 1018 | } }; | |
| 1039 | 1019 | self.computeOutFileNames(); |
| 1040 | 1020 | } |
| 1041 | 1021 | |
| ... | ... | @@ -1159,7 +1139,7 @@ pub const LibExeObjStep = struct { |
| 1159 | 1139 | pub fn addPackagePath(self: &LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void { |
| 1160 | 1140 | assert(self.is_zig); |
| 1161 | 1141 | |
| 1162 | self.packages.append(Pkg { | |
| 1142 | self.packages.append(Pkg{ | |
| 1163 | 1143 | .name = name, |
| 1164 | 1144 | .path = pkg_index_path, |
| 1165 | 1145 | }) catch unreachable; |
| ... | ... | @@ -1343,8 +1323,7 @@ pub const LibExeObjStep = struct { |
| 1343 | 1323 | try builder.spawnChild(zig_args.toSliceConst()); |
| 1344 | 1324 | |
| 1345 | 1325 | if (self.kind == Kind.Lib and !self.static and self.target.wantSharedLibSymLinks()) { |
| 1346 | try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, | |
| 1347 | self.name_only_filename); | |
| 1326 | try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename); | |
| 1348 | 1327 | } |
| 1349 | 1328 | } |
| 1350 | 1329 | |
| ... | ... | @@ -1373,7 +1352,8 @@ pub const LibExeObjStep = struct { |
| 1373 | 1352 | args.append("ssp-buffer-size=4") catch unreachable; |
| 1374 | 1353 | } |
| 1375 | 1354 | }, |
| 1376 | builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => { | |
| 1355 | builtin.Mode.ReleaseFast, | |
| 1356 | builtin.Mode.ReleaseSmall => { | |
| 1377 | 1357 | args.append("-O2") catch unreachable; |
| 1378 | 1358 | args.append("-fno-stack-protector") catch unreachable; |
| 1379 | 1359 | }, |
| ... | ... | @@ -1505,8 +1485,7 @@ pub const LibExeObjStep = struct { |
| 1505 | 1485 | } |
| 1506 | 1486 | |
| 1507 | 1487 | if (!is_darwin) { |
| 1508 | const rpath_arg = builder.fmt("-Wl,-rpath,{}", | |
| 1509 | os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable); | |
| 1488 | const rpath_arg = builder.fmt("-Wl,-rpath,{}", os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable); | |
| 1510 | 1489 | defer builder.allocator.free(rpath_arg); |
| 1511 | 1490 | cc_args.append(rpath_arg) catch unreachable; |
| 1512 | 1491 | |
| ... | ... | @@ -1535,8 +1514,7 @@ pub const LibExeObjStep = struct { |
| 1535 | 1514 | try builder.spawnChild(cc_args.toSliceConst()); |
| 1536 | 1515 | |
| 1537 | 1516 | if (self.target.wantSharedLibSymLinks()) { |
| 1538 | try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, | |
| 1539 | self.name_only_filename); | |
| 1517 | try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename); | |
| 1540 | 1518 | } |
| 1541 | 1519 | } |
| 1542 | 1520 | }, |
| ... | ... | @@ -1581,8 +1559,7 @@ pub const LibExeObjStep = struct { |
| 1581 | 1559 | cc_args.append("-o") catch unreachable; |
| 1582 | 1560 | cc_args.append(output_path) catch unreachable; |
| 1583 | 1561 | |
| 1584 | const rpath_arg = builder.fmt("-Wl,-rpath,{}", | |
| 1585 | os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable); | |
| 1562 | const rpath_arg = builder.fmt("-Wl,-rpath,{}", os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable); | |
| 1586 | 1563 | defer builder.allocator.free(rpath_arg); |
| 1587 | 1564 | cc_args.append(rpath_arg) catch unreachable; |
| 1588 | 1565 | |
| ... | ... | @@ -1635,7 +1612,7 @@ pub const TestStep = struct { |
| 1635 | 1612 | |
| 1636 | 1613 | pub fn init(builder: &Builder, root_src: []const u8) TestStep { |
| 1637 | 1614 | const step_name = builder.fmt("test {}", root_src); |
| 1638 | return TestStep { | |
| 1615 | return TestStep{ | |
| 1639 | 1616 | .step = Step.init(step_name, builder.allocator, make), |
| 1640 | 1617 | .builder = builder, |
| 1641 | 1618 | .root_src = root_src, |
| ... | ... | @@ -1644,7 +1621,7 @@ pub const TestStep = struct { |
| 1644 | 1621 | .name_prefix = "", |
| 1645 | 1622 | .filter = null, |
| 1646 | 1623 | .link_libs = BufSet.init(builder.allocator), |
| 1647 | .target = Target { .Native = {} }, | |
| 1624 | .target = Target{ .Native = {} }, | |
| 1648 | 1625 | .exec_cmd_args = null, |
| 1649 | 1626 | .include_dirs = ArrayList([]const u8).init(builder.allocator), |
| 1650 | 1627 | }; |
| ... | ... | @@ -1674,16 +1651,12 @@ pub const TestStep = struct { |
| 1674 | 1651 | self.filter = text; |
| 1675 | 1652 | } |
| 1676 | 1653 | |
| 1677 | pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, | |
| 1678 | target_environ: builtin.Environ) void | |
| 1679 | { | |
| 1680 | self.target = Target { | |
| 1681 | .Cross = CrossTarget { | |
| 1682 | .arch = target_arch, | |
| 1683 | .os = target_os, | |
| 1684 | .environ = target_environ, | |
| 1685 | } | |
| 1686 | }; | |
| 1654 | pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void { | |
| 1655 | self.target = Target{ .Cross = CrossTarget{ | |
| 1656 | .arch = target_arch, | |
| 1657 | .os = target_os, | |
| 1658 | .environ = target_environ, | |
| 1659 | } }; | |
| 1687 | 1660 | } |
| 1688 | 1661 | |
| 1689 | 1662 | pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) void { |
| ... | ... | @@ -1789,11 +1762,9 @@ pub const CommandStep = struct { |
| 1789 | 1762 | env_map: &const BufMap, |
| 1790 | 1763 | |
| 1791 | 1764 | /// ::argv is copied. |
| 1792 | pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap, | |
| 1793 | argv: []const []const u8) &CommandStep | |
| 1794 | { | |
| 1765 | pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) &CommandStep { | |
| 1795 | 1766 | const self = builder.allocator.create(CommandStep) catch unreachable; |
| 1796 | *self = CommandStep { | |
| 1767 | self.* = CommandStep{ | |
| 1797 | 1768 | .builder = builder, |
| 1798 | 1769 | .step = Step.init(argv[0], builder.allocator, make), |
| 1799 | 1770 | .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable, |
| ... | ... | @@ -1828,7 +1799,7 @@ const InstallArtifactStep = struct { |
| 1828 | 1799 | LibExeObjStep.Kind.Exe => builder.exe_dir, |
| 1829 | 1800 | LibExeObjStep.Kind.Lib => builder.lib_dir, |
| 1830 | 1801 | }; |
| 1831 | *self = Self { | |
| 1802 | self.* = Self{ | |
| 1832 | 1803 | .builder = builder, |
| 1833 | 1804 | .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make), |
| 1834 | 1805 | .artifact = artifact, |
| ... | ... | @@ -1837,10 +1808,8 @@ const InstallArtifactStep = struct { |
| 1837 | 1808 | self.step.dependOn(&artifact.step); |
| 1838 | 1809 | builder.pushInstalledFile(self.dest_file); |
| 1839 | 1810 | if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) { |
| 1840 | builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, | |
| 1841 | artifact.major_only_filename) catch unreachable); | |
| 1842 | builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, | |
| 1843 | artifact.name_only_filename) catch unreachable); | |
| 1811 | builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.major_only_filename) catch unreachable); | |
| 1812 | builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.name_only_filename) catch unreachable); | |
| 1844 | 1813 | } |
| 1845 | 1814 | return self; |
| 1846 | 1815 | } |
| ... | ... | @@ -1859,8 +1828,7 @@ const InstallArtifactStep = struct { |
| 1859 | 1828 | }; |
| 1860 | 1829 | try builder.copyFileMode(self.artifact.getOutputPath(), self.dest_file, mode); |
| 1861 | 1830 | if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) { |
| 1862 | try doAtomicSymLinks(builder.allocator, self.dest_file, | |
| 1863 | self.artifact.major_only_filename, self.artifact.name_only_filename); | |
| 1831 | try doAtomicSymLinks(builder.allocator, self.dest_file, self.artifact.major_only_filename, self.artifact.name_only_filename); | |
| 1864 | 1832 | } |
| 1865 | 1833 | } |
| 1866 | 1834 | }; |
| ... | ... | @@ -1872,7 +1840,7 @@ pub const InstallFileStep = struct { |
| 1872 | 1840 | dest_path: []const u8, |
| 1873 | 1841 | |
| 1874 | 1842 | pub fn init(builder: &Builder, src_path: []const u8, dest_path: []const u8) InstallFileStep { |
| 1875 | return InstallFileStep { | |
| 1843 | return InstallFileStep{ | |
| 1876 | 1844 | .builder = builder, |
| 1877 | 1845 | .step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make), |
| 1878 | 1846 | .src_path = src_path, |
| ... | ... | @@ -1893,7 +1861,7 @@ pub const WriteFileStep = struct { |
| 1893 | 1861 | data: []const u8, |
| 1894 | 1862 | |
| 1895 | 1863 | pub fn init(builder: &Builder, file_path: []const u8, data: []const u8) WriteFileStep { |
| 1896 | return WriteFileStep { | |
| 1864 | return WriteFileStep{ | |
| 1897 | 1865 | .builder = builder, |
| 1898 | 1866 | .step = Step.init(builder.fmt("writefile {}", file_path), builder.allocator, make), |
| 1899 | 1867 | .file_path = file_path, |
| ... | ... | @@ -1922,7 +1890,7 @@ pub const LogStep = struct { |
| 1922 | 1890 | data: []const u8, |
| 1923 | 1891 | |
| 1924 | 1892 | pub fn init(builder: &Builder, data: []const u8) LogStep { |
| 1925 | return LogStep { | |
| 1893 | return LogStep{ | |
| 1926 | 1894 | .builder = builder, |
| 1927 | 1895 | .step = Step.init(builder.fmt("log {}", data), builder.allocator, make), |
| 1928 | 1896 | .data = data, |
| ... | ... | @@ -1941,7 +1909,7 @@ pub const RemoveDirStep = struct { |
| 1941 | 1909 | dir_path: []const u8, |
| 1942 | 1910 | |
| 1943 | 1911 | pub fn init(builder: &Builder, dir_path: []const u8) RemoveDirStep { |
| 1944 | return RemoveDirStep { | |
| 1912 | return RemoveDirStep{ | |
| 1945 | 1913 | .builder = builder, |
| 1946 | 1914 | .step = Step.init(builder.fmt("RemoveDir {}", dir_path), builder.allocator, make), |
| 1947 | 1915 | .dir_path = dir_path, |
| ... | ... | @@ -1966,8 +1934,8 @@ pub const Step = struct { |
| 1966 | 1934 | loop_flag: bool, |
| 1967 | 1935 | done_flag: bool, |
| 1968 | 1936 | |
| 1969 | pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)error!void) Step { | |
| 1970 | return Step { | |
| 1937 | pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn(&Step) error!void) Step { | |
| 1938 | return Step{ | |
| 1971 | 1939 | .name = name, |
| 1972 | 1940 | .makeFn = makeFn, |
| 1973 | 1941 | .dependencies = ArrayList(&Step).init(allocator), |
| ... | ... | @@ -1980,8 +1948,7 @@ pub const Step = struct { |
| 1980 | 1948 | } |
| 1981 | 1949 | |
| 1982 | 1950 | pub fn make(self: &Step) !void { |
| 1983 | if (self.done_flag) | |
| 1984 | return; | |
| 1951 | if (self.done_flag) return; | |
| 1985 | 1952 | |
| 1986 | 1953 | try self.makeFn(self); |
| 1987 | 1954 | self.done_flag = true; |
| ... | ... | @@ -1994,9 +1961,7 @@ pub const Step = struct { |
| 1994 | 1961 | fn makeNoOp(self: &Step) error!void {} |
| 1995 | 1962 | }; |
| 1996 | 1963 | |
| 1997 | fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, | |
| 1998 | filename_name_only: []const u8) !void | |
| 1999 | { | |
| 1964 | fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, filename_name_only: []const u8) !void { | |
| 2000 | 1965 | const out_dir = os.path.dirname(output_path); |
| 2001 | 1966 | const out_basename = os.path.basename(output_path); |
| 2002 | 1967 | // sym link for libfoo.so.1 to libfoo.so.1.2.3 |
std/crypto/blake2.zig+470-241| ... | ... | @@ -6,11 +6,23 @@ const builtin = @import("builtin"); |
| 6 | 6 | const htest = @import("test.zig"); |
| 7 | 7 | |
| 8 | 8 | const RoundParam = struct { |
| 9 | a: usize, b: usize, c: usize, d: usize, x: usize, y: usize, | |
| 9 | a: usize, | |
| 10 | b: usize, | |
| 11 | c: usize, | |
| 12 | d: usize, | |
| 13 | x: usize, | |
| 14 | y: usize, | |
| 10 | 15 | }; |
| 11 | 16 | |
| 12 | 17 | fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam { |
| 13 | return RoundParam { .a = a, .b = b, .c = c, .d = d, .x = x, .y = y, }; | |
| 18 | return RoundParam{ | |
| 19 | .a = a, | |
| 20 | .b = b, | |
| 21 | .c = c, | |
| 22 | .d = d, | |
| 23 | .x = x, | |
| 24 | .y = y, | |
| 25 | }; | |
| 14 | 26 | } |
| 15 | 27 | |
| 16 | 28 | ///////////////////// |
| ... | ... | @@ -19,145 +31,153 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam { |
| 19 | 31 | pub const Blake2s224 = Blake2s(224); |
| 20 | 32 | pub const Blake2s256 = Blake2s(256); |
| 21 | 33 | |
| 22 | fn Blake2s(comptime out_len: usize) type { return struct { | |
| 23 | const Self = this; | |
| 24 | const block_size = 64; | |
| 25 | const digest_size = out_len / 8; | |
| 34 | fn Blake2s(comptime out_len: usize) type { | |
| 35 | return struct { | |
| 36 | const Self = this; | |
| 37 | const block_size = 64; | |
| 38 | const digest_size = out_len / 8; | |
| 39 | ||
| 40 | const iv = [8]u32{ | |
| 41 | 0x6A09E667, | |
| 42 | 0xBB67AE85, | |
| 43 | 0x3C6EF372, | |
| 44 | 0xA54FF53A, | |
| 45 | 0x510E527F, | |
| 46 | 0x9B05688C, | |
| 47 | 0x1F83D9AB, | |
| 48 | 0x5BE0CD19, | |
| 49 | }; | |
| 26 | 50 | |
| 27 | const iv = [8]u32 { | |
| 28 | 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, | |
| 29 | 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19, | |
| 30 | }; | |
| 51 | const sigma = [10][16]u8{ | |
| 52 | []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, | |
| 53 | []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, | |
| 54 | []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, | |
| 55 | []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, | |
| 56 | []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, | |
| 57 | []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, | |
| 58 | []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, | |
| 59 | []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, | |
| 60 | []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, | |
| 61 | []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, | |
| 62 | }; | |
| 31 | 63 | |
| 32 | const sigma = [10][16]u8 { | |
| 33 | []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, | |
| 34 | []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, | |
| 35 | []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, | |
| 36 | []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, | |
| 37 | []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, | |
| 38 | []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, | |
| 39 | []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, | |
| 40 | []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, | |
| 41 | []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, | |
| 42 | []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, | |
| 43 | }; | |
| 64 | h: [8]u32, | |
| 65 | t: u64, | |
| 66 | // Streaming cache | |
| 67 | buf: [64]u8, | |
| 68 | buf_len: u8, | |
| 44 | 69 | |
| 45 | h: [8]u32, | |
| 46 | t: u64, | |
| 47 | // Streaming cache | |
| 48 | buf: [64]u8, | |
| 49 | buf_len: u8, | |
| 50 | ||
| 51 | pub fn init() Self { | |
| 52 | debug.assert(8 <= out_len and out_len <= 512); | |
| 53 | ||
| 54 | var s: Self = undefined; | |
| 55 | s.reset(); | |
| 56 | return s; | |
| 57 | } | |
| 58 | ||
| 59 | pub fn reset(d: &Self) void { | |
| 60 | mem.copy(u32, d.h[0..], iv[0..]); | |
| 61 | ||
| 62 | // No key plus default parameters | |
| 63 | d.h[0] ^= 0x01010000 ^ u32(out_len >> 3); | |
| 64 | d.t = 0; | |
| 65 | d.buf_len = 0; | |
| 66 | } | |
| 67 | ||
| 68 | pub fn hash(b: []const u8, out: []u8) void { | |
| 69 | var d = Self.init(); | |
| 70 | d.update(b); | |
| 71 | d.final(out); | |
| 72 | } | |
| 73 | ||
| 74 | pub fn update(d: &Self, b: []const u8) void { | |
| 75 | var off: usize = 0; | |
| 76 | ||
| 77 | // Partial buffer exists from previous update. Copy into buffer then hash. | |
| 78 | if (d.buf_len != 0 and d.buf_len + b.len > 64) { | |
| 79 | off += 64 - d.buf_len; | |
| 80 | mem.copy(u8, d.buf[d.buf_len..], b[0..off]); | |
| 81 | d.t += 64; | |
| 82 | d.round(d.buf[0..], false); | |
| 83 | d.buf_len = 0; | |
| 70 | pub fn init() Self { | |
| 71 | debug.assert(8 <= out_len and out_len <= 512); | |
| 72 | ||
| 73 | var s: Self = undefined; | |
| 74 | s.reset(); | |
| 75 | return s; | |
| 84 | 76 | } |
| 85 | 77 | |
| 86 | // Full middle blocks. | |
| 87 | while (off + 64 <= b.len) : (off += 64) { | |
| 88 | d.t += 64; | |
| 89 | d.round(b[off..off + 64], false); | |
| 78 | pub fn reset(d: &Self) void { | |
| 79 | mem.copy(u32, d.h[0..], iv[0..]); | |
| 80 | ||
| 81 | // No key plus default parameters | |
| 82 | d.h[0] ^= 0x01010000 ^ u32(out_len >> 3); | |
| 83 | d.t = 0; | |
| 84 | d.buf_len = 0; | |
| 90 | 85 | } |
| 91 | 86 | |
| 92 | // Copy any remainder for next pass. | |
| 93 | mem.copy(u8, d.buf[d.buf_len..], b[off..]); | |
| 94 | d.buf_len += u8(b[off..].len); | |
| 95 | } | |
| 87 | pub fn hash(b: []const u8, out: []u8) void { | |
| 88 | var d = Self.init(); | |
| 89 | d.update(b); | |
| 90 | d.final(out); | |
| 91 | } | |
| 96 | 92 | |
| 97 | pub fn final(d: &Self, out: []u8) void { | |
| 98 | debug.assert(out.len >= out_len / 8); | |
| 93 | pub fn update(d: &Self, b: []const u8) void { | |
| 94 | var off: usize = 0; | |
| 99 | 95 | |
| 100 | mem.set(u8, d.buf[d.buf_len..], 0); | |
| 101 | d.t += d.buf_len; | |
| 102 | d.round(d.buf[0..], true); | |
| 96 | // Partial buffer exists from previous update. Copy into buffer then hash. | |
| 97 | if (d.buf_len != 0 and d.buf_len + b.len > 64) { | |
| 98 | off += 64 - d.buf_len; | |
| 99 | mem.copy(u8, d.buf[d.buf_len..], b[0..off]); | |
| 100 | d.t += 64; | |
| 101 | d.round(d.buf[0..], false); | |
| 102 | d.buf_len = 0; | |
| 103 | } | |
| 103 | 104 | |
| 104 | const rr = d.h[0 .. out_len / 32]; | |
| 105 | // Full middle blocks. | |
| 106 | while (off + 64 <= b.len) : (off += 64) { | |
| 107 | d.t += 64; | |
| 108 | d.round(b[off..off + 64], false); | |
| 109 | } | |
| 105 | 110 | |
| 106 | for (rr) |s, j| { | |
| 107 | mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Little); | |
| 111 | // Copy any remainder for next pass. | |
| 112 | mem.copy(u8, d.buf[d.buf_len..], b[off..]); | |
| 113 | d.buf_len += u8(b[off..].len); | |
| 108 | 114 | } |
| 109 | } | |
| 110 | 115 | |
| 111 | fn round(d: &Self, b: []const u8, last: bool) void { | |
| 112 | debug.assert(b.len == 64); | |
| 116 | pub fn final(d: &Self, out: []u8) void { | |
| 117 | debug.assert(out.len >= out_len / 8); | |
| 113 | 118 | |
| 114 | var m: [16]u32 = undefined; | |
| 115 | var v: [16]u32 = undefined; | |
| 119 | mem.set(u8, d.buf[d.buf_len..], 0); | |
| 120 | d.t += d.buf_len; | |
| 121 | d.round(d.buf[0..], true); | |
| 116 | 122 | |
| 117 | for (m) |*r, i| { | |
| 118 | *r = mem.readIntLE(u32, b[4*i .. 4*i + 4]); | |
| 119 | } | |
| 123 | const rr = d.h[0..out_len / 32]; | |
| 120 | 124 | |
| 121 | var k: usize = 0; | |
| 122 | while (k < 8) : (k += 1) { | |
| 123 | v[k] = d.h[k]; | |
| 124 | v[k+8] = iv[k]; | |
| 125 | for (rr) |s, j| { | |
| 126 | mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Little); | |
| 127 | } | |
| 125 | 128 | } |
| 126 | 129 | |
| 127 | v[12] ^= @truncate(u32, d.t); | |
| 128 | v[13] ^= u32(d.t >> 32); | |
| 129 | if (last) v[14] = ~v[14]; | |
| 130 | ||
| 131 | const rounds = comptime []RoundParam { | |
| 132 | Rp(0, 4, 8, 12, 0, 1), | |
| 133 | Rp(1, 5, 9, 13, 2, 3), | |
| 134 | Rp(2, 6, 10, 14, 4, 5), | |
| 135 | Rp(3, 7, 11, 15, 6, 7), | |
| 136 | Rp(0, 5, 10, 15, 8, 9), | |
| 137 | Rp(1, 6, 11, 12, 10, 11), | |
| 138 | Rp(2, 7, 8, 13, 12, 13), | |
| 139 | Rp(3, 4, 9, 14, 14, 15), | |
| 140 | }; | |
| 130 | fn round(d: &Self, b: []const u8, last: bool) void { | |
| 131 | debug.assert(b.len == 64); | |
| 141 | 132 | |
| 142 | comptime var j: usize = 0; | |
| 143 | inline while (j < 10) : (j += 1) { | |
| 144 | inline for (rounds) |r| { | |
| 145 | v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; | |
| 146 | v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16)); | |
| 147 | v[r.c] = v[r.c] +% v[r.d]; | |
| 148 | v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12)); | |
| 149 | v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; | |
| 150 | v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8)); | |
| 151 | v[r.c] = v[r.c] +% v[r.d]; | |
| 152 | v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7)); | |
| 133 | var m: [16]u32 = undefined; | |
| 134 | var v: [16]u32 = undefined; | |
| 135 | ||
| 136 | for (m) |*r, i| { | |
| 137 | r.* = mem.readIntLE(u32, b[4 * i..4 * i + 4]); | |
| 153 | 138 | } |
| 154 | } | |
| 155 | 139 | |
| 156 | for (d.h) |*r, i| { | |
| 157 | *r ^= v[i] ^ v[i + 8]; | |
| 140 | var k: usize = 0; | |
| 141 | while (k < 8) : (k += 1) { | |
| 142 | v[k] = d.h[k]; | |
| 143 | v[k + 8] = iv[k]; | |
| 144 | } | |
| 145 | ||
| 146 | v[12] ^= @truncate(u32, d.t); | |
| 147 | v[13] ^= u32(d.t >> 32); | |
| 148 | if (last) v[14] = ~v[14]; | |
| 149 | ||
| 150 | const rounds = comptime []RoundParam{ | |
| 151 | Rp(0, 4, 8, 12, 0, 1), | |
| 152 | Rp(1, 5, 9, 13, 2, 3), | |
| 153 | Rp(2, 6, 10, 14, 4, 5), | |
| 154 | Rp(3, 7, 11, 15, 6, 7), | |
| 155 | Rp(0, 5, 10, 15, 8, 9), | |
| 156 | Rp(1, 6, 11, 12, 10, 11), | |
| 157 | Rp(2, 7, 8, 13, 12, 13), | |
| 158 | Rp(3, 4, 9, 14, 14, 15), | |
| 159 | }; | |
| 160 | ||
| 161 | comptime var j: usize = 0; | |
| 162 | inline while (j < 10) : (j += 1) { | |
| 163 | inline for (rounds) |r| { | |
| 164 | v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; | |
| 165 | v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16)); | |
| 166 | v[r.c] = v[r.c] +% v[r.d]; | |
| 167 | v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12)); | |
| 168 | v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; | |
| 169 | v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8)); | |
| 170 | v[r.c] = v[r.c] +% v[r.d]; | |
| 171 | v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7)); | |
| 172 | } | |
| 173 | } | |
| 174 | ||
| 175 | for (d.h) |*r, i| { | |
| 176 | r.* ^= v[i] ^ v[i + 8]; | |
| 177 | } | |
| 158 | 178 | } |
| 159 | } | |
| 160 | };} | |
| 179 | }; | |
| 180 | } | |
| 161 | 181 | |
| 162 | 182 | test "blake2s224 single" { |
| 163 | 183 | const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4"; |
| ... | ... | @@ -230,7 +250,7 @@ test "blake2s256 streaming" { |
| 230 | 250 | } |
| 231 | 251 | |
| 232 | 252 | test "blake2s256 aligned final" { |
| 233 | var block = []u8 {0} ** Blake2s256.block_size; | |
| 253 | var block = []u8{0} ** Blake2s256.block_size; | |
| 234 | 254 | var out: [Blake2s256.digest_size]u8 = undefined; |
| 235 | 255 | |
| 236 | 256 | var h = Blake2s256.init(); |
| ... | ... | @@ -238,154 +258,363 @@ test "blake2s256 aligned final" { |
| 238 | 258 | h.final(out[0..]); |
| 239 | 259 | } |
| 240 | 260 | |
| 241 | ||
| 242 | 261 | ///////////////////// |
| 243 | 262 | // Blake2b |
| 244 | 263 | |
| 245 | 264 | pub const Blake2b384 = Blake2b(384); |
| 246 | 265 | pub const Blake2b512 = Blake2b(512); |
| 247 | 266 | |
| 248 | fn Blake2b(comptime out_len: usize) type { return struct { | |
| 249 | const Self = this; | |
| 250 | const block_size = 128; | |
| 251 | const digest_size = out_len / 8; | |
| 267 | fn Blake2b(comptime out_len: usize) type { | |
| 268 | return struct { | |
| 269 | const Self = this; | |
| 270 | const block_size = 128; | |
| 271 | const digest_size = out_len / 8; | |
| 272 | ||
| 273 | const iv = [8]u64{ | |
| 274 | 0x6a09e667f3bcc908, | |
| 275 | 0xbb67ae8584caa73b, | |
| 276 | 0x3c6ef372fe94f82b, | |
| 277 | 0xa54ff53a5f1d36f1, | |
| 278 | 0x510e527fade682d1, | |
| 279 | 0x9b05688c2b3e6c1f, | |
| 280 | 0x1f83d9abfb41bd6b, | |
| 281 | 0x5be0cd19137e2179, | |
| 282 | }; | |
| 252 | 283 | |
| 253 | const iv = [8]u64 { | |
| 254 | 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, | |
| 255 | 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, | |
| 256 | 0x510e527fade682d1, 0x9b05688c2b3e6c1f, | |
| 257 | 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, | |
| 258 | }; | |
| 284 | const sigma = [12][16]u8{ | |
| 285 | []const u8{ | |
| 286 | 0, | |
| 287 | 1, | |
| 288 | 2, | |
| 289 | 3, | |
| 290 | 4, | |
| 291 | 5, | |
| 292 | 6, | |
| 293 | 7, | |
| 294 | 8, | |
| 295 | 9, | |
| 296 | 10, | |
| 297 | 11, | |
| 298 | 12, | |
| 299 | 13, | |
| 300 | 14, | |
| 301 | 15, | |
| 302 | }, | |
| 303 | []const u8{ | |
| 304 | 14, | |
| 305 | 10, | |
| 306 | 4, | |
| 307 | 8, | |
| 308 | 9, | |
| 309 | 15, | |
| 310 | 13, | |
| 311 | 6, | |
| 312 | 1, | |
| 313 | 12, | |
| 314 | 0, | |
| 315 | 2, | |
| 316 | 11, | |
| 317 | 7, | |
| 318 | 5, | |
| 319 | 3, | |
| 320 | }, | |
| 321 | []const u8{ | |
| 322 | 11, | |
| 323 | 8, | |
| 324 | 12, | |
| 325 | 0, | |
| 326 | 5, | |
| 327 | 2, | |
| 328 | 15, | |
| 329 | 13, | |
| 330 | 10, | |
| 331 | 14, | |
| 332 | 3, | |
| 333 | 6, | |
| 334 | 7, | |
| 335 | 1, | |
| 336 | 9, | |
| 337 | 4, | |
| 338 | }, | |
| 339 | []const u8{ | |
| 340 | 7, | |
| 341 | 9, | |
| 342 | 3, | |
| 343 | 1, | |
| 344 | 13, | |
| 345 | 12, | |
| 346 | 11, | |
| 347 | 14, | |
| 348 | 2, | |
| 349 | 6, | |
| 350 | 5, | |
| 351 | 10, | |
| 352 | 4, | |
| 353 | 0, | |
| 354 | 15, | |
| 355 | 8, | |
| 356 | }, | |
| 357 | []const u8{ | |
| 358 | 9, | |
| 359 | 0, | |
| 360 | 5, | |
| 361 | 7, | |
| 362 | 2, | |
| 363 | 4, | |
| 364 | 10, | |
| 365 | 15, | |
| 366 | 14, | |
| 367 | 1, | |
| 368 | 11, | |
| 369 | 12, | |
| 370 | 6, | |
| 371 | 8, | |
| 372 | 3, | |
| 373 | 13, | |
| 374 | }, | |
| 375 | []const u8{ | |
| 376 | 2, | |
| 377 | 12, | |
| 378 | 6, | |
| 379 | 10, | |
| 380 | 0, | |
| 381 | 11, | |
| 382 | 8, | |
| 383 | 3, | |
| 384 | 4, | |
| 385 | 13, | |
| 386 | 7, | |
| 387 | 5, | |
| 388 | 15, | |
| 389 | 14, | |
| 390 | 1, | |
| 391 | 9, | |
| 392 | }, | |
| 393 | []const u8{ | |
| 394 | 12, | |
| 395 | 5, | |
| 396 | 1, | |
| 397 | 15, | |
| 398 | 14, | |
| 399 | 13, | |
| 400 | 4, | |
| 401 | 10, | |
| 402 | 0, | |
| 403 | 7, | |
| 404 | 6, | |
| 405 | 3, | |
| 406 | 9, | |
| 407 | 2, | |
| 408 | 8, | |
| 409 | 11, | |
| 410 | }, | |
| 411 | []const u8{ | |
| 412 | 13, | |
| 413 | 11, | |
| 414 | 7, | |
| 415 | 14, | |
| 416 | 12, | |
| 417 | 1, | |
| 418 | 3, | |
| 419 | 9, | |
| 420 | 5, | |
| 421 | 0, | |
| 422 | 15, | |
| 423 | 4, | |
| 424 | 8, | |
| 425 | 6, | |
| 426 | 2, | |
| 427 | 10, | |
| 428 | }, | |
| 429 | []const u8{ | |
| 430 | 6, | |
| 431 | 15, | |
| 432 | 14, | |
| 433 | 9, | |
| 434 | 11, | |
| 435 | 3, | |
| 436 | 0, | |
| 437 | 8, | |
| 438 | 12, | |
| 439 | 2, | |
| 440 | 13, | |
| 441 | 7, | |
| 442 | 1, | |
| 443 | 4, | |
| 444 | 10, | |
| 445 | 5, | |
| 446 | }, | |
| 447 | []const u8{ | |
| 448 | 10, | |
| 449 | 2, | |
| 450 | 8, | |
| 451 | 4, | |
| 452 | 7, | |
| 453 | 6, | |
| 454 | 1, | |
| 455 | 5, | |
| 456 | 15, | |
| 457 | 11, | |
| 458 | 9, | |
| 459 | 14, | |
| 460 | 3, | |
| 461 | 12, | |
| 462 | 13, | |
| 463 | 0, | |
| 464 | }, | |
| 465 | []const u8{ | |
| 466 | 0, | |
| 467 | 1, | |
| 468 | 2, | |
| 469 | 3, | |
| 470 | 4, | |
| 471 | 5, | |
| 472 | 6, | |
| 473 | 7, | |
| 474 | 8, | |
| 475 | 9, | |
| 476 | 10, | |
| 477 | 11, | |
| 478 | 12, | |
| 479 | 13, | |
| 480 | 14, | |
| 481 | 15, | |
| 482 | }, | |
| 483 | []const u8{ | |
| 484 | 14, | |
| 485 | 10, | |
| 486 | 4, | |
| 487 | 8, | |
| 488 | 9, | |
| 489 | 15, | |
| 490 | 13, | |
| 491 | 6, | |
| 492 | 1, | |
| 493 | 12, | |
| 494 | 0, | |
| 495 | 2, | |
| 496 | 11, | |
| 497 | 7, | |
| 498 | 5, | |
| 499 | 3, | |
| 500 | }, | |
| 501 | }; | |
| 259 | 502 | |
| 260 | const sigma = [12][16]u8 { | |
| 261 | []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, | |
| 262 | []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, | |
| 263 | []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, | |
| 264 | []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, | |
| 265 | []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, | |
| 266 | []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, | |
| 267 | []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, | |
| 268 | []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, | |
| 269 | []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, | |
| 270 | []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 }, | |
| 271 | []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, | |
| 272 | []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, | |
| 273 | }; | |
| 503 | h: [8]u64, | |
| 504 | t: u128, | |
| 505 | // Streaming cache | |
| 506 | buf: [128]u8, | |
| 507 | buf_len: u8, | |
| 274 | 508 | |
| 275 | h: [8]u64, | |
| 276 | t: u128, | |
| 277 | // Streaming cache | |
| 278 | buf: [128]u8, | |
| 279 | buf_len: u8, | |
| 280 | ||
| 281 | pub fn init() Self { | |
| 282 | debug.assert(8 <= out_len and out_len <= 512); | |
| 283 | ||
| 284 | var s: Self = undefined; | |
| 285 | s.reset(); | |
| 286 | return s; | |
| 287 | } | |
| 288 | ||
| 289 | pub fn reset(d: &Self) void { | |
| 290 | mem.copy(u64, d.h[0..], iv[0..]); | |
| 291 | ||
| 292 | // No key plus default parameters | |
| 293 | d.h[0] ^= 0x01010000 ^ (out_len >> 3); | |
| 294 | d.t = 0; | |
| 295 | d.buf_len = 0; | |
| 296 | } | |
| 297 | ||
| 298 | pub fn hash(b: []const u8, out: []u8) void { | |
| 299 | var d = Self.init(); | |
| 300 | d.update(b); | |
| 301 | d.final(out); | |
| 302 | } | |
| 303 | ||
| 304 | pub fn update(d: &Self, b: []const u8) void { | |
| 305 | var off: usize = 0; | |
| 306 | ||
| 307 | // Partial buffer exists from previous update. Copy into buffer then hash. | |
| 308 | if (d.buf_len != 0 and d.buf_len + b.len > 128) { | |
| 309 | off += 128 - d.buf_len; | |
| 310 | mem.copy(u8, d.buf[d.buf_len..], b[0..off]); | |
| 311 | d.t += 128; | |
| 312 | d.round(d.buf[0..], false); | |
| 509 | pub fn init() Self { | |
| 510 | debug.assert(8 <= out_len and out_len <= 512); | |
| 511 | ||
| 512 | var s: Self = undefined; | |
| 513 | s.reset(); | |
| 514 | return s; | |
| 515 | } | |
| 516 | ||
| 517 | pub fn reset(d: &Self) void { | |
| 518 | mem.copy(u64, d.h[0..], iv[0..]); | |
| 519 | ||
| 520 | // No key plus default parameters | |
| 521 | d.h[0] ^= 0x01010000 ^ (out_len >> 3); | |
| 522 | d.t = 0; | |
| 313 | 523 | d.buf_len = 0; |
| 314 | 524 | } |
| 315 | 525 | |
| 316 | // Full middle blocks. | |
| 317 | while (off + 128 <= b.len) : (off += 128) { | |
| 318 | d.t += 128; | |
| 319 | d.round(b[off..off + 128], false); | |
| 526 | pub fn hash(b: []const u8, out: []u8) void { | |
| 527 | var d = Self.init(); | |
| 528 | d.update(b); | |
| 529 | d.final(out); | |
| 320 | 530 | } |
| 321 | 531 | |
| 322 | // Copy any remainder for next pass. | |
| 323 | mem.copy(u8, d.buf[d.buf_len..], b[off..]); | |
| 324 | d.buf_len += u8(b[off..].len); | |
| 325 | } | |
| 532 | pub fn update(d: &Self, b: []const u8) void { | |
| 533 | var off: usize = 0; | |
| 326 | 534 | |
| 327 | pub fn final(d: &Self, out: []u8) void { | |
| 328 | mem.set(u8, d.buf[d.buf_len..], 0); | |
| 329 | d.t += d.buf_len; | |
| 330 | d.round(d.buf[0..], true); | |
| 535 | // Partial buffer exists from previous update. Copy into buffer then hash. | |
| 536 | if (d.buf_len != 0 and d.buf_len + b.len > 128) { | |
| 537 | off += 128 - d.buf_len; | |
| 538 | mem.copy(u8, d.buf[d.buf_len..], b[0..off]); | |
| 539 | d.t += 128; | |
| 540 | d.round(d.buf[0..], false); | |
| 541 | d.buf_len = 0; | |
| 542 | } | |
| 331 | 543 | |
| 332 | const rr = d.h[0 .. out_len / 64]; | |
| 544 | // Full middle blocks. | |
| 545 | while (off + 128 <= b.len) : (off += 128) { | |
| 546 | d.t += 128; | |
| 547 | d.round(b[off..off + 128], false); | |
| 548 | } | |
| 333 | 549 | |
| 334 | for (rr) |s, j| { | |
| 335 | mem.writeInt(out[8*j .. 8*j + 8], s, builtin.Endian.Little); | |
| 550 | // Copy any remainder for next pass. | |
| 551 | mem.copy(u8, d.buf[d.buf_len..], b[off..]); | |
| 552 | d.buf_len += u8(b[off..].len); | |
| 336 | 553 | } |
| 337 | } | |
| 338 | 554 | |
| 339 | fn round(d: &Self, b: []const u8, last: bool) void { | |
| 340 | debug.assert(b.len == 128); | |
| 555 | pub fn final(d: &Self, out: []u8) void { | |
| 556 | mem.set(u8, d.buf[d.buf_len..], 0); | |
| 557 | d.t += d.buf_len; | |
| 558 | d.round(d.buf[0..], true); | |
| 341 | 559 | |
| 342 | var m: [16]u64 = undefined; | |
| 343 | var v: [16]u64 = undefined; | |
| 560 | const rr = d.h[0..out_len / 64]; | |
| 344 | 561 | |
| 345 | for (m) |*r, i| { | |
| 346 | *r = mem.readIntLE(u64, b[8*i .. 8*i + 8]); | |
| 562 | for (rr) |s, j| { | |
| 563 | mem.writeInt(out[8 * j..8 * j + 8], s, builtin.Endian.Little); | |
| 564 | } | |
| 347 | 565 | } |
| 348 | 566 | |
| 349 | var k: usize = 0; | |
| 350 | while (k < 8) : (k += 1) { | |
| 351 | v[k] = d.h[k]; | |
| 352 | v[k+8] = iv[k]; | |
| 353 | } | |
| 567 | fn round(d: &Self, b: []const u8, last: bool) void { | |
| 568 | debug.assert(b.len == 128); | |
| 354 | 569 | |
| 355 | v[12] ^= @truncate(u64, d.t); | |
| 356 | v[13] ^= u64(d.t >> 64); | |
| 357 | if (last) v[14] = ~v[14]; | |
| 358 | ||
| 359 | const rounds = comptime []RoundParam { | |
| 360 | Rp(0, 4, 8, 12, 0, 1), | |
| 361 | Rp(1, 5, 9, 13, 2, 3), | |
| 362 | Rp(2, 6, 10, 14, 4, 5), | |
| 363 | Rp(3, 7, 11, 15, 6, 7), | |
| 364 | Rp(0, 5, 10, 15, 8, 9), | |
| 365 | Rp(1, 6, 11, 12, 10, 11), | |
| 366 | Rp(2, 7, 8, 13, 12, 13), | |
| 367 | Rp(3, 4, 9, 14, 14, 15), | |
| 368 | }; | |
| 570 | var m: [16]u64 = undefined; | |
| 571 | var v: [16]u64 = undefined; | |
| 369 | 572 | |
| 370 | comptime var j: usize = 0; | |
| 371 | inline while (j < 12) : (j += 1) { | |
| 372 | inline for (rounds) |r| { | |
| 373 | v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; | |
| 374 | v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32)); | |
| 375 | v[r.c] = v[r.c] +% v[r.d]; | |
| 376 | v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24)); | |
| 377 | v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; | |
| 378 | v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16)); | |
| 379 | v[r.c] = v[r.c] +% v[r.d]; | |
| 380 | v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63)); | |
| 573 | for (m) |*r, i| { | |
| 574 | r.* = mem.readIntLE(u64, b[8 * i..8 * i + 8]); | |
| 575 | } | |
| 576 | ||
| 577 | var k: usize = 0; | |
| 578 | while (k < 8) : (k += 1) { | |
| 579 | v[k] = d.h[k]; | |
| 580 | v[k + 8] = iv[k]; | |
| 381 | 581 | } |
| 382 | } | |
| 383 | 582 | |
| 384 | for (d.h) |*r, i| { | |
| 385 | *r ^= v[i] ^ v[i + 8]; | |
| 583 | v[12] ^= @truncate(u64, d.t); | |
| 584 | v[13] ^= u64(d.t >> 64); | |
| 585 | if (last) v[14] = ~v[14]; | |
| 586 | ||
| 587 | const rounds = comptime []RoundParam{ | |
| 588 | Rp(0, 4, 8, 12, 0, 1), | |
| 589 | Rp(1, 5, 9, 13, 2, 3), | |
| 590 | Rp(2, 6, 10, 14, 4, 5), | |
| 591 | Rp(3, 7, 11, 15, 6, 7), | |
| 592 | Rp(0, 5, 10, 15, 8, 9), | |
| 593 | Rp(1, 6, 11, 12, 10, 11), | |
| 594 | Rp(2, 7, 8, 13, 12, 13), | |
| 595 | Rp(3, 4, 9, 14, 14, 15), | |
| 596 | }; | |
| 597 | ||
| 598 | comptime var j: usize = 0; | |
| 599 | inline while (j < 12) : (j += 1) { | |
| 600 | inline for (rounds) |r| { | |
| 601 | v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; | |
| 602 | v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32)); | |
| 603 | v[r.c] = v[r.c] +% v[r.d]; | |
| 604 | v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24)); | |
| 605 | v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; | |
| 606 | v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16)); | |
| 607 | v[r.c] = v[r.c] +% v[r.d]; | |
| 608 | v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63)); | |
| 609 | } | |
| 610 | } | |
| 611 | ||
| 612 | for (d.h) |*r, i| { | |
| 613 | r.* ^= v[i] ^ v[i + 8]; | |
| 614 | } | |
| 386 | 615 | } |
| 387 | } | |
| 388 | };} | |
| 616 | }; | |
| 617 | } | |
| 389 | 618 | |
| 390 | 619 | test "blake2b384 single" { |
| 391 | 620 | const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100"; |
| ... | ... | @@ -458,7 +687,7 @@ test "blake2b512 streaming" { |
| 458 | 687 | } |
| 459 | 688 | |
| 460 | 689 | test "blake2b512 aligned final" { |
| 461 | var block = []u8 {0} ** Blake2b512.block_size; | |
| 690 | var block = []u8{0} ** Blake2b512.block_size; | |
| 462 | 691 | var out: [Blake2b512.digest_size]u8 = undefined; |
| 463 | 692 | |
| 464 | 693 | var h = Blake2b512.init(); |
std/crypto/hmac.zig+2-2| ... | ... | @@ -29,12 +29,12 @@ pub fn Hmac(comptime H: type) type { |
| 29 | 29 | |
| 30 | 30 | var o_key_pad: [H.block_size]u8 = undefined; |
| 31 | 31 | for (o_key_pad) |*b, i| { |
| 32 | *b = scratch[i] ^ 0x5c; | |
| 32 | b.* = scratch[i] ^ 0x5c; | |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | var i_key_pad: [H.block_size]u8 = undefined; |
| 36 | 36 | for (i_key_pad) |*b, i| { |
| 37 | *b = scratch[i] ^ 0x36; | |
| 37 | b.* = scratch[i] ^ 0x36; | |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | // HMAC(k, m) = H(o_key_pad | H(i_key_pad | message)) where | is concatenation |
std/crypto/sha3.zig+180-101| ... | ... | @@ -10,148 +10,228 @@ pub const Sha3_256 = Keccak(256, 0x06); |
| 10 | 10 | pub const Sha3_384 = Keccak(384, 0x06); |
| 11 | 11 | pub const Sha3_512 = Keccak(512, 0x06); |
| 12 | 12 | |
| 13 | fn Keccak(comptime bits: usize, comptime delim: u8) type { return struct { | |
| 14 | const Self = this; | |
| 15 | const block_size = 200; | |
| 16 | const digest_size = bits / 8; | |
| 17 | ||
| 18 | s: [200]u8, | |
| 19 | offset: usize, | |
| 20 | rate: usize, | |
| 21 | ||
| 22 | pub fn init() Self { | |
| 23 | var d: Self = undefined; | |
| 24 | d.reset(); | |
| 25 | return d; | |
| 26 | } | |
| 13 | fn Keccak(comptime bits: usize, comptime delim: u8) type { | |
| 14 | return struct { | |
| 15 | const Self = this; | |
| 16 | const block_size = 200; | |
| 17 | const digest_size = bits / 8; | |
| 18 | ||
| 19 | s: [200]u8, | |
| 20 | offset: usize, | |
| 21 | rate: usize, | |
| 22 | ||
| 23 | pub fn init() Self { | |
| 24 | var d: Self = undefined; | |
| 25 | d.reset(); | |
| 26 | return d; | |
| 27 | } | |
| 27 | 28 | |
| 28 | pub fn reset(d: &Self) void { | |
| 29 | mem.set(u8, d.s[0..], 0); | |
| 30 | d.offset = 0; | |
| 31 | d.rate = 200 - (bits / 4); | |
| 32 | } | |
| 29 | pub fn reset(d: &Self) void { | |
| 30 | mem.set(u8, d.s[0..], 0); | |
| 31 | d.offset = 0; | |
| 32 | d.rate = 200 - (bits / 4); | |
| 33 | } | |
| 33 | 34 | |
| 34 | pub fn hash(b: []const u8, out: []u8) void { | |
| 35 | var d = Self.init(); | |
| 36 | d.update(b); | |
| 37 | d.final(out); | |
| 38 | } | |
| 35 | pub fn hash(b: []const u8, out: []u8) void { | |
| 36 | var d = Self.init(); | |
| 37 | d.update(b); | |
| 38 | d.final(out); | |
| 39 | } | |
| 39 | 40 | |
| 40 | pub fn update(d: &Self, b: []const u8) void { | |
| 41 | var ip: usize = 0; | |
| 42 | var len = b.len; | |
| 43 | var rate = d.rate - d.offset; | |
| 44 | var offset = d.offset; | |
| 41 | pub fn update(d: &Self, b: []const u8) void { | |
| 42 | var ip: usize = 0; | |
| 43 | var len = b.len; | |
| 44 | var rate = d.rate - d.offset; | |
| 45 | var offset = d.offset; | |
| 45 | 46 | |
| 46 | // absorb | |
| 47 | while (len >= rate) { | |
| 48 | for (d.s[offset .. offset + rate]) |*r, i| | |
| 49 | *r ^= b[ip..][i]; | |
| 47 | // absorb | |
| 48 | while (len >= rate) { | |
| 49 | for (d.s[offset..offset + rate]) |*r, i| | |
| 50 | r.* ^= b[ip..][i]; | |
| 50 | 51 | |
| 51 | keccak_f(1600, d.s[0..]); | |
| 52 | keccak_f(1600, d.s[0..]); | |
| 52 | 53 | |
| 53 | ip += rate; | |
| 54 | len -= rate; | |
| 55 | rate = d.rate; | |
| 56 | offset = 0; | |
| 57 | } | |
| 54 | ip += rate; | |
| 55 | len -= rate; | |
| 56 | rate = d.rate; | |
| 57 | offset = 0; | |
| 58 | } | |
| 58 | 59 | |
| 59 | for (d.s[offset .. offset + len]) |*r, i| | |
| 60 | *r ^= b[ip..][i]; | |
| 60 | for (d.s[offset..offset + len]) |*r, i| | |
| 61 | r.* ^= b[ip..][i]; | |
| 61 | 62 | |
| 62 | d.offset = offset + len; | |
| 63 | } | |
| 63 | d.offset = offset + len; | |
| 64 | } | |
| 64 | 65 | |
| 65 | pub fn final(d: &Self, out: []u8) void { | |
| 66 | // padding | |
| 67 | d.s[d.offset] ^= delim; | |
| 68 | d.s[d.rate - 1] ^= 0x80; | |
| 66 | pub fn final(d: &Self, out: []u8) void { | |
| 67 | // padding | |
| 68 | d.s[d.offset] ^= delim; | |
| 69 | d.s[d.rate - 1] ^= 0x80; | |
| 69 | 70 | |
| 70 | keccak_f(1600, d.s[0..]); | |
| 71 | keccak_f(1600, d.s[0..]); | |
| 71 | 72 | |
| 72 | // squeeze | |
| 73 | var op: usize = 0; | |
| 74 | var len: usize = bits / 8; | |
| 73 | // squeeze | |
| 74 | var op: usize = 0; | |
| 75 | var len: usize = bits / 8; | |
| 75 | 76 | |
| 76 | while (len >= d.rate) { | |
| 77 | mem.copy(u8, out[op..], d.s[0..d.rate]); | |
| 78 | keccak_f(1600, d.s[0..]); | |
| 79 | op += d.rate; | |
| 80 | len -= d.rate; | |
| 77 | while (len >= d.rate) { | |
| 78 | mem.copy(u8, out[op..], d.s[0..d.rate]); | |
| 79 | keccak_f(1600, d.s[0..]); | |
| 80 | op += d.rate; | |
| 81 | len -= d.rate; | |
| 82 | } | |
| 83 | ||
| 84 | mem.copy(u8, out[op..], d.s[0..len]); | |
| 81 | 85 | } |
| 86 | }; | |
| 87 | } | |
| 82 | 88 | |
| 83 | mem.copy(u8, out[op..], d.s[0..len]); | |
| 84 | } | |
| 85 | };} | |
| 86 | ||
| 87 | const RC = []const u64 { | |
| 88 | 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000, | |
| 89 | 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, | |
| 90 | 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, | |
| 91 | 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003, | |
| 92 | 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a, | |
| 93 | 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, | |
| 89 | const RC = []const u64{ | |
| 90 | 0x0000000000000001, | |
| 91 | 0x0000000000008082, | |
| 92 | 0x800000000000808a, | |
| 93 | 0x8000000080008000, | |
| 94 | 0x000000000000808b, | |
| 95 | 0x0000000080000001, | |
| 96 | 0x8000000080008081, | |
| 97 | 0x8000000000008009, | |
| 98 | 0x000000000000008a, | |
| 99 | 0x0000000000000088, | |
| 100 | 0x0000000080008009, | |
| 101 | 0x000000008000000a, | |
| 102 | 0x000000008000808b, | |
| 103 | 0x800000000000008b, | |
| 104 | 0x8000000000008089, | |
| 105 | 0x8000000000008003, | |
| 106 | 0x8000000000008002, | |
| 107 | 0x8000000000000080, | |
| 108 | 0x000000000000800a, | |
| 109 | 0x800000008000000a, | |
| 110 | 0x8000000080008081, | |
| 111 | 0x8000000000008080, | |
| 112 | 0x0000000080000001, | |
| 113 | 0x8000000080008008, | |
| 94 | 114 | }; |
| 95 | 115 | |
| 96 | const ROTC = []const usize { | |
| 97 | 1, 3, 6, 10, 15, 21, 28, 36, | |
| 98 | 45, 55, 2, 14, 27, 41, 56, 8, | |
| 99 | 25, 43, 62, 18, 39, 61, 20, 44 | |
| 116 | const ROTC = []const usize{ | |
| 117 | 1, | |
| 118 | 3, | |
| 119 | 6, | |
| 120 | 10, | |
| 121 | 15, | |
| 122 | 21, | |
| 123 | 28, | |
| 124 | 36, | |
| 125 | 45, | |
| 126 | 55, | |
| 127 | 2, | |
| 128 | 14, | |
| 129 | 27, | |
| 130 | 41, | |
| 131 | 56, | |
| 132 | 8, | |
| 133 | 25, | |
| 134 | 43, | |
| 135 | 62, | |
| 136 | 18, | |
| 137 | 39, | |
| 138 | 61, | |
| 139 | 20, | |
| 140 | 44, | |
| 100 | 141 | }; |
| 101 | 142 | |
| 102 | const PIL = []const usize { | |
| 103 | 10, 7, 11, 17, 18, 3, 5, 16, | |
| 104 | 8, 21, 24, 4, 15, 23, 19, 13, | |
| 105 | 12, 2, 20, 14, 22, 9, 6, 1 | |
| 143 | const PIL = []const usize{ | |
| 144 | 10, | |
| 145 | 7, | |
| 146 | 11, | |
| 147 | 17, | |
| 148 | 18, | |
| 149 | 3, | |
| 150 | 5, | |
| 151 | 16, | |
| 152 | 8, | |
| 153 | 21, | |
| 154 | 24, | |
| 155 | 4, | |
| 156 | 15, | |
| 157 | 23, | |
| 158 | 19, | |
| 159 | 13, | |
| 160 | 12, | |
| 161 | 2, | |
| 162 | 20, | |
| 163 | 14, | |
| 164 | 22, | |
| 165 | 9, | |
| 166 | 6, | |
| 167 | 1, | |
| 106 | 168 | }; |
| 107 | 169 | |
| 108 | const M5 = []const usize { | |
| 109 | 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 | |
| 170 | const M5 = []const usize{ | |
| 171 | 0, | |
| 172 | 1, | |
| 173 | 2, | |
| 174 | 3, | |
| 175 | 4, | |
| 176 | 0, | |
| 177 | 1, | |
| 178 | 2, | |
| 179 | 3, | |
| 180 | 4, | |
| 110 | 181 | }; |
| 111 | 182 | |
| 112 | 183 | fn keccak_f(comptime F: usize, d: []u8) void { |
| 113 | 184 | debug.assert(d.len == F / 8); |
| 114 | 185 | |
| 115 | 186 | const B = F / 25; |
| 116 | const no_rounds = comptime x: { break :x 12 + 2 * math.log2(B); }; | |
| 187 | const no_rounds = comptime x: { | |
| 188 | break :x 12 + 2 * math.log2(B); | |
| 189 | }; | |
| 117 | 190 | |
| 118 | var s = []const u64 {0} ** 25; | |
| 119 | var t = []const u64 {0} ** 1; | |
| 120 | var c = []const u64 {0} ** 5; | |
| 191 | var s = []const u64{0} ** 25; | |
| 192 | var t = []const u64{0} ** 1; | |
| 193 | var c = []const u64{0} ** 5; | |
| 121 | 194 | |
| 122 | 195 | for (s) |*r, i| { |
| 123 | *r = mem.readIntLE(u64, d[8*i .. 8*i + 8]); | |
| 196 | r.* = mem.readIntLE(u64, d[8 * i..8 * i + 8]); | |
| 124 | 197 | } |
| 125 | 198 | |
| 126 | 199 | comptime var x: usize = 0; |
| 127 | 200 | comptime var y: usize = 0; |
| 128 | 201 | for (RC[0..no_rounds]) |round| { |
| 129 | 202 | // theta |
| 130 | x = 0; inline while (x < 5) : (x += 1) { | |
| 131 | c[x] = s[x] ^ s[x+5] ^ s[x+10] ^ s[x+15] ^ s[x+20]; | |
| 203 | x = 0; | |
| 204 | inline while (x < 5) : (x += 1) { | |
| 205 | c[x] = s[x] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20]; | |
| 132 | 206 | } |
| 133 | x = 0; inline while (x < 5) : (x += 1) { | |
| 134 | t[0] = c[M5[x+4]] ^ math.rotl(u64, c[M5[x+1]], usize(1)); | |
| 135 | y = 0; inline while (y < 5) : (y += 1) { | |
| 136 | s[x + y*5] ^= t[0]; | |
| 207 | x = 0; | |
| 208 | inline while (x < 5) : (x += 1) { | |
| 209 | t[0] = c[M5[x + 4]] ^ math.rotl(u64, c[M5[x + 1]], usize(1)); | |
| 210 | y = 0; | |
| 211 | inline while (y < 5) : (y += 1) { | |
| 212 | s[x + y * 5] ^= t[0]; | |
| 137 | 213 | } |
| 138 | 214 | } |
| 139 | 215 | |
| 140 | 216 | // rho+pi |
| 141 | 217 | t[0] = s[1]; |
| 142 | x = 0; inline while (x < 24) : (x += 1) { | |
| 218 | x = 0; | |
| 219 | inline while (x < 24) : (x += 1) { | |
| 143 | 220 | c[0] = s[PIL[x]]; |
| 144 | 221 | s[PIL[x]] = math.rotl(u64, t[0], ROTC[x]); |
| 145 | 222 | t[0] = c[0]; |
| 146 | 223 | } |
| 147 | 224 | |
| 148 | 225 | // chi |
| 149 | y = 0; inline while (y < 5) : (y += 1) { | |
| 150 | x = 0; inline while (x < 5) : (x += 1) { | |
| 151 | c[x] = s[x + y*5]; | |
| 226 | y = 0; | |
| 227 | inline while (y < 5) : (y += 1) { | |
| 228 | x = 0; | |
| 229 | inline while (x < 5) : (x += 1) { | |
| 230 | c[x] = s[x + y * 5]; | |
| 152 | 231 | } |
| 153 | x = 0; inline while (x < 5) : (x += 1) { | |
| 154 | s[x + y*5] = c[x] ^ (~c[M5[x+1]] & c[M5[x+2]]); | |
| 232 | x = 0; | |
| 233 | inline while (x < 5) : (x += 1) { | |
| 234 | s[x + y * 5] = c[x] ^ (~c[M5[x + 1]] & c[M5[x + 2]]); | |
| 155 | 235 | } |
| 156 | 236 | } |
| 157 | 237 | |
| ... | ... | @@ -160,11 +240,10 @@ fn keccak_f(comptime F: usize, d: []u8) void { |
| 160 | 240 | } |
| 161 | 241 | |
| 162 | 242 | for (s) |r, i| { |
| 163 | mem.writeInt(d[8*i .. 8*i + 8], r, builtin.Endian.Little); | |
| 243 | mem.writeInt(d[8 * i..8 * i + 8], r, builtin.Endian.Little); | |
| 164 | 244 | } |
| 165 | 245 | } |
| 166 | 246 | |
| 167 | ||
| 168 | 247 | test "sha3-224 single" { |
| 169 | 248 | htest.assertEqualHash(Sha3_224, "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", ""); |
| 170 | 249 | htest.assertEqualHash(Sha3_224, "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", "abc"); |
| ... | ... | @@ -192,7 +271,7 @@ test "sha3-224 streaming" { |
| 192 | 271 | } |
| 193 | 272 | |
| 194 | 273 | test "sha3-256 single" { |
| 195 | htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" , ""); | |
| 274 | htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", ""); | |
| 196 | 275 | htest.assertEqualHash(Sha3_256, "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", "abc"); |
| 197 | 276 | htest.assertEqualHash(Sha3_256, "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); |
| 198 | 277 | } |
| ... | ... | @@ -218,7 +297,7 @@ test "sha3-256 streaming" { |
| 218 | 297 | } |
| 219 | 298 | |
| 220 | 299 | test "sha3-256 aligned final" { |
| 221 | var block = []u8 {0} ** Sha3_256.block_size; | |
| 300 | var block = []u8{0} ** Sha3_256.block_size; | |
| 222 | 301 | var out: [Sha3_256.digest_size]u8 = undefined; |
| 223 | 302 | |
| 224 | 303 | var h = Sha3_256.init(); |
| ... | ... | @@ -228,7 +307,7 @@ test "sha3-256 aligned final" { |
| 228 | 307 | |
| 229 | 308 | test "sha3-384 single" { |
| 230 | 309 | const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"; |
| 231 | htest.assertEqualHash(Sha3_384, h1 , ""); | |
| 310 | htest.assertEqualHash(Sha3_384, h1, ""); | |
| 232 | 311 | const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"; |
| 233 | 312 | htest.assertEqualHash(Sha3_384, h2, "abc"); |
| 234 | 313 | const h3 = "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7"; |
| ... | ... | @@ -259,7 +338,7 @@ test "sha3-384 streaming" { |
| 259 | 338 | |
| 260 | 339 | test "sha3-512 single" { |
| 261 | 340 | const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"; |
| 262 | htest.assertEqualHash(Sha3_512, h1 , ""); | |
| 341 | htest.assertEqualHash(Sha3_512, h1, ""); | |
| 263 | 342 | const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"; |
| 264 | 343 | htest.assertEqualHash(Sha3_512, h2, "abc"); |
| 265 | 344 | const h3 = "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"; |
| ... | ... | @@ -289,7 +368,7 @@ test "sha3-512 streaming" { |
| 289 | 368 | } |
| 290 | 369 | |
| 291 | 370 | test "sha3-512 aligned final" { |
| 292 | var block = []u8 {0} ** Sha3_512.block_size; | |
| 371 | var block = []u8{0} ** Sha3_512.block_size; | |
| 293 | 372 | var out: [Sha3_512.digest_size]u8 = undefined; |
| 294 | 373 | |
| 295 | 374 | var h = Sha3_512.init(); |
std/event.zig+20-33| ... | ... | @@ -6,7 +6,7 @@ const mem = std.mem; |
| 6 | 6 | const posix = std.os.posix; |
| 7 | 7 | |
| 8 | 8 | pub const TcpServer = struct { |
| 9 | handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File) void, | |
| 9 | handleRequestFn: async<&mem.Allocator> fn(&TcpServer, &const std.net.Address, &const std.os.File) void, | |
| 10 | 10 | |
| 11 | 11 | loop: &Loop, |
| 12 | 12 | sockfd: i32, |
| ... | ... | @@ -18,13 +18,11 @@ pub const TcpServer = struct { |
| 18 | 18 | const PromiseNode = std.LinkedList(promise).Node; |
| 19 | 19 | |
| 20 | 20 | pub fn init(loop: &Loop) !TcpServer { |
| 21 | const sockfd = try std.os.posixSocket(posix.AF_INET, | |
| 22 | posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK, | |
| 23 | posix.PROTO_tcp); | |
| 21 | const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp); | |
| 24 | 22 | errdefer std.os.close(sockfd); |
| 25 | 23 | |
| 26 | 24 | // TODO can't initialize handler coroutine here because we need well defined copy elision |
| 27 | return TcpServer { | |
| 25 | return TcpServer{ | |
| 28 | 26 | .loop = loop, |
| 29 | 27 | .sockfd = sockfd, |
| 30 | 28 | .accept_coro = null, |
| ... | ... | @@ -34,9 +32,7 @@ pub const TcpServer = struct { |
| 34 | 32 | }; |
| 35 | 33 | } |
| 36 | 34 | |
| 37 | pub fn listen(self: &TcpServer, address: &const std.net.Address, | |
| 38 | handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File)void) !void | |
| 39 | { | |
| 35 | pub fn listen(self: &TcpServer, address: &const std.net.Address, handleRequestFn: async<&mem.Allocator> fn(&TcpServer, &const std.net.Address, &const std.os.File) void) !void { | |
| 40 | 36 | self.handleRequestFn = handleRequestFn; |
| 41 | 37 | |
| 42 | 38 | try std.os.posixBind(self.sockfd, &address.os_addr); |
| ... | ... | @@ -48,7 +44,6 @@ pub const TcpServer = struct { |
| 48 | 44 | |
| 49 | 45 | try self.loop.addFd(self.sockfd, ??self.accept_coro); |
| 50 | 46 | errdefer self.loop.removeFd(self.sockfd); |
| 51 | ||
| 52 | 47 | } |
| 53 | 48 | |
| 54 | 49 | pub fn deinit(self: &TcpServer) void { |
| ... | ... | @@ -60,9 +55,7 @@ pub const TcpServer = struct { |
| 60 | 55 | pub async fn handler(self: &TcpServer) void { |
| 61 | 56 | while (true) { |
| 62 | 57 | var accepted_addr: std.net.Address = undefined; |
| 63 | if (std.os.posixAccept(self.sockfd, &accepted_addr.os_addr, | |
| 64 | posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| | |
| 65 | { | |
| 58 | if (std.os.posixAccept(self.sockfd, &accepted_addr.os_addr, posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| { | |
| 66 | 59 | var socket = std.os.File.openHandle(accepted_fd); |
| 67 | 60 | _ = async<self.loop.allocator> self.handleRequestFn(self, accepted_addr, socket) catch |err| switch (err) { |
| 68 | 61 | error.OutOfMemory => { |
| ... | ... | @@ -110,7 +103,7 @@ pub const Loop = struct { |
| 110 | 103 | |
| 111 | 104 | fn init(allocator: &mem.Allocator) !Loop { |
| 112 | 105 | const epollfd = try std.os.linuxEpollCreate(std.os.linux.EPOLL_CLOEXEC); |
| 113 | return Loop { | |
| 106 | return Loop{ | |
| 114 | 107 | .keep_running = true, |
| 115 | 108 | .allocator = allocator, |
| 116 | 109 | .epollfd = epollfd, |
| ... | ... | @@ -118,11 +111,9 @@ pub const Loop = struct { |
| 118 | 111 | } |
| 119 | 112 | |
| 120 | 113 | pub fn addFd(self: &Loop, fd: i32, prom: promise) !void { |
| 121 | var ev = std.os.linux.epoll_event { | |
| 122 | .events = std.os.linux.EPOLLIN|std.os.linux.EPOLLOUT|std.os.linux.EPOLLET, | |
| 123 | .data = std.os.linux.epoll_data { | |
| 124 | .ptr = @ptrToInt(prom), | |
| 125 | }, | |
| 114 | var ev = std.os.linux.epoll_event{ | |
| 115 | .events = std.os.linux.EPOLLIN | std.os.linux.EPOLLOUT | std.os.linux.EPOLLET, | |
| 116 | .data = std.os.linux.epoll_data{ .ptr = @ptrToInt(prom) }, | |
| 126 | 117 | }; |
| 127 | 118 | try std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_ADD, fd, &ev); |
| 128 | 119 | } |
| ... | ... | @@ -157,9 +148,9 @@ pub const Loop = struct { |
| 157 | 148 | }; |
| 158 | 149 | |
| 159 | 150 | pub async fn connect(loop: &Loop, _address: &const std.net.Address) !std.os.File { |
| 160 | var address = *_address; // TODO https://github.com/zig-lang/zig/issues/733 | |
| 151 | var address = _address.*; // TODO https://github.com/zig-lang/zig/issues/733 | |
| 161 | 152 | |
| 162 | const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK, posix.PROTO_tcp); | |
| 153 | const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp); | |
| 163 | 154 | errdefer std.os.close(sockfd); |
| 164 | 155 | |
| 165 | 156 | try std.os.posixConnectAsync(sockfd, &address.os_addr); |
| ... | ... | @@ -179,11 +170,9 @@ test "listen on a port, send bytes, receive bytes" { |
| 179 | 170 | |
| 180 | 171 | const Self = this; |
| 181 | 172 | |
| 182 | async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, | |
| 183 | _socket: &const std.os.File) void | |
| 184 | { | |
| 173 | async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, _socket: &const std.os.File) void { | |
| 185 | 174 | const self = @fieldParentPtr(Self, "tcp_server", tcp_server); |
| 186 | var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733 | |
| 175 | var socket = _socket.*; // TODO https://github.com/zig-lang/zig/issues/733 | |
| 187 | 176 | defer socket.close(); |
| 188 | 177 | const next_handler = async errorableHandler(self, _addr, socket) catch |err| switch (err) { |
| 189 | 178 | error.OutOfMemory => @panic("unable to handle connection: out of memory"), |
| ... | ... | @@ -191,14 +180,14 @@ test "listen on a port, send bytes, receive bytes" { |
| 191 | 180 | (await next_handler) catch |err| { |
| 192 | 181 | std.debug.panic("unable to handle connection: {}\n", err); |
| 193 | 182 | }; |
| 194 | suspend |p| { cancel p; } | |
| 183 | suspend |p| { | |
| 184 | cancel p; | |
| 185 | } | |
| 195 | 186 | } |
| 196 | 187 | |
| 197 | async fn errorableHandler(self: &Self, _addr: &const std.net.Address, | |
| 198 | _socket: &const std.os.File) !void | |
| 199 | { | |
| 200 | const addr = *_addr; // TODO https://github.com/zig-lang/zig/issues/733 | |
| 201 | var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733 | |
| 188 | async fn errorableHandler(self: &Self, _addr: &const std.net.Address, _socket: &const std.os.File) !void { | |
| 189 | const addr = _addr.*; // TODO https://github.com/zig-lang/zig/issues/733 | |
| 190 | var socket = _socket.*; // TODO https://github.com/zig-lang/zig/issues/733 | |
| 202 | 191 | |
| 203 | 192 | var adapter = std.io.FileOutStream.init(&socket); |
| 204 | 193 | var stream = &adapter.stream; |
| ... | ... | @@ -210,9 +199,7 @@ test "listen on a port, send bytes, receive bytes" { |
| 210 | 199 | const addr = std.net.Address.initIp4(ip4addr, 0); |
| 211 | 200 | |
| 212 | 201 | var loop = try Loop.init(std.debug.global_allocator); |
| 213 | var server = MyServer { | |
| 214 | .tcp_server = try TcpServer.init(&loop), | |
| 215 | }; | |
| 202 | var server = MyServer{ .tcp_server = try TcpServer.init(&loop) }; | |
| 216 | 203 | defer server.tcp_server.deinit(); |
| 217 | 204 | try server.tcp_server.listen(addr, MyServer.handler); |
| 218 | 205 |
std/hash/crc.zig+16-16| ... | ... | @@ -9,9 +9,9 @@ const std = @import("../index.zig"); |
| 9 | 9 | const debug = std.debug; |
| 10 | 10 | |
| 11 | 11 | pub const Polynomial = struct { |
| 12 | const IEEE = 0xedb88320; | |
| 12 | const IEEE = 0xedb88320; | |
| 13 | 13 | const Castagnoli = 0x82f63b78; |
| 14 | const Koopman = 0xeb31d82e; | |
| 14 | const Koopman = 0xeb31d82e; | |
| 15 | 15 | }; |
| 16 | 16 | |
| 17 | 17 | // IEEE is by far the most common CRC and so is aliased by default. |
| ... | ... | @@ -27,20 +27,22 @@ pub fn Crc32WithPoly(comptime poly: u32) type { |
| 27 | 27 | |
| 28 | 28 | for (tables[0]) |*e, i| { |
| 29 | 29 | var crc = u32(i); |
| 30 | var j: usize = 0; while (j < 8) : (j += 1) { | |
| 30 | var j: usize = 0; | |
| 31 | while (j < 8) : (j += 1) { | |
| 31 | 32 | if (crc & 1 == 1) { |
| 32 | 33 | crc = (crc >> 1) ^ poly; |
| 33 | 34 | } else { |
| 34 | 35 | crc = (crc >> 1); |
| 35 | 36 | } |
| 36 | 37 | } |
| 37 | *e = crc; | |
| 38 | e.* = crc; | |
| 38 | 39 | } |
| 39 | 40 | |
| 40 | 41 | var i: usize = 0; |
| 41 | 42 | while (i < 256) : (i += 1) { |
| 42 | 43 | var crc = tables[0][i]; |
| 43 | var j: usize = 1; while (j < 8) : (j += 1) { | |
| 44 | var j: usize = 1; | |
| 45 | while (j < 8) : (j += 1) { | |
| 44 | 46 | const index = @truncate(u8, crc); |
| 45 | 47 | crc = tables[0][index] ^ (crc >> 8); |
| 46 | 48 | tables[j][i] = crc; |
| ... | ... | @@ -53,22 +55,21 @@ pub fn Crc32WithPoly(comptime poly: u32) type { |
| 53 | 55 | crc: u32, |
| 54 | 56 | |
| 55 | 57 | pub fn init() Self { |
| 56 | return Self { | |
| 57 | .crc = 0xffffffff, | |
| 58 | }; | |
| 58 | return Self{ .crc = 0xffffffff }; | |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | pub fn update(self: &Self, input: []const u8) void { |
| 62 | 62 | var i: usize = 0; |
| 63 | 63 | while (i + 8 <= input.len) : (i += 8) { |
| 64 | const p = input[i..i+8]; | |
| 64 | const p = input[i..i + 8]; | |
| 65 | 65 | |
| 66 | 66 | // Unrolling this way gives ~50Mb/s increase |
| 67 | self.crc ^= (u32(p[0]) << 0); | |
| 68 | self.crc ^= (u32(p[1]) << 8); | |
| 67 | self.crc ^= (u32(p[0]) << 0); | |
| 68 | self.crc ^= (u32(p[1]) << 8); | |
| 69 | 69 | self.crc ^= (u32(p[2]) << 16); |
| 70 | 70 | self.crc ^= (u32(p[3]) << 24); |
| 71 | 71 | |
| 72 | ||
| 72 | 73 | self.crc = |
| 73 | 74 | lookup_tables[0][p[7]] ^ |
| 74 | 75 | lookup_tables[1][p[6]] ^ |
| ... | ... | @@ -123,14 +124,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 123 | 124 | |
| 124 | 125 | for (table) |*e, i| { |
| 125 | 126 | var crc = u32(i * 16); |
| 126 | var j: usize = 0; while (j < 8) : (j += 1) { | |
| 127 | var j: usize = 0; | |
| 128 | while (j < 8) : (j += 1) { | |
| 127 | 129 | if (crc & 1 == 1) { |
| 128 | 130 | crc = (crc >> 1) ^ poly; |
| 129 | 131 | } else { |
| 130 | 132 | crc = (crc >> 1); |
| 131 | 133 | } |
| 132 | 134 | } |
| 133 | *e = crc; | |
| 135 | e.* = crc; | |
| 134 | 136 | } |
| 135 | 137 | |
| 136 | 138 | break :block table; |
| ... | ... | @@ -139,9 +141,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 139 | 141 | crc: u32, |
| 140 | 142 | |
| 141 | 143 | pub fn init() Self { |
| 142 | return Self { | |
| 143 | .crc = 0xffffffff, | |
| 144 | }; | |
| 144 | return Self{ .crc = 0xffffffff }; | |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | 147 | pub fn update(self: &Self, input: []const u8) void { |
std/hash_map.zig+57-45| ... | ... | @@ -9,10 +9,7 @@ const builtin = @import("builtin"); |
| 9 | 9 | const want_modification_safety = builtin.mode != builtin.Mode.ReleaseFast; |
| 10 | 10 | const debug_u32 = if (want_modification_safety) u32 else void; |
| 11 | 11 | |
| 12 | pub fn HashMap(comptime K: type, comptime V: type, | |
| 13 | comptime hash: fn(key: K)u32, | |
| 14 | comptime eql: fn(a: K, b: K)bool) type | |
| 15 | { | |
| 12 | pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn(key: K) u32, comptime eql: fn(a: K, b: K) bool) type { | |
| 16 | 13 | return struct { |
| 17 | 14 | entries: []Entry, |
| 18 | 15 | size: usize, |
| ... | ... | @@ -65,7 +62,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 65 | 62 | }; |
| 66 | 63 | |
| 67 | 64 | pub fn init(allocator: &Allocator) Self { |
| 68 | return Self { | |
| 65 | return Self{ | |
| 69 | 66 | .entries = []Entry{}, |
| 70 | 67 | .allocator = allocator, |
| 71 | 68 | .size = 0, |
| ... | ... | @@ -129,34 +126,36 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 129 | 126 | if (hm.entries.len == 0) return null; |
| 130 | 127 | hm.incrementModificationCount(); |
| 131 | 128 | const start_index = hm.keyToIndex(key); |
| 132 | {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) { | |
| 133 | const index = (start_index + roll_over) % hm.entries.len; | |
| 134 | var entry = &hm.entries[index]; | |
| 135 | ||
| 136 | if (!entry.used) | |
| 137 | return null; | |
| 138 | ||
| 139 | if (!eql(entry.key, key)) continue; | |
| 140 | ||
| 141 | while (roll_over < hm.entries.len) : (roll_over += 1) { | |
| 142 | const next_index = (start_index + roll_over + 1) % hm.entries.len; | |
| 143 | const next_entry = &hm.entries[next_index]; | |
| 144 | if (!next_entry.used or next_entry.distance_from_start_index == 0) { | |
| 145 | entry.used = false; | |
| 146 | hm.size -= 1; | |
| 147 | return entry; | |
| 129 | { | |
| 130 | var roll_over: usize = 0; | |
| 131 | while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) { | |
| 132 | const index = (start_index + roll_over) % hm.entries.len; | |
| 133 | var entry = &hm.entries[index]; | |
| 134 | ||
| 135 | if (!entry.used) return null; | |
| 136 | ||
| 137 | if (!eql(entry.key, key)) continue; | |
| 138 | ||
| 139 | while (roll_over < hm.entries.len) : (roll_over += 1) { | |
| 140 | const next_index = (start_index + roll_over + 1) % hm.entries.len; | |
| 141 | const next_entry = &hm.entries[next_index]; | |
| 142 | if (!next_entry.used or next_entry.distance_from_start_index == 0) { | |
| 143 | entry.used = false; | |
| 144 | hm.size -= 1; | |
| 145 | return entry; | |
| 146 | } | |
| 147 | entry.* = next_entry.*; | |
| 148 | entry.distance_from_start_index -= 1; | |
| 149 | entry = next_entry; | |
| 148 | 150 | } |
| 149 | *entry = *next_entry; | |
| 150 | entry.distance_from_start_index -= 1; | |
| 151 | entry = next_entry; | |
| 151 | unreachable; // shifting everything in the table | |
| 152 | 152 | } |
| 153 | unreachable; // shifting everything in the table | |
| 154 | }} | |
| 153 | } | |
| 155 | 154 | return null; |
| 156 | 155 | } |
| 157 | 156 | |
| 158 | 157 | pub fn iterator(hm: &const Self) Iterator { |
| 159 | return Iterator { | |
| 158 | return Iterator{ | |
| 160 | 159 | .hm = hm, |
| 161 | 160 | .count = 0, |
| 162 | 161 | .index = 0, |
| ... | ... | @@ -182,21 +181,23 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 182 | 181 | /// Returns the value that was already there. |
| 183 | 182 | fn internalPut(hm: &Self, orig_key: K, orig_value: &const V) ?V { |
| 184 | 183 | var key = orig_key; |
| 185 | var value = *orig_value; | |
| 184 | var value = orig_value.*; | |
| 186 | 185 | const start_index = hm.keyToIndex(key); |
| 187 | 186 | var roll_over: usize = 0; |
| 188 | 187 | var distance_from_start_index: usize = 0; |
| 189 | while (roll_over < hm.entries.len) : ({roll_over += 1; distance_from_start_index += 1;}) { | |
| 188 | while (roll_over < hm.entries.len) : ({ | |
| 189 | roll_over += 1; | |
| 190 | distance_from_start_index += 1; | |
| 191 | }) { | |
| 190 | 192 | const index = (start_index + roll_over) % hm.entries.len; |
| 191 | 193 | const entry = &hm.entries[index]; |
| 192 | 194 | |
| 193 | 195 | if (entry.used and !eql(entry.key, key)) { |
| 194 | 196 | if (entry.distance_from_start_index < distance_from_start_index) { |
| 195 | 197 | // robin hood to the rescue |
| 196 | const tmp = *entry; | |
| 197 | hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index, | |
| 198 | distance_from_start_index); | |
| 199 | *entry = Entry { | |
| 198 | const tmp = entry.*; | |
| 199 | hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index, distance_from_start_index); | |
| 200 | entry.* = Entry{ | |
| 200 | 201 | .used = true, |
| 201 | 202 | .distance_from_start_index = distance_from_start_index, |
| 202 | 203 | .key = key, |
| ... | ... | @@ -219,7 +220,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 219 | 220 | } |
| 220 | 221 | |
| 221 | 222 | hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index); |
| 222 | *entry = Entry { | |
| 223 | entry.* = Entry{ | |
| 223 | 224 | .used = true, |
| 224 | 225 | .distance_from_start_index = distance_from_start_index, |
| 225 | 226 | .key = key, |
| ... | ... | @@ -232,13 +233,16 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 232 | 233 | |
| 233 | 234 | fn internalGet(hm: &const Self, key: K) ?&Entry { |
| 234 | 235 | const start_index = hm.keyToIndex(key); |
| 235 | {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) { | |
| 236 | const index = (start_index + roll_over) % hm.entries.len; | |
| 237 | const entry = &hm.entries[index]; | |
| 238 | ||
| 239 | if (!entry.used) return null; | |
| 240 | if (eql(entry.key, key)) return entry; | |
| 241 | }} | |
| 236 | { | |
| 237 | var roll_over: usize = 0; | |
| 238 | while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) { | |
| 239 | const index = (start_index + roll_over) % hm.entries.len; | |
| 240 | const entry = &hm.entries[index]; | |
| 241 | ||
| 242 | if (!entry.used) return null; | |
| 243 | if (eql(entry.key, key)) return entry; | |
| 244 | } | |
| 245 | } | |
| 242 | 246 | return null; |
| 243 | 247 | } |
| 244 | 248 | |
| ... | ... | @@ -282,11 +286,19 @@ test "iterator hash map" { |
| 282 | 286 | assert((reset_map.put(2, 22) catch unreachable) == null); |
| 283 | 287 | assert((reset_map.put(3, 33) catch unreachable) == null); |
| 284 | 288 | |
| 285 | var keys = []i32 { 1, 2, 3 }; | |
| 286 | var values = []i32 { 11, 22, 33 }; | |
| 289 | var keys = []i32{ | |
| 290 | 1, | |
| 291 | 2, | |
| 292 | 3, | |
| 293 | }; | |
| 294 | var values = []i32{ | |
| 295 | 11, | |
| 296 | 22, | |
| 297 | 33, | |
| 298 | }; | |
| 287 | 299 | |
| 288 | 300 | var it = reset_map.iterator(); |
| 289 | var count : usize = 0; | |
| 301 | var count: usize = 0; | |
| 290 | 302 | while (it.next()) |next| { |
| 291 | 303 | assert(next.key == keys[count]); |
| 292 | 304 | assert(next.value == values[count]); |
| ... | ... | @@ -305,7 +317,7 @@ test "iterator hash map" { |
| 305 | 317 | } |
| 306 | 318 | |
| 307 | 319 | it.reset(); |
| 308 | var entry = ?? it.next(); | |
| 320 | var entry = ??it.next(); | |
| 309 | 321 | assert(entry.key == keys[0]); |
| 310 | 322 | assert(entry.value == values[0]); |
| 311 | 323 | } |
std/json.zig+124-83| ... | ... | @@ -35,7 +35,7 @@ pub const Token = struct { |
| 35 | 35 | }; |
| 36 | 36 | |
| 37 | 37 | pub fn init(id: Id, count: usize, offset: u1) Token { |
| 38 | return Token { | |
| 38 | return Token{ | |
| 39 | 39 | .id = id, |
| 40 | 40 | .offset = offset, |
| 41 | 41 | .string_has_escape = false, |
| ... | ... | @@ -45,7 +45,7 @@ pub const Token = struct { |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 47 | pub fn initString(count: usize, has_unicode_escape: bool) Token { |
| 48 | return Token { | |
| 48 | return Token{ | |
| 49 | 49 | .id = Id.String, |
| 50 | 50 | .offset = 0, |
| 51 | 51 | .string_has_escape = has_unicode_escape, |
| ... | ... | @@ -55,7 +55,7 @@ pub const Token = struct { |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | 57 | pub fn initNumber(count: usize, number_is_integer: bool) Token { |
| 58 | return Token { | |
| 58 | return Token{ | |
| 59 | 59 | .id = Id.Number, |
| 60 | 60 | .offset = 0, |
| 61 | 61 | .string_has_escape = false, |
| ... | ... | @@ -66,7 +66,7 @@ pub const Token = struct { |
| 66 | 66 | |
| 67 | 67 | // A marker token is a zero-length |
| 68 | 68 | pub fn initMarker(id: Id) Token { |
| 69 | return Token { | |
| 69 | return Token{ | |
| 70 | 70 | .id = id, |
| 71 | 71 | .offset = 0, |
| 72 | 72 | .string_has_escape = false, |
| ... | ... | @@ -77,7 +77,7 @@ pub const Token = struct { |
| 77 | 77 | |
| 78 | 78 | // Slice into the underlying input string. |
| 79 | 79 | pub fn slice(self: &const Token, input: []const u8, i: usize) []const u8 { |
| 80 | return input[i + self.offset - self.count .. i + self.offset]; | |
| 80 | return input[i + self.offset - self.count..i + self.offset]; | |
| 81 | 81 | } |
| 82 | 82 | }; |
| 83 | 83 | |
| ... | ... | @@ -105,8 +105,8 @@ const StreamingJsonParser = struct { |
| 105 | 105 | stack: u256, |
| 106 | 106 | stack_used: u8, |
| 107 | 107 | |
| 108 | const object_bit = 0; | |
| 109 | const array_bit = 1; | |
| 108 | const object_bit = 0; | |
| 109 | const array_bit = 1; | |
| 110 | 110 | const max_stack_size = @maxValue(u8); |
| 111 | 111 | |
| 112 | 112 | pub fn init() StreamingJsonParser { |
| ... | ... | @@ -120,7 +120,7 @@ const StreamingJsonParser = struct { |
| 120 | 120 | p.count = 0; |
| 121 | 121 | // Set before ever read in main transition function |
| 122 | 122 | p.after_string_state = undefined; |
| 123 | p.after_value_state = State.ValueEnd; // handle end of values normally | |
| 123 | p.after_value_state = State.ValueEnd; // handle end of values normally | |
| 124 | 124 | p.stack = 0; |
| 125 | 125 | p.stack_used = 0; |
| 126 | 126 | p.complete = false; |
| ... | ... | @@ -181,7 +181,7 @@ const StreamingJsonParser = struct { |
| 181 | 181 | } |
| 182 | 182 | }; |
| 183 | 183 | |
| 184 | pub const Error = error { | |
| 184 | pub const Error = error{ | |
| 185 | 185 | InvalidTopLevel, |
| 186 | 186 | TooManyNestedItems, |
| 187 | 187 | TooManyClosingItems, |
| ... | ... | @@ -206,8 +206,8 @@ const StreamingJsonParser = struct { |
| 206 | 206 | // |
| 207 | 207 | // There is currently no error recovery on a bad stream. |
| 208 | 208 | pub fn feed(p: &StreamingJsonParser, c: u8, token1: &?Token, token2: &?Token) Error!void { |
| 209 | *token1 = null; | |
| 210 | *token2 = null; | |
| 209 | token1.* = null; | |
| 210 | token2.* = null; | |
| 211 | 211 | p.count += 1; |
| 212 | 212 | |
| 213 | 213 | // unlikely |
| ... | ... | @@ -228,7 +228,7 @@ const StreamingJsonParser = struct { |
| 228 | 228 | p.state = State.ValueBegin; |
| 229 | 229 | p.after_string_state = State.ObjectSeparator; |
| 230 | 230 | |
| 231 | *token = Token.initMarker(Token.Id.ObjectBegin); | |
| 231 | token.* = Token.initMarker(Token.Id.ObjectBegin); | |
| 232 | 232 | }, |
| 233 | 233 | '[' => { |
| 234 | 234 | p.stack <<= 1; |
| ... | ... | @@ -238,7 +238,7 @@ const StreamingJsonParser = struct { |
| 238 | 238 | p.state = State.ValueBegin; |
| 239 | 239 | p.after_string_state = State.ValueEnd; |
| 240 | 240 | |
| 241 | *token = Token.initMarker(Token.Id.ArrayBegin); | |
| 241 | token.* = Token.initMarker(Token.Id.ArrayBegin); | |
| 242 | 242 | }, |
| 243 | 243 | '-' => { |
| 244 | 244 | p.number_is_integer = true; |
| ... | ... | @@ -281,7 +281,10 @@ const StreamingJsonParser = struct { |
| 281 | 281 | p.after_value_state = State.TopLevelEnd; |
| 282 | 282 | p.count = 0; |
| 283 | 283 | }, |
| 284 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 284 | 0x09, | |
| 285 | 0x0A, | |
| 286 | 0x0D, | |
| 287 | 0x20 => { | |
| 285 | 288 | // whitespace |
| 286 | 289 | }, |
| 287 | 290 | else => { |
| ... | ... | @@ -290,7 +293,10 @@ const StreamingJsonParser = struct { |
| 290 | 293 | }, |
| 291 | 294 | |
| 292 | 295 | State.TopLevelEnd => switch (c) { |
| 293 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 296 | 0x09, | |
| 297 | 0x0A, | |
| 298 | 0x0D, | |
| 299 | 0x20 => { | |
| 294 | 300 | // whitespace |
| 295 | 301 | }, |
| 296 | 302 | else => { |
| ... | ... | @@ -324,7 +330,7 @@ const StreamingJsonParser = struct { |
| 324 | 330 | else => {}, |
| 325 | 331 | } |
| 326 | 332 | |
| 327 | *token = Token.initMarker(Token.Id.ObjectEnd); | |
| 333 | token.* = Token.initMarker(Token.Id.ObjectEnd); | |
| 328 | 334 | }, |
| 329 | 335 | ']' => { |
| 330 | 336 | if (p.stack & 1 != array_bit) { |
| ... | ... | @@ -348,7 +354,7 @@ const StreamingJsonParser = struct { |
| 348 | 354 | else => {}, |
| 349 | 355 | } |
| 350 | 356 | |
| 351 | *token = Token.initMarker(Token.Id.ArrayEnd); | |
| 357 | token.* = Token.initMarker(Token.Id.ArrayEnd); | |
| 352 | 358 | }, |
| 353 | 359 | '{' => { |
| 354 | 360 | if (p.stack_used == max_stack_size) { |
| ... | ... | @@ -362,7 +368,7 @@ const StreamingJsonParser = struct { |
| 362 | 368 | p.state = State.ValueBegin; |
| 363 | 369 | p.after_string_state = State.ObjectSeparator; |
| 364 | 370 | |
| 365 | *token = Token.initMarker(Token.Id.ObjectBegin); | |
| 371 | token.* = Token.initMarker(Token.Id.ObjectBegin); | |
| 366 | 372 | }, |
| 367 | 373 | '[' => { |
| 368 | 374 | if (p.stack_used == max_stack_size) { |
| ... | ... | @@ -376,7 +382,7 @@ const StreamingJsonParser = struct { |
| 376 | 382 | p.state = State.ValueBegin; |
| 377 | 383 | p.after_string_state = State.ValueEnd; |
| 378 | 384 | |
| 379 | *token = Token.initMarker(Token.Id.ArrayBegin); | |
| 385 | token.* = Token.initMarker(Token.Id.ArrayBegin); | |
| 380 | 386 | }, |
| 381 | 387 | '-' => { |
| 382 | 388 | p.state = State.Number; |
| ... | ... | @@ -406,7 +412,10 @@ const StreamingJsonParser = struct { |
| 406 | 412 | p.state = State.NullLiteral1; |
| 407 | 413 | p.count = 0; |
| 408 | 414 | }, |
| 409 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 415 | 0x09, | |
| 416 | 0x0A, | |
| 417 | 0x0D, | |
| 418 | 0x20 => { | |
| 410 | 419 | // whitespace |
| 411 | 420 | }, |
| 412 | 421 | else => { |
| ... | ... | @@ -428,7 +437,7 @@ const StreamingJsonParser = struct { |
| 428 | 437 | p.state = State.ValueBegin; |
| 429 | 438 | p.after_string_state = State.ObjectSeparator; |
| 430 | 439 | |
| 431 | *token = Token.initMarker(Token.Id.ObjectBegin); | |
| 440 | token.* = Token.initMarker(Token.Id.ObjectBegin); | |
| 432 | 441 | }, |
| 433 | 442 | '[' => { |
| 434 | 443 | if (p.stack_used == max_stack_size) { |
| ... | ... | @@ -442,7 +451,7 @@ const StreamingJsonParser = struct { |
| 442 | 451 | p.state = State.ValueBegin; |
| 443 | 452 | p.after_string_state = State.ValueEnd; |
| 444 | 453 | |
| 445 | *token = Token.initMarker(Token.Id.ArrayBegin); | |
| 454 | token.* = Token.initMarker(Token.Id.ArrayBegin); | |
| 446 | 455 | }, |
| 447 | 456 | '-' => { |
| 448 | 457 | p.state = State.Number; |
| ... | ... | @@ -472,7 +481,10 @@ const StreamingJsonParser = struct { |
| 472 | 481 | p.state = State.NullLiteral1; |
| 473 | 482 | p.count = 0; |
| 474 | 483 | }, |
| 475 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 484 | 0x09, | |
| 485 | 0x0A, | |
| 486 | 0x0D, | |
| 487 | 0x20 => { | |
| 476 | 488 | // whitespace |
| 477 | 489 | }, |
| 478 | 490 | else => { |
| ... | ... | @@ -501,7 +513,7 @@ const StreamingJsonParser = struct { |
| 501 | 513 | p.state = State.TopLevelEnd; |
| 502 | 514 | } |
| 503 | 515 | |
| 504 | *token = Token.initMarker(Token.Id.ArrayEnd); | |
| 516 | token.* = Token.initMarker(Token.Id.ArrayEnd); | |
| 505 | 517 | }, |
| 506 | 518 | '}' => { |
| 507 | 519 | if (p.stack_used == 0) { |
| ... | ... | @@ -519,9 +531,12 @@ const StreamingJsonParser = struct { |
| 519 | 531 | p.state = State.TopLevelEnd; |
| 520 | 532 | } |
| 521 | 533 | |
| 522 | *token = Token.initMarker(Token.Id.ObjectEnd); | |
| 534 | token.* = Token.initMarker(Token.Id.ObjectEnd); | |
| 523 | 535 | }, |
| 524 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 536 | 0x09, | |
| 537 | 0x0A, | |
| 538 | 0x0D, | |
| 539 | 0x20 => { | |
| 525 | 540 | // whitespace |
| 526 | 541 | }, |
| 527 | 542 | else => { |
| ... | ... | @@ -534,7 +549,10 @@ const StreamingJsonParser = struct { |
| 534 | 549 | p.state = State.ValueBegin; |
| 535 | 550 | p.after_string_state = State.ValueEnd; |
| 536 | 551 | }, |
| 537 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 552 | 0x09, | |
| 553 | 0x0A, | |
| 554 | 0x0D, | |
| 555 | 0x20 => { | |
| 538 | 556 | // whitespace |
| 539 | 557 | }, |
| 540 | 558 | else => { |
| ... | ... | @@ -553,12 +571,15 @@ const StreamingJsonParser = struct { |
| 553 | 571 | p.complete = true; |
| 554 | 572 | } |
| 555 | 573 | |
| 556 | *token = Token.initString(p.count - 1, p.string_has_escape); | |
| 574 | token.* = Token.initString(p.count - 1, p.string_has_escape); | |
| 557 | 575 | }, |
| 558 | 576 | '\\' => { |
| 559 | 577 | p.state = State.StringEscapeCharacter; |
| 560 | 578 | }, |
| 561 | 0x20, 0x21, 0x23 ... 0x5B, 0x5D ... 0x7F => { | |
| 579 | 0x20, | |
| 580 | 0x21, | |
| 581 | 0x23 ... 0x5B, | |
| 582 | 0x5D ... 0x7F => { | |
| 562 | 583 | // non-control ascii |
| 563 | 584 | }, |
| 564 | 585 | 0xC0 ... 0xDF => { |
| ... | ... | @@ -599,7 +620,14 @@ const StreamingJsonParser = struct { |
| 599 | 620 | // The current JSONTestSuite tests rely on both of this behaviour being present |
| 600 | 621 | // however, so we default to the status quo where both are accepted until this |
| 601 | 622 | // is further clarified. |
| 602 | '"', '\\', '/', 'b', 'f', 'n', 'r', 't' => { | |
| 623 | '"', | |
| 624 | '\\', | |
| 625 | '/', | |
| 626 | 'b', | |
| 627 | 'f', | |
| 628 | 'n', | |
| 629 | 'r', | |
| 630 | 't' => { | |
| 603 | 631 | p.string_has_escape = true; |
| 604 | 632 | p.state = State.String; |
| 605 | 633 | }, |
| ... | ... | @@ -613,28 +641,36 @@ const StreamingJsonParser = struct { |
| 613 | 641 | }, |
| 614 | 642 | |
| 615 | 643 | State.StringEscapeHexUnicode4 => switch (c) { |
| 616 | '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { | |
| 644 | '0' ... '9', | |
| 645 | 'A' ... 'F', | |
| 646 | 'a' ... 'f' => { | |
| 617 | 647 | p.state = State.StringEscapeHexUnicode3; |
| 618 | 648 | }, |
| 619 | 649 | else => return error.InvalidUnicodeHexSymbol, |
| 620 | 650 | }, |
| 621 | 651 | |
| 622 | 652 | State.StringEscapeHexUnicode3 => switch (c) { |
| 623 | '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { | |
| 653 | '0' ... '9', | |
| 654 | 'A' ... 'F', | |
| 655 | 'a' ... 'f' => { | |
| 624 | 656 | p.state = State.StringEscapeHexUnicode2; |
| 625 | 657 | }, |
| 626 | 658 | else => return error.InvalidUnicodeHexSymbol, |
| 627 | 659 | }, |
| 628 | 660 | |
| 629 | 661 | State.StringEscapeHexUnicode2 => switch (c) { |
| 630 | '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { | |
| 662 | '0' ... '9', | |
| 663 | 'A' ... 'F', | |
| 664 | 'a' ... 'f' => { | |
| 631 | 665 | p.state = State.StringEscapeHexUnicode1; |
| 632 | 666 | }, |
| 633 | 667 | else => return error.InvalidUnicodeHexSymbol, |
| 634 | 668 | }, |
| 635 | 669 | |
| 636 | 670 | State.StringEscapeHexUnicode1 => switch (c) { |
| 637 | '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { | |
| 671 | '0' ... '9', | |
| 672 | 'A' ... 'F', | |
| 673 | 'a' ... 'f' => { | |
| 638 | 674 | p.state = State.String; |
| 639 | 675 | }, |
| 640 | 676 | else => return error.InvalidUnicodeHexSymbol, |
| ... | ... | @@ -662,13 +698,14 @@ const StreamingJsonParser = struct { |
| 662 | 698 | p.number_is_integer = false; |
| 663 | 699 | p.state = State.NumberFractionalRequired; |
| 664 | 700 | }, |
| 665 | 'e', 'E' => { | |
| 701 | 'e', | |
| 702 | 'E' => { | |
| 666 | 703 | p.number_is_integer = false; |
| 667 | 704 | p.state = State.NumberExponent; |
| 668 | 705 | }, |
| 669 | 706 | else => { |
| 670 | 707 | p.state = p.after_value_state; |
| 671 | *token = Token.initNumber(p.count, p.number_is_integer); | |
| 708 | token.* = Token.initNumber(p.count, p.number_is_integer); | |
| 672 | 709 | return true; |
| 673 | 710 | }, |
| 674 | 711 | } |
| ... | ... | @@ -681,7 +718,8 @@ const StreamingJsonParser = struct { |
| 681 | 718 | p.number_is_integer = false; |
| 682 | 719 | p.state = State.NumberFractionalRequired; |
| 683 | 720 | }, |
| 684 | 'e', 'E' => { | |
| 721 | 'e', | |
| 722 | 'E' => { | |
| 685 | 723 | p.number_is_integer = false; |
| 686 | 724 | p.state = State.NumberExponent; |
| 687 | 725 | }, |
| ... | ... | @@ -690,7 +728,7 @@ const StreamingJsonParser = struct { |
| 690 | 728 | }, |
| 691 | 729 | else => { |
| 692 | 730 | p.state = p.after_value_state; |
| 693 | *token = Token.initNumber(p.count, p.number_is_integer); | |
| 731 | token.* = Token.initNumber(p.count, p.number_is_integer); | |
| 694 | 732 | return true; |
| 695 | 733 | }, |
| 696 | 734 | } |
| ... | ... | @@ -714,13 +752,14 @@ const StreamingJsonParser = struct { |
| 714 | 752 | '0' ... '9' => { |
| 715 | 753 | // another digit |
| 716 | 754 | }, |
| 717 | 'e', 'E' => { | |
| 755 | 'e', | |
| 756 | 'E' => { | |
| 718 | 757 | p.number_is_integer = false; |
| 719 | 758 | p.state = State.NumberExponent; |
| 720 | 759 | }, |
| 721 | 760 | else => { |
| 722 | 761 | p.state = p.after_value_state; |
| 723 | *token = Token.initNumber(p.count, p.number_is_integer); | |
| 762 | token.* = Token.initNumber(p.count, p.number_is_integer); | |
| 724 | 763 | return true; |
| 725 | 764 | }, |
| 726 | 765 | } |
| ... | ... | @@ -729,20 +768,22 @@ const StreamingJsonParser = struct { |
| 729 | 768 | State.NumberMaybeExponent => { |
| 730 | 769 | p.complete = p.after_value_state == State.TopLevelEnd; |
| 731 | 770 | switch (c) { |
| 732 | 'e', 'E' => { | |
| 771 | 'e', | |
| 772 | 'E' => { | |
| 733 | 773 | p.number_is_integer = false; |
| 734 | 774 | p.state = State.NumberExponent; |
| 735 | 775 | }, |
| 736 | 776 | else => { |
| 737 | 777 | p.state = p.after_value_state; |
| 738 | *token = Token.initNumber(p.count, p.number_is_integer); | |
| 778 | token.* = Token.initNumber(p.count, p.number_is_integer); | |
| 739 | 779 | return true; |
| 740 | 780 | }, |
| 741 | 781 | } |
| 742 | 782 | }, |
| 743 | 783 | |
| 744 | 784 | State.NumberExponent => switch (c) { |
| 745 | '-', '+', => { | |
| 785 | '-', | |
| 786 | '+' => { | |
| 746 | 787 | p.complete = false; |
| 747 | 788 | p.state = State.NumberExponentDigitsRequired; |
| 748 | 789 | }, |
| ... | ... | @@ -773,7 +814,7 @@ const StreamingJsonParser = struct { |
| 773 | 814 | }, |
| 774 | 815 | else => { |
| 775 | 816 | p.state = p.after_value_state; |
| 776 | *token = Token.initNumber(p.count, p.number_is_integer); | |
| 817 | token.* = Token.initNumber(p.count, p.number_is_integer); | |
| 777 | 818 | return true; |
| 778 | 819 | }, |
| 779 | 820 | } |
| ... | ... | @@ -793,7 +834,7 @@ const StreamingJsonParser = struct { |
| 793 | 834 | 'e' => { |
| 794 | 835 | p.state = p.after_value_state; |
| 795 | 836 | p.complete = p.state == State.TopLevelEnd; |
| 796 | *token = Token.init(Token.Id.True, p.count + 1, 1); | |
| 837 | token.* = Token.init(Token.Id.True, p.count + 1, 1); | |
| 797 | 838 | }, |
| 798 | 839 | else => { |
| 799 | 840 | return error.InvalidLiteral; |
| ... | ... | @@ -819,7 +860,7 @@ const StreamingJsonParser = struct { |
| 819 | 860 | 'e' => { |
| 820 | 861 | p.state = p.after_value_state; |
| 821 | 862 | p.complete = p.state == State.TopLevelEnd; |
| 822 | *token = Token.init(Token.Id.False, p.count + 1, 1); | |
| 863 | token.* = Token.init(Token.Id.False, p.count + 1, 1); | |
| 823 | 864 | }, |
| 824 | 865 | else => { |
| 825 | 866 | return error.InvalidLiteral; |
| ... | ... | @@ -840,7 +881,7 @@ const StreamingJsonParser = struct { |
| 840 | 881 | 'l' => { |
| 841 | 882 | p.state = p.after_value_state; |
| 842 | 883 | p.complete = p.state == State.TopLevelEnd; |
| 843 | *token = Token.init(Token.Id.Null, p.count + 1, 1); | |
| 884 | token.* = Token.init(Token.Id.Null, p.count + 1, 1); | |
| 844 | 885 | }, |
| 845 | 886 | else => { |
| 846 | 887 | return error.InvalidLiteral; |
| ... | ... | @@ -895,7 +936,7 @@ pub const Value = union(enum) { |
| 895 | 936 | Object: ObjectMap, |
| 896 | 937 | |
| 897 | 938 | pub fn dump(self: &const Value) void { |
| 898 | switch (*self) { | |
| 939 | switch (self.*) { | |
| 899 | 940 | Value.Null => { |
| 900 | 941 | std.debug.warn("null"); |
| 901 | 942 | }, |
| ... | ... | @@ -950,7 +991,7 @@ pub const Value = union(enum) { |
| 950 | 991 | } |
| 951 | 992 | |
| 952 | 993 | fn dumpIndentLevel(self: &const Value, indent: usize, level: usize) void { |
| 953 | switch (*self) { | |
| 994 | switch (self.*) { | |
| 954 | 995 | Value.Null => { |
| 955 | 996 | std.debug.warn("null"); |
| 956 | 997 | }, |
| ... | ... | @@ -1027,7 +1068,7 @@ const JsonParser = struct { |
| 1027 | 1068 | }; |
| 1028 | 1069 | |
| 1029 | 1070 | pub fn init(allocator: &Allocator, copy_strings: bool) JsonParser { |
| 1030 | return JsonParser { | |
| 1071 | return JsonParser{ | |
| 1031 | 1072 | .allocator = allocator, |
| 1032 | 1073 | .state = State.Simple, |
| 1033 | 1074 | .copy_strings = copy_strings, |
| ... | ... | @@ -1082,7 +1123,7 @@ const JsonParser = struct { |
| 1082 | 1123 | |
| 1083 | 1124 | std.debug.assert(p.stack.len == 1); |
| 1084 | 1125 | |
| 1085 | return ValueTree { | |
| 1126 | return ValueTree{ | |
| 1086 | 1127 | .arena = arena, |
| 1087 | 1128 | .root = p.stack.at(0), |
| 1088 | 1129 | }; |
| ... | ... | @@ -1115,11 +1156,11 @@ const JsonParser = struct { |
| 1115 | 1156 | |
| 1116 | 1157 | switch (token.id) { |
| 1117 | 1158 | Token.Id.ObjectBegin => { |
| 1118 | try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); | |
| 1159 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); | |
| 1119 | 1160 | p.state = State.ObjectKey; |
| 1120 | 1161 | }, |
| 1121 | 1162 | Token.Id.ArrayBegin => { |
| 1122 | try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) }); | |
| 1163 | try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) }); | |
| 1123 | 1164 | p.state = State.ArrayValue; |
| 1124 | 1165 | }, |
| 1125 | 1166 | Token.Id.String => { |
| ... | ... | @@ -1133,12 +1174,12 @@ const JsonParser = struct { |
| 1133 | 1174 | p.state = State.ObjectKey; |
| 1134 | 1175 | }, |
| 1135 | 1176 | Token.Id.True => { |
| 1136 | _ = try object.put(key, Value { .Bool = true }); | |
| 1177 | _ = try object.put(key, Value{ .Bool = true }); | |
| 1137 | 1178 | _ = p.stack.pop(); |
| 1138 | 1179 | p.state = State.ObjectKey; |
| 1139 | 1180 | }, |
| 1140 | 1181 | Token.Id.False => { |
| 1141 | _ = try object.put(key, Value { .Bool = false }); | |
| 1182 | _ = try object.put(key, Value{ .Bool = false }); | |
| 1142 | 1183 | _ = p.stack.pop(); |
| 1143 | 1184 | p.state = State.ObjectKey; |
| 1144 | 1185 | }, |
| ... | ... | @@ -1165,11 +1206,11 @@ const JsonParser = struct { |
| 1165 | 1206 | try p.pushToParent(value); |
| 1166 | 1207 | }, |
| 1167 | 1208 | Token.Id.ObjectBegin => { |
| 1168 | try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); | |
| 1209 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); | |
| 1169 | 1210 | p.state = State.ObjectKey; |
| 1170 | 1211 | }, |
| 1171 | 1212 | Token.Id.ArrayBegin => { |
| 1172 | try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) }); | |
| 1213 | try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) }); | |
| 1173 | 1214 | p.state = State.ArrayValue; |
| 1174 | 1215 | }, |
| 1175 | 1216 | Token.Id.String => { |
| ... | ... | @@ -1179,10 +1220,10 @@ const JsonParser = struct { |
| 1179 | 1220 | try array.append(try p.parseNumber(token, input, i)); |
| 1180 | 1221 | }, |
| 1181 | 1222 | Token.Id.True => { |
| 1182 | try array.append(Value { .Bool = true }); | |
| 1223 | try array.append(Value{ .Bool = true }); | |
| 1183 | 1224 | }, |
| 1184 | 1225 | Token.Id.False => { |
| 1185 | try array.append(Value { .Bool = false }); | |
| 1226 | try array.append(Value{ .Bool = false }); | |
| 1186 | 1227 | }, |
| 1187 | 1228 | Token.Id.Null => { |
| 1188 | 1229 | try array.append(Value.Null); |
| ... | ... | @@ -1194,11 +1235,11 @@ const JsonParser = struct { |
| 1194 | 1235 | }, |
| 1195 | 1236 | State.Simple => switch (token.id) { |
| 1196 | 1237 | Token.Id.ObjectBegin => { |
| 1197 | try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); | |
| 1238 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); | |
| 1198 | 1239 | p.state = State.ObjectKey; |
| 1199 | 1240 | }, |
| 1200 | 1241 | Token.Id.ArrayBegin => { |
| 1201 | try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) }); | |
| 1242 | try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) }); | |
| 1202 | 1243 | p.state = State.ArrayValue; |
| 1203 | 1244 | }, |
| 1204 | 1245 | Token.Id.String => { |
| ... | ... | @@ -1208,15 +1249,16 @@ const JsonParser = struct { |
| 1208 | 1249 | try p.stack.append(try p.parseNumber(token, input, i)); |
| 1209 | 1250 | }, |
| 1210 | 1251 | Token.Id.True => { |
| 1211 | try p.stack.append(Value { .Bool = true }); | |
| 1252 | try p.stack.append(Value{ .Bool = true }); | |
| 1212 | 1253 | }, |
| 1213 | 1254 | Token.Id.False => { |
| 1214 | try p.stack.append(Value { .Bool = false }); | |
| 1255 | try p.stack.append(Value{ .Bool = false }); | |
| 1215 | 1256 | }, |
| 1216 | 1257 | Token.Id.Null => { |
| 1217 | 1258 | try p.stack.append(Value.Null); |
| 1218 | 1259 | }, |
| 1219 | Token.Id.ObjectEnd, Token.Id.ArrayEnd => { | |
| 1260 | Token.Id.ObjectEnd, | |
| 1261 | Token.Id.ArrayEnd => { | |
| 1220 | 1262 | unreachable; |
| 1221 | 1263 | }, |
| 1222 | 1264 | }, |
| ... | ... | @@ -1248,15 +1290,14 @@ const JsonParser = struct { |
| 1248 | 1290 | // TODO: We don't strictly have to copy values which do not contain any escape |
| 1249 | 1291 | // characters if flagged with the option. |
| 1250 | 1292 | const slice = token.slice(input, i); |
| 1251 | return Value { .String = try mem.dupe(p.allocator, u8, slice) }; | |
| 1293 | return Value{ .String = try mem.dupe(p.allocator, u8, slice) }; | |
| 1252 | 1294 | } |
| 1253 | 1295 | |
| 1254 | 1296 | fn parseNumber(p: &JsonParser, token: &const Token, input: []const u8, i: usize) !Value { |
| 1255 | 1297 | return if (token.number_is_integer) |
| 1256 | Value { .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) } | |
| 1298 | Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) } | |
| 1257 | 1299 | else |
| 1258 | @panic("TODO: fmt.parseFloat not yet implemented") | |
| 1259 | ; | |
| 1300 | @panic("TODO: fmt.parseFloat not yet implemented"); | |
| 1260 | 1301 | } |
| 1261 | 1302 | }; |
| 1262 | 1303 | |
| ... | ... | @@ -1267,21 +1308,21 @@ test "json parser dynamic" { |
| 1267 | 1308 | defer p.deinit(); |
| 1268 | 1309 | |
| 1269 | 1310 | const s = |
| 1270 | \\{ | |
| 1271 | \\ "Image": { | |
| 1272 | \\ "Width": 800, | |
| 1273 | \\ "Height": 600, | |
| 1274 | \\ "Title": "View from 15th Floor", | |
| 1275 | \\ "Thumbnail": { | |
| 1276 | \\ "Url": "http://www.example.com/image/481989943", | |
| 1277 | \\ "Height": 125, | |
| 1278 | \\ "Width": 100 | |
| 1279 | \\ }, | |
| 1280 | \\ "Animated" : false, | |
| 1281 | \\ "IDs": [116, 943, 234, 38793] | |
| 1282 | \\ } | |
| 1283 | \\} | |
| 1284 | ; | |
| 1311 | \\{ | |
| 1312 | \\ "Image": { | |
| 1313 | \\ "Width": 800, | |
| 1314 | \\ "Height": 600, | |
| 1315 | \\ "Title": "View from 15th Floor", | |
| 1316 | \\ "Thumbnail": { | |
| 1317 | \\ "Url": "http://www.example.com/image/481989943", | |
| 1318 | \\ "Height": 125, | |
| 1319 | \\ "Width": 100 | |
| 1320 | \\ }, | |
| 1321 | \\ "Animated" : false, | |
| 1322 | \\ "IDs": [116, 943, 234, 38793] | |
| 1323 | \\ } | |
| 1324 | \\} | |
| 1325 | ; | |
| 1285 | 1326 | |
| 1286 | 1327 | var tree = try p.parse(s); |
| 1287 | 1328 | defer tree.deinit(); |
std/math/acos.zig+7-7| ... | ... | @@ -16,7 +16,7 @@ pub fn acos(x: var) @typeOf(x) { |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | fn r32(z: f32) f32 { |
| 19 | const pS0 = 1.6666586697e-01; | |
| 19 | const pS0 = 1.6666586697e-01; | |
| 20 | 20 | const pS1 = -4.2743422091e-02; |
| 21 | 21 | const pS2 = -8.6563630030e-03; |
| 22 | 22 | const qS1 = -7.0662963390e-01; |
| ... | ... | @@ -74,16 +74,16 @@ fn acos32(x: f32) f32 { |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | 76 | fn r64(z: f64) f64 { |
| 77 | const pS0: f64 = 1.66666666666666657415e-01; | |
| 77 | const pS0: f64 = 1.66666666666666657415e-01; | |
| 78 | 78 | const pS1: f64 = -3.25565818622400915405e-01; |
| 79 | const pS2: f64 = 2.01212532134862925881e-01; | |
| 79 | const pS2: f64 = 2.01212532134862925881e-01; | |
| 80 | 80 | const pS3: f64 = -4.00555345006794114027e-02; |
| 81 | const pS4: f64 = 7.91534994289814532176e-04; | |
| 82 | const pS5: f64 = 3.47933107596021167570e-05; | |
| 81 | const pS4: f64 = 7.91534994289814532176e-04; | |
| 82 | const pS5: f64 = 3.47933107596021167570e-05; | |
| 83 | 83 | const qS1: f64 = -2.40339491173441421878e+00; |
| 84 | const qS2: f64 = 2.02094576023350569471e+00; | |
| 84 | const qS2: f64 = 2.02094576023350569471e+00; | |
| 85 | 85 | const qS3: f64 = -6.88283971605453293030e-01; |
| 86 | const qS4: f64 = 7.70381505559019352791e-02; | |
| 86 | const qS4: f64 = 7.70381505559019352791e-02; | |
| 87 | 87 | |
| 88 | 88 | const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); |
| 89 | 89 | const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); |
std/math/asin.zig+9-9| ... | ... | @@ -17,7 +17,7 @@ pub fn asin(x: var) @typeOf(x) { |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | 19 | fn r32(z: f32) f32 { |
| 20 | const pS0 = 1.6666586697e-01; | |
| 20 | const pS0 = 1.6666586697e-01; | |
| 21 | 21 | const pS1 = -4.2743422091e-02; |
| 22 | 22 | const pS2 = -8.6563630030e-03; |
| 23 | 23 | const qS1 = -7.0662963390e-01; |
| ... | ... | @@ -37,9 +37,9 @@ fn asin32(x: f32) f32 { |
| 37 | 37 | if (ix >= 0x3F800000) { |
| 38 | 38 | // |x| >= 1 |
| 39 | 39 | if (ix == 0x3F800000) { |
| 40 | return x * pio2 + 0x1.0p-120; // asin(+-1) = +-pi/2 with inexact | |
| 40 | return x * pio2 + 0x1.0p-120; // asin(+-1) = +-pi/2 with inexact | |
| 41 | 41 | } else { |
| 42 | return math.nan(f32); // asin(|x| > 1) is nan | |
| 42 | return math.nan(f32); // asin(|x| > 1) is nan | |
| 43 | 43 | } |
| 44 | 44 | } |
| 45 | 45 | |
| ... | ... | @@ -66,16 +66,16 @@ fn asin32(x: f32) f32 { |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 68 | fn r64(z: f64) f64 { |
| 69 | const pS0: f64 = 1.66666666666666657415e-01; | |
| 69 | const pS0: f64 = 1.66666666666666657415e-01; | |
| 70 | 70 | const pS1: f64 = -3.25565818622400915405e-01; |
| 71 | const pS2: f64 = 2.01212532134862925881e-01; | |
| 71 | const pS2: f64 = 2.01212532134862925881e-01; | |
| 72 | 72 | const pS3: f64 = -4.00555345006794114027e-02; |
| 73 | const pS4: f64 = 7.91534994289814532176e-04; | |
| 74 | const pS5: f64 = 3.47933107596021167570e-05; | |
| 73 | const pS4: f64 = 7.91534994289814532176e-04; | |
| 74 | const pS5: f64 = 3.47933107596021167570e-05; | |
| 75 | 75 | const qS1: f64 = -2.40339491173441421878e+00; |
| 76 | const qS2: f64 = 2.02094576023350569471e+00; | |
| 76 | const qS2: f64 = 2.02094576023350569471e+00; | |
| 77 | 77 | const qS3: f64 = -6.88283971605453293030e-01; |
| 78 | const qS4: f64 = 7.70381505559019352791e-02; | |
| 78 | const qS4: f64 = 7.70381505559019352791e-02; | |
| 79 | 79 | |
| 80 | 80 | const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); |
| 81 | 81 | const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); |
std/math/atan2.zig+34-32| ... | ... | @@ -31,7 +31,7 @@ pub fn atan2(comptime T: type, x: T, y: T) T { |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | 33 | fn atan2_32(y: f32, x: f32) f32 { |
| 34 | const pi: f32 = 3.1415927410e+00; | |
| 34 | const pi: f32 = 3.1415927410e+00; | |
| 35 | 35 | const pi_lo: f32 = -8.7422776573e-08; |
| 36 | 36 | |
| 37 | 37 | if (math.isNan(x) or math.isNan(y)) { |
| ... | ... | @@ -53,9 +53,10 @@ fn atan2_32(y: f32, x: f32) f32 { |
| 53 | 53 | |
| 54 | 54 | if (iy == 0) { |
| 55 | 55 | switch (m) { |
| 56 | 0, 1 => return y, // atan(+-0, +...) | |
| 57 | 2 => return pi, // atan(+0, -...) | |
| 58 | 3 => return -pi, // atan(-0, -...) | |
| 56 | 0, | |
| 57 | 1 => return y, // atan(+-0, +...) | |
| 58 | 2 => return pi, // atan(+0, -...) | |
| 59 | 3 => return -pi, // atan(-0, -...) | |
| 59 | 60 | else => unreachable, |
| 60 | 61 | } |
| 61 | 62 | } |
| ... | ... | @@ -71,18 +72,18 @@ fn atan2_32(y: f32, x: f32) f32 { |
| 71 | 72 | if (ix == 0x7F800000) { |
| 72 | 73 | if (iy == 0x7F800000) { |
| 73 | 74 | switch (m) { |
| 74 | 0 => return pi / 4, // atan(+inf, +inf) | |
| 75 | 1 => return -pi / 4, // atan(-inf, +inf) | |
| 76 | 2 => return 3*pi / 4, // atan(+inf, -inf) | |
| 77 | 3 => return -3*pi / 4, // atan(-inf, -inf) | |
| 75 | 0 => return pi / 4, // atan(+inf, +inf) | |
| 76 | 1 => return -pi / 4, // atan(-inf, +inf) | |
| 77 | 2 => return 3 * pi / 4, // atan(+inf, -inf) | |
| 78 | 3 => return -3 * pi / 4, // atan(-inf, -inf) | |
| 78 | 79 | else => unreachable, |
| 79 | 80 | } |
| 80 | 81 | } else { |
| 81 | 82 | switch (m) { |
| 82 | 0 => return 0.0, // atan(+..., +inf) | |
| 83 | 1 => return -0.0, // atan(-..., +inf) | |
| 84 | 2 => return pi, // atan(+..., -inf) | |
| 85 | 3 => return -pi, // atan(-...f, -inf) | |
| 83 | 0 => return 0.0, // atan(+..., +inf) | |
| 84 | 1 => return -0.0, // atan(-..., +inf) | |
| 85 | 2 => return pi, // atan(+..., -inf) | |
| 86 | 3 => return -pi, // atan(-...f, -inf) | |
| 86 | 87 | else => unreachable, |
| 87 | 88 | } |
| 88 | 89 | } |
| ... | ... | @@ -107,16 +108,16 @@ fn atan2_32(y: f32, x: f32) f32 { |
| 107 | 108 | }; |
| 108 | 109 | |
| 109 | 110 | switch (m) { |
| 110 | 0 => return z, // atan(+, +) | |
| 111 | 1 => return -z, // atan(-, +) | |
| 112 | 2 => return pi - (z - pi_lo), // atan(+, -) | |
| 113 | 3 => return (z - pi_lo) - pi, // atan(-, -) | |
| 111 | 0 => return z, // atan(+, +) | |
| 112 | 1 => return -z, // atan(-, +) | |
| 113 | 2 => return pi - (z - pi_lo), // atan(+, -) | |
| 114 | 3 => return (z - pi_lo) - pi, // atan(-, -) | |
| 114 | 115 | else => unreachable, |
| 115 | 116 | } |
| 116 | 117 | } |
| 117 | 118 | |
| 118 | 119 | fn atan2_64(y: f64, x: f64) f64 { |
| 119 | const pi: f64 = 3.1415926535897931160E+00; | |
| 120 | const pi: f64 = 3.1415926535897931160E+00; | |
| 120 | 121 | const pi_lo: f64 = 1.2246467991473531772E-16; |
| 121 | 122 | |
| 122 | 123 | if (math.isNan(x) or math.isNan(y)) { |
| ... | ... | @@ -143,9 +144,10 @@ fn atan2_64(y: f64, x: f64) f64 { |
| 143 | 144 | |
| 144 | 145 | if (iy | ly == 0) { |
| 145 | 146 | switch (m) { |
| 146 | 0, 1 => return y, // atan(+-0, +...) | |
| 147 | 2 => return pi, // atan(+0, -...) | |
| 148 | 3 => return -pi, // atan(-0, -...) | |
| 147 | 0, | |
| 148 | 1 => return y, // atan(+-0, +...) | |
| 149 | 2 => return pi, // atan(+0, -...) | |
| 150 | 3 => return -pi, // atan(-0, -...) | |
| 149 | 151 | else => unreachable, |
| 150 | 152 | } |
| 151 | 153 | } |
| ... | ... | @@ -161,18 +163,18 @@ fn atan2_64(y: f64, x: f64) f64 { |
| 161 | 163 | if (ix == 0x7FF00000) { |
| 162 | 164 | if (iy == 0x7FF00000) { |
| 163 | 165 | switch (m) { |
| 164 | 0 => return pi / 4, // atan(+inf, +inf) | |
| 165 | 1 => return -pi / 4, // atan(-inf, +inf) | |
| 166 | 2 => return 3*pi / 4, // atan(+inf, -inf) | |
| 167 | 3 => return -3*pi / 4, // atan(-inf, -inf) | |
| 166 | 0 => return pi / 4, // atan(+inf, +inf) | |
| 167 | 1 => return -pi / 4, // atan(-inf, +inf) | |
| 168 | 2 => return 3 * pi / 4, // atan(+inf, -inf) | |
| 169 | 3 => return -3 * pi / 4, // atan(-inf, -inf) | |
| 168 | 170 | else => unreachable, |
| 169 | 171 | } |
| 170 | 172 | } else { |
| 171 | 173 | switch (m) { |
| 172 | 0 => return 0.0, // atan(+..., +inf) | |
| 173 | 1 => return -0.0, // atan(-..., +inf) | |
| 174 | 2 => return pi, // atan(+..., -inf) | |
| 175 | 3 => return -pi, // atan(-...f, -inf) | |
| 174 | 0 => return 0.0, // atan(+..., +inf) | |
| 175 | 1 => return -0.0, // atan(-..., +inf) | |
| 176 | 2 => return pi, // atan(+..., -inf) | |
| 177 | 3 => return -pi, // atan(-...f, -inf) | |
| 176 | 178 | else => unreachable, |
| 177 | 179 | } |
| 178 | 180 | } |
| ... | ... | @@ -197,10 +199,10 @@ fn atan2_64(y: f64, x: f64) f64 { |
| 197 | 199 | }; |
| 198 | 200 | |
| 199 | 201 | switch (m) { |
| 200 | 0 => return z, // atan(+, +) | |
| 201 | 1 => return -z, // atan(-, +) | |
| 202 | 2 => return pi - (z - pi_lo), // atan(+, -) | |
| 203 | 3 => return (z - pi_lo) - pi, // atan(-, -) | |
| 202 | 0 => return z, // atan(+, +) | |
| 203 | 1 => return -z, // atan(-, +) | |
| 204 | 2 => return pi - (z - pi_lo), // atan(+, -) | |
| 205 | 3 => return (z - pi_lo) - pi, // atan(-, -) | |
| 204 | 206 | else => unreachable, |
| 205 | 207 | } |
| 206 | 208 | } |
std/math/cbrt.zig+5-5| ... | ... | @@ -58,15 +58,15 @@ fn cbrt32(x: f32) f32 { |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | fn cbrt64(x: f64) f64 { |
| 61 | const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20 | |
| 62 | const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20 | |
| 61 | const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20 | |
| 62 | const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20 | |
| 63 | 63 | |
| 64 | 64 | // |1 / cbrt(x) - p(x)| < 2^(23.5) |
| 65 | const P0: f64 = 1.87595182427177009643; | |
| 65 | const P0: f64 = 1.87595182427177009643; | |
| 66 | 66 | const P1: f64 = -1.88497979543377169875; |
| 67 | const P2: f64 = 1.621429720105354466140; | |
| 67 | const P2: f64 = 1.621429720105354466140; | |
| 68 | 68 | const P3: f64 = -0.758397934778766047437; |
| 69 | const P4: f64 = 0.145996192886612446982; | |
| 69 | const P4: f64 = 0.145996192886612446982; | |
| 70 | 70 | |
| 71 | 71 | var u = @bitCast(u64, x); |
| 72 | 72 | var hx = u32(u >> 32) & 0x7FFFFFFF; |
std/math/ceil.zig+2-2| ... | ... | @@ -56,7 +56,7 @@ fn ceil64(x: f64) f64 { |
| 56 | 56 | const e = (u >> 52) & 0x7FF; |
| 57 | 57 | var y: f64 = undefined; |
| 58 | 58 | |
| 59 | if (e >= 0x3FF+52 or x == 0) { | |
| 59 | if (e >= 0x3FF + 52 or x == 0) { | |
| 60 | 60 | return x; |
| 61 | 61 | } |
| 62 | 62 | |
| ... | ... | @@ -68,7 +68,7 @@ fn ceil64(x: f64) f64 { |
| 68 | 68 | y = x + math.f64_toint - math.f64_toint - x; |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | if (e <= 0x3FF-1) { | |
| 71 | if (e <= 0x3FF - 1) { | |
| 72 | 72 | math.forceEval(y); |
| 73 | 73 | if (u >> 63 != 0) { |
| 74 | 74 | return -0.0; |
std/math/cos.zig+6-6| ... | ... | @@ -18,20 +18,20 @@ pub fn cos(x: var) @typeOf(x) { |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | // sin polynomial coefficients |
| 21 | const S0 = 1.58962301576546568060E-10; | |
| 21 | const S0 = 1.58962301576546568060E-10; | |
| 22 | 22 | const S1 = -2.50507477628578072866E-8; |
| 23 | const S2 = 2.75573136213857245213E-6; | |
| 23 | const S2 = 2.75573136213857245213E-6; | |
| 24 | 24 | const S3 = -1.98412698295895385996E-4; |
| 25 | const S4 = 8.33333333332211858878E-3; | |
| 25 | const S4 = 8.33333333332211858878E-3; | |
| 26 | 26 | const S5 = -1.66666666666666307295E-1; |
| 27 | 27 | |
| 28 | 28 | // cos polynomial coeffiecients |
| 29 | 29 | const C0 = -1.13585365213876817300E-11; |
| 30 | const C1 = 2.08757008419747316778E-9; | |
| 30 | const C1 = 2.08757008419747316778E-9; | |
| 31 | 31 | const C2 = -2.75573141792967388112E-7; |
| 32 | const C3 = 2.48015872888517045348E-5; | |
| 32 | const C3 = 2.48015872888517045348E-5; | |
| 33 | 33 | const C4 = -1.38888888888730564116E-3; |
| 34 | const C5 = 4.16666666666665929218E-2; | |
| 34 | const C5 = 4.16666666666665929218E-2; | |
| 35 | 35 | |
| 36 | 36 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. |
| 37 | 37 | // |
std/math/floor.zig+2-2| ... | ... | @@ -57,7 +57,7 @@ fn floor64(x: f64) f64 { |
| 57 | 57 | const e = (u >> 52) & 0x7FF; |
| 58 | 58 | var y: f64 = undefined; |
| 59 | 59 | |
| 60 | if (e >= 0x3FF+52 or x == 0) { | |
| 60 | if (e >= 0x3FF + 52 or x == 0) { | |
| 61 | 61 | return x; |
| 62 | 62 | } |
| 63 | 63 | |
| ... | ... | @@ -69,7 +69,7 @@ fn floor64(x: f64) f64 { |
| 69 | 69 | y = x + math.f64_toint - math.f64_toint - x; |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | if (e <= 0x3FF-1) { | |
| 72 | if (e <= 0x3FF - 1) { | |
| 73 | 73 | math.forceEval(y); |
| 74 | 74 | if (u >> 63 != 0) { |
| 75 | 75 | return -1.0; |
std/math/fma.zig+5-2| ... | ... | @@ -5,7 +5,7 @@ const assert = std.debug.assert; |
| 5 | 5 | pub fn fma(comptime T: type, x: T, y: T, z: T) T { |
| 6 | 6 | return switch (T) { |
| 7 | 7 | f32 => fma32(x, y, z), |
| 8 | f64 => fma64(x, y ,z), | |
| 8 | f64 => fma64(x, y, z), | |
| 9 | 9 | else => @compileError("fma not implemented for " ++ @typeName(T)), |
| 10 | 10 | }; |
| 11 | 11 | } |
| ... | ... | @@ -71,7 +71,10 @@ fn fma64(x: f64, y: f64, z: f64) f64 { |
| 71 | 71 | } |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | const dd = struct { hi: f64, lo: f64, }; | |
| 74 | const dd = struct { | |
| 75 | hi: f64, | |
| 76 | lo: f64, | |
| 77 | }; | |
| 75 | 78 | |
| 76 | 79 | fn dd_add(a: f64, b: f64) dd { |
| 77 | 80 | var ret: dd = undefined; |
std/math/hypot.zig+4-4| ... | ... | @@ -39,11 +39,11 @@ fn hypot32(x: f32, y: f32) f32 { |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | 41 | var z: f32 = 1.0; |
| 42 | if (ux >= (0x7F+60) << 23) { | |
| 42 | if (ux >= (0x7F + 60) << 23) { | |
| 43 | 43 | z = 0x1.0p90; |
| 44 | 44 | xx *= 0x1.0p-90; |
| 45 | 45 | yy *= 0x1.0p-90; |
| 46 | } else if (uy < (0x7F-60) << 23) { | |
| 46 | } else if (uy < (0x7F - 60) << 23) { | |
| 47 | 47 | z = 0x1.0p-90; |
| 48 | 48 | xx *= 0x1.0p-90; |
| 49 | 49 | yy *= 0x1.0p-90; |
| ... | ... | @@ -57,8 +57,8 @@ fn sq(hi: &f64, lo: &f64, x: f64) void { |
| 57 | 57 | const xc = x * split; |
| 58 | 58 | const xh = x - xc + xc; |
| 59 | 59 | const xl = x - xh; |
| 60 | *hi = x * x; | |
| 61 | *lo = xh * xh - *hi + 2 * xh * xl + xl * xl; | |
| 60 | hi.* = x * x; | |
| 61 | lo.* = xh * xh - hi.* + 2 * xh * xl + xl * xl; | |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | fn hypot64(x: f64, y: f64) f64 { |
std/math/ln.zig+2-4| ... | ... | @@ -120,11 +120,9 @@ pub fn ln_64(x_: f64) f64 { |
| 120 | 120 | k -= 54; |
| 121 | 121 | x *= 0x1.0p54; |
| 122 | 122 | hx = u32(@bitCast(u64, ix) >> 32); |
| 123 | } | |
| 124 | else if (hx >= 0x7FF00000) { | |
| 123 | } else if (hx >= 0x7FF00000) { | |
| 125 | 124 | return x; |
| 126 | } | |
| 127 | else if (hx == 0x3FF00000 and ix << 32 == 0) { | |
| 125 | } else if (hx == 0x3FF00000 and ix << 32 == 0) { | |
| 128 | 126 | return 0; |
| 129 | 127 | } |
| 130 | 128 |
std/math/log10.zig+8-10| ... | ... | @@ -35,10 +35,10 @@ pub fn log10(x: var) @typeOf(x) { |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | 37 | pub fn log10_32(x_: f32) f32 { |
| 38 | const ivln10hi: f32 = 4.3432617188e-01; | |
| 39 | const ivln10lo: f32 = -3.1689971365e-05; | |
| 40 | const log10_2hi: f32 = 3.0102920532e-01; | |
| 41 | const log10_2lo: f32 = 7.9034151668e-07; | |
| 38 | const ivln10hi: f32 = 4.3432617188e-01; | |
| 39 | const ivln10lo: f32 = -3.1689971365e-05; | |
| 40 | const log10_2hi: f32 = 3.0102920532e-01; | |
| 41 | const log10_2lo: f32 = 7.9034151668e-07; | |
| 42 | 42 | const Lg1: f32 = 0xaaaaaa.0p-24; |
| 43 | 43 | const Lg2: f32 = 0xccce13.0p-25; |
| 44 | 44 | const Lg3: f32 = 0x91e9ee.0p-25; |
| ... | ... | @@ -95,8 +95,8 @@ pub fn log10_32(x_: f32) f32 { |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | 97 | pub fn log10_64(x_: f64) f64 { |
| 98 | const ivln10hi: f64 = 4.34294481878168880939e-01; | |
| 99 | const ivln10lo: f64 = 2.50829467116452752298e-11; | |
| 98 | const ivln10hi: f64 = 4.34294481878168880939e-01; | |
| 99 | const ivln10lo: f64 = 2.50829467116452752298e-11; | |
| 100 | 100 | const log10_2hi: f64 = 3.01029995663611771306e-01; |
| 101 | 101 | const log10_2lo: f64 = 3.69423907715893078616e-13; |
| 102 | 102 | const Lg1: f64 = 6.666666666666735130e-01; |
| ... | ... | @@ -126,11 +126,9 @@ pub fn log10_64(x_: f64) f64 { |
| 126 | 126 | k -= 54; |
| 127 | 127 | x *= 0x1.0p54; |
| 128 | 128 | hx = u32(@bitCast(u64, x) >> 32); |
| 129 | } | |
| 130 | else if (hx >= 0x7FF00000) { | |
| 129 | } else if (hx >= 0x7FF00000) { | |
| 131 | 130 | return x; |
| 132 | } | |
| 133 | else if (hx == 0x3FF00000 and ix << 32 == 0) { | |
| 131 | } else if (hx == 0x3FF00000 and ix << 32 == 0) { | |
| 134 | 132 | return 0; |
| 135 | 133 | } |
| 136 | 134 |
std/math/log2.zig+5-2| ... | ... | @@ -27,7 +27,10 @@ pub fn log2(x: var) @typeOf(x) { |
| 27 | 27 | TypeId.IntLiteral => comptime { |
| 28 | 28 | var result = 0; |
| 29 | 29 | var x_shifted = x; |
| 30 | while (b: {x_shifted >>= 1; break :b x_shifted != 0;}) : (result += 1) {} | |
| 30 | while (b: { | |
| 31 | x_shifted >>= 1; | |
| 32 | break :b x_shifted != 0; | |
| 33 | }) : (result += 1) {} | |
| 31 | 34 | return result; |
| 32 | 35 | }, |
| 33 | 36 | TypeId.Int => { |
| ... | ... | @@ -38,7 +41,7 @@ pub fn log2(x: var) @typeOf(x) { |
| 38 | 41 | } |
| 39 | 42 | |
| 40 | 43 | pub fn log2_32(x_: f32) f32 { |
| 41 | const ivln2hi: f32 = 1.4428710938e+00; | |
| 44 | const ivln2hi: f32 = 1.4428710938e+00; | |
| 42 | 45 | const ivln2lo: f32 = -1.7605285393e-04; |
| 43 | 46 | const Lg1: f32 = 0xaaaaaa.0p-24; |
| 44 | 47 | const Lg2: f32 = 0xccce13.0p-25; |
std/math/round.zig+4-4| ... | ... | @@ -24,13 +24,13 @@ fn round32(x_: f32) f32 { |
| 24 | 24 | const e = (u >> 23) & 0xFF; |
| 25 | 25 | var y: f32 = undefined; |
| 26 | 26 | |
| 27 | if (e >= 0x7F+23) { | |
| 27 | if (e >= 0x7F + 23) { | |
| 28 | 28 | return x; |
| 29 | 29 | } |
| 30 | 30 | if (u >> 31 != 0) { |
| 31 | 31 | x = -x; |
| 32 | 32 | } |
| 33 | if (e < 0x7F-1) { | |
| 33 | if (e < 0x7F - 1) { | |
| 34 | 34 | math.forceEval(x + math.f32_toint); |
| 35 | 35 | return 0 * @bitCast(f32, u); |
| 36 | 36 | } |
| ... | ... | @@ -61,13 +61,13 @@ fn round64(x_: f64) f64 { |
| 61 | 61 | const e = (u >> 52) & 0x7FF; |
| 62 | 62 | var y: f64 = undefined; |
| 63 | 63 | |
| 64 | if (e >= 0x3FF+52) { | |
| 64 | if (e >= 0x3FF + 52) { | |
| 65 | 65 | return x; |
| 66 | 66 | } |
| 67 | 67 | if (u >> 63 != 0) { |
| 68 | 68 | x = -x; |
| 69 | 69 | } |
| 70 | if (e < 0x3ff-1) { | |
| 70 | if (e < 0x3ff - 1) { | |
| 71 | 71 | math.forceEval(x + math.f64_toint); |
| 72 | 72 | return 0 * @bitCast(f64, u); |
| 73 | 73 | } |
std/math/sin.zig+6-6| ... | ... | @@ -19,20 +19,20 @@ pub fn sin(x: var) @typeOf(x) { |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | // sin polynomial coefficients |
| 22 | const S0 = 1.58962301576546568060E-10; | |
| 22 | const S0 = 1.58962301576546568060E-10; | |
| 23 | 23 | const S1 = -2.50507477628578072866E-8; |
| 24 | const S2 = 2.75573136213857245213E-6; | |
| 24 | const S2 = 2.75573136213857245213E-6; | |
| 25 | 25 | const S3 = -1.98412698295895385996E-4; |
| 26 | const S4 = 8.33333333332211858878E-3; | |
| 26 | const S4 = 8.33333333332211858878E-3; | |
| 27 | 27 | const S5 = -1.66666666666666307295E-1; |
| 28 | 28 | |
| 29 | 29 | // cos polynomial coeffiecients |
| 30 | 30 | const C0 = -1.13585365213876817300E-11; |
| 31 | const C1 = 2.08757008419747316778E-9; | |
| 31 | const C1 = 2.08757008419747316778E-9; | |
| 32 | 32 | const C2 = -2.75573141792967388112E-7; |
| 33 | const C3 = 2.48015872888517045348E-5; | |
| 33 | const C3 = 2.48015872888517045348E-5; | |
| 34 | 34 | const C4 = -1.38888888888730564116E-3; |
| 35 | const C5 = 4.16666666666665929218E-2; | |
| 35 | const C5 = 4.16666666666665929218E-2; | |
| 36 | 36 | |
| 37 | 37 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. |
| 38 | 38 | // |
std/math/tan.zig+3-3| ... | ... | @@ -19,12 +19,12 @@ pub fn tan(x: var) @typeOf(x) { |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | const Tp0 = -1.30936939181383777646E4; |
| 22 | const Tp1 = 1.15351664838587416140E6; | |
| 22 | const Tp1 = 1.15351664838587416140E6; | |
| 23 | 23 | const Tp2 = -1.79565251976484877988E7; |
| 24 | 24 | |
| 25 | const Tq1 = 1.36812963470692954678E4; | |
| 25 | const Tq1 = 1.36812963470692954678E4; | |
| 26 | 26 | const Tq2 = -1.32089234440210967447E6; |
| 27 | const Tq3 = 2.50083801823357915839E7; | |
| 27 | const Tq3 = 2.50083801823357915839E7; | |
| 28 | 28 | const Tq4 = -5.38695755929454629881E7; |
| 29 | 29 | |
| 30 | 30 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. |
std/net.zig+16-24| ... | ... | @@ -19,37 +19,29 @@ pub const Address = struct { |
| 19 | 19 | os_addr: OsAddress, |
| 20 | 20 | |
| 21 | 21 | pub fn initIp4(ip4: u32, port: u16) Address { |
| 22 | return Address { | |
| 23 | .os_addr = posix.sockaddr { | |
| 24 | .in = posix.sockaddr_in { | |
| 25 | .family = posix.AF_INET, | |
| 26 | .port = std.mem.endianSwapIfLe(u16, port), | |
| 27 | .addr = ip4, | |
| 28 | .zero = []u8{0} ** 8, | |
| 29 | }, | |
| 30 | }, | |
| 31 | }; | |
| 22 | return Address{ .os_addr = posix.sockaddr{ .in = posix.sockaddr_in{ | |
| 23 | .family = posix.AF_INET, | |
| 24 | .port = std.mem.endianSwapIfLe(u16, port), | |
| 25 | .addr = ip4, | |
| 26 | .zero = []u8{0} ** 8, | |
| 27 | } } }; | |
| 32 | 28 | } |
| 33 | 29 | |
| 34 | 30 | pub fn initIp6(ip6: &const Ip6Addr, port: u16) Address { |
| 35 | return Address { | |
| 31 | return Address{ | |
| 36 | 32 | .family = posix.AF_INET6, |
| 37 | .os_addr = posix.sockaddr { | |
| 38 | .in6 = posix.sockaddr_in6 { | |
| 39 | .family = posix.AF_INET6, | |
| 40 | .port = std.mem.endianSwapIfLe(u16, port), | |
| 41 | .flowinfo = 0, | |
| 42 | .addr = ip6.addr, | |
| 43 | .scope_id = ip6.scope_id, | |
| 44 | }, | |
| 45 | }, | |
| 33 | .os_addr = posix.sockaddr{ .in6 = posix.sockaddr_in6{ | |
| 34 | .family = posix.AF_INET6, | |
| 35 | .port = std.mem.endianSwapIfLe(u16, port), | |
| 36 | .flowinfo = 0, | |
| 37 | .addr = ip6.addr, | |
| 38 | .scope_id = ip6.scope_id, | |
| 39 | } }, | |
| 46 | 40 | }; |
| 47 | 41 | } |
| 48 | 42 | |
| 49 | 43 | pub fn initPosix(addr: &const posix.sockaddr) Address { |
| 50 | return Address { | |
| 51 | .os_addr = *addr, | |
| 52 | }; | |
| 44 | return Address{ .os_addr = addr.* }; | |
| 53 | 45 | } |
| 54 | 46 | |
| 55 | 47 | pub fn format(self: &const Address, out_stream: var) !void { |
| ... | ... | @@ -98,7 +90,7 @@ pub fn parseIp4(buf: []const u8) !u32 { |
| 98 | 90 | } |
| 99 | 91 | } else { |
| 100 | 92 | return error.InvalidCharacter; |
| 101 | } | |
| 93 | } | |
| 102 | 94 | } |
| 103 | 95 | if (index == 3 and saw_any_digits) { |
| 104 | 96 | out_ptr[index] = x; |
std/os/child_process.zig+101-91| ... | ... | @@ -49,7 +49,7 @@ pub const ChildProcess = struct { |
| 49 | 49 | err_pipe: if (is_windows) void else [2]i32, |
| 50 | 50 | llnode: if (is_windows) void else LinkedList(&ChildProcess).Node, |
| 51 | 51 | |
| 52 | pub const SpawnError = error { | |
| 52 | pub const SpawnError = error{ | |
| 53 | 53 | ProcessFdQuotaExceeded, |
| 54 | 54 | Unexpected, |
| 55 | 55 | NotDir, |
| ... | ... | @@ -88,7 +88,7 @@ pub const ChildProcess = struct { |
| 88 | 88 | const child = try allocator.create(ChildProcess); |
| 89 | 89 | errdefer allocator.destroy(child); |
| 90 | 90 | |
| 91 | *child = ChildProcess { | |
| 91 | child.* = ChildProcess{ | |
| 92 | 92 | .allocator = allocator, |
| 93 | 93 | .argv = argv, |
| 94 | 94 | .pid = undefined, |
| ... | ... | @@ -99,8 +99,10 @@ pub const ChildProcess = struct { |
| 99 | 99 | .term = null, |
| 100 | 100 | .env_map = null, |
| 101 | 101 | .cwd = null, |
| 102 | .uid = if (is_windows) {} else null, | |
| 103 | .gid = if (is_windows) {} else null, | |
| 102 | .uid = if (is_windows) {} else | |
| 103 | null, | |
| 104 | .gid = if (is_windows) {} else | |
| 105 | null, | |
| 104 | 106 | .stdin = null, |
| 105 | 107 | .stdout = null, |
| 106 | 108 | .stderr = null, |
| ... | ... | @@ -193,9 +195,7 @@ pub const ChildProcess = struct { |
| 193 | 195 | |
| 194 | 196 | /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. |
| 195 | 197 | /// If it succeeds, the caller owns result.stdout and result.stderr memory. |
| 196 | pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, | |
| 197 | env_map: ?&const BufMap, max_output_size: usize) !ExecResult | |
| 198 | { | |
| 198 | pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, env_map: ?&const BufMap, max_output_size: usize) !ExecResult { | |
| 199 | 199 | const child = try ChildProcess.init(argv, allocator); |
| 200 | 200 | defer child.deinit(); |
| 201 | 201 | |
| ... | ... | @@ -218,7 +218,7 @@ pub const ChildProcess = struct { |
| 218 | 218 | try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size); |
| 219 | 219 | try stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size); |
| 220 | 220 | |
| 221 | return ExecResult { | |
| 221 | return ExecResult{ | |
| 222 | 222 | .term = try child.wait(), |
| 223 | 223 | .stdout = stdout.toOwnedSlice(), |
| 224 | 224 | .stderr = stderr.toOwnedSlice(), |
| ... | ... | @@ -255,9 +255,9 @@ pub const ChildProcess = struct { |
| 255 | 255 | self.term = (SpawnError!Term)(x: { |
| 256 | 256 | var exit_code: windows.DWORD = undefined; |
| 257 | 257 | if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) { |
| 258 | break :x Term { .Unknown = 0 }; | |
| 258 | break :x Term{ .Unknown = 0 }; | |
| 259 | 259 | } else { |
| 260 | break :x Term { .Exited = @bitCast(i32, exit_code)}; | |
| 260 | break :x Term{ .Exited = @bitCast(i32, exit_code) }; | |
| 261 | 261 | } |
| 262 | 262 | }); |
| 263 | 263 | |
| ... | ... | @@ -288,9 +288,18 @@ pub const ChildProcess = struct { |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | 290 | fn cleanupStreams(self: &ChildProcess) void { |
| 291 | if (self.stdin) |*stdin| { stdin.close(); self.stdin = null; } | |
| 292 | if (self.stdout) |*stdout| { stdout.close(); self.stdout = null; } | |
| 293 | if (self.stderr) |*stderr| { stderr.close(); self.stderr = null; } | |
| 291 | if (self.stdin) |*stdin| { | |
| 292 | stdin.close(); | |
| 293 | self.stdin = null; | |
| 294 | } | |
| 295 | if (self.stdout) |*stdout| { | |
| 296 | stdout.close(); | |
| 297 | self.stdout = null; | |
| 298 | } | |
| 299 | if (self.stderr) |*stderr| { | |
| 300 | stderr.close(); | |
| 301 | self.stderr = null; | |
| 302 | } | |
| 294 | 303 | } |
| 295 | 304 | |
| 296 | 305 | fn cleanupAfterWait(self: &ChildProcess, status: i32) !Term { |
| ... | ... | @@ -317,25 +326,30 @@ pub const ChildProcess = struct { |
| 317 | 326 | |
| 318 | 327 | fn statusToTerm(status: i32) Term { |
| 319 | 328 | return if (posix.WIFEXITED(status)) |
| 320 | Term { .Exited = posix.WEXITSTATUS(status) } | |
| 329 | Term{ .Exited = posix.WEXITSTATUS(status) } | |
| 321 | 330 | else if (posix.WIFSIGNALED(status)) |
| 322 | Term { .Signal = posix.WTERMSIG(status) } | |
| 331 | Term{ .Signal = posix.WTERMSIG(status) } | |
| 323 | 332 | else if (posix.WIFSTOPPED(status)) |
| 324 | Term { .Stopped = posix.WSTOPSIG(status) } | |
| 333 | Term{ .Stopped = posix.WSTOPSIG(status) } | |
| 325 | 334 | else |
| 326 | Term { .Unknown = status } | |
| 327 | ; | |
| 335 | Term{ .Unknown = status }; | |
| 328 | 336 | } |
| 329 | 337 | |
| 330 | 338 | fn spawnPosix(self: &ChildProcess) !void { |
| 331 | 339 | const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined; |
| 332 | errdefer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); }; | |
| 340 | errdefer if (self.stdin_behavior == StdIo.Pipe) { | |
| 341 | destroyPipe(stdin_pipe); | |
| 342 | }; | |
| 333 | 343 | |
| 334 | 344 | const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined; |
| 335 | errdefer if (self.stdout_behavior == StdIo.Pipe) { destroyPipe(stdout_pipe); }; | |
| 345 | errdefer if (self.stdout_behavior == StdIo.Pipe) { | |
| 346 | destroyPipe(stdout_pipe); | |
| 347 | }; | |
| 336 | 348 | |
| 337 | 349 | const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined; |
| 338 | errdefer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); }; | |
| 350 | errdefer if (self.stderr_behavior == StdIo.Pipe) { | |
| 351 | destroyPipe(stderr_pipe); | |
| 352 | }; | |
| 339 | 353 | |
| 340 | 354 | const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); |
| 341 | 355 | const dev_null_fd = if (any_ignore) blk: { |
| ... | ... | @@ -346,7 +360,9 @@ pub const ChildProcess = struct { |
| 346 | 360 | } else blk: { |
| 347 | 361 | break :blk undefined; |
| 348 | 362 | }; |
| 349 | defer { if (any_ignore) os.close(dev_null_fd); } | |
| 363 | defer { | |
| 364 | if (any_ignore) os.close(dev_null_fd); | |
| 365 | } | |
| 350 | 366 | |
| 351 | 367 | var env_map_owned: BufMap = undefined; |
| 352 | 368 | var we_own_env_map: bool = undefined; |
| ... | ... | @@ -358,7 +374,9 @@ pub const ChildProcess = struct { |
| 358 | 374 | env_map_owned = try os.getEnvMap(self.allocator); |
| 359 | 375 | break :x &env_map_owned; |
| 360 | 376 | }; |
| 361 | defer { if (we_own_env_map) env_map_owned.deinit(); } | |
| 377 | defer { | |
| 378 | if (we_own_env_map) env_map_owned.deinit(); | |
| 379 | } | |
| 362 | 380 | |
| 363 | 381 | // This pipe is used to communicate errors between the time of fork |
| 364 | 382 | // and execve from the child process to the parent process. |
| ... | ... | @@ -369,23 +387,21 @@ pub const ChildProcess = struct { |
| 369 | 387 | const pid_err = posix.getErrno(pid_result); |
| 370 | 388 | if (pid_err > 0) { |
| 371 | 389 | return switch (pid_err) { |
| 372 | posix.EAGAIN, posix.ENOMEM, posix.ENOSYS => error.SystemResources, | |
| 390 | posix.EAGAIN, | |
| 391 | posix.ENOMEM, | |
| 392 | posix.ENOSYS => error.SystemResources, | |
| 373 | 393 | else => os.unexpectedErrorPosix(pid_err), |
| 374 | 394 | }; |
| 375 | 395 | } |
| 376 | 396 | if (pid_result == 0) { |
| 377 | 397 | // we are the child |
| 378 | 398 | |
| 379 | setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch | |
| 380 | |err| forkChildErrReport(err_pipe[1], err); | |
| 381 | setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch | |
| 382 | |err| forkChildErrReport(err_pipe[1], err); | |
| 383 | setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch | |
| 384 | |err| forkChildErrReport(err_pipe[1], err); | |
| 399 | setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); | |
| 400 | setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); | |
| 401 | setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); | |
| 385 | 402 | |
| 386 | 403 | if (self.cwd) |cwd| { |
| 387 | os.changeCurDir(self.allocator, cwd) catch | |
| 388 | |err| forkChildErrReport(err_pipe[1], err); | |
| 404 | os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err); | |
| 389 | 405 | } |
| 390 | 406 | |
| 391 | 407 | if (self.gid) |gid| { |
| ... | ... | @@ -396,8 +412,7 @@ pub const ChildProcess = struct { |
| 396 | 412 | os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err); |
| 397 | 413 | } |
| 398 | 414 | |
| 399 | os.posixExecve(self.argv, env_map, self.allocator) catch | |
| 400 | |err| forkChildErrReport(err_pipe[1], err); | |
| 415 | os.posixExecve(self.argv, env_map, self.allocator) catch |err| forkChildErrReport(err_pipe[1], err); | |
| 401 | 416 | } |
| 402 | 417 | |
| 403 | 418 | // we are the parent |
| ... | ... | @@ -423,37 +438,41 @@ pub const ChildProcess = struct { |
| 423 | 438 | self.llnode = LinkedList(&ChildProcess).Node.init(self); |
| 424 | 439 | self.term = null; |
| 425 | 440 | |
| 426 | if (self.stdin_behavior == StdIo.Pipe) { os.close(stdin_pipe[0]); } | |
| 427 | if (self.stdout_behavior == StdIo.Pipe) { os.close(stdout_pipe[1]); } | |
| 428 | if (self.stderr_behavior == StdIo.Pipe) { os.close(stderr_pipe[1]); } | |
| 441 | if (self.stdin_behavior == StdIo.Pipe) { | |
| 442 | os.close(stdin_pipe[0]); | |
| 443 | } | |
| 444 | if (self.stdout_behavior == StdIo.Pipe) { | |
| 445 | os.close(stdout_pipe[1]); | |
| 446 | } | |
| 447 | if (self.stderr_behavior == StdIo.Pipe) { | |
| 448 | os.close(stderr_pipe[1]); | |
| 449 | } | |
| 429 | 450 | } |
| 430 | 451 | |
| 431 | 452 | fn spawnWindows(self: &ChildProcess) !void { |
| 432 | const saAttr = windows.SECURITY_ATTRIBUTES { | |
| 453 | const saAttr = windows.SECURITY_ATTRIBUTES{ | |
| 433 | 454 | .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES), |
| 434 | 455 | .bInheritHandle = windows.TRUE, |
| 435 | 456 | .lpSecurityDescriptor = null, |
| 436 | 457 | }; |
| 437 | 458 | |
| 438 | const any_ignore = (self.stdin_behavior == StdIo.Ignore or | |
| 439 | self.stdout_behavior == StdIo.Ignore or | |
| 440 | self.stderr_behavior == StdIo.Ignore); | |
| 459 | const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); | |
| 441 | 460 | |
| 442 | 461 | const nul_handle = if (any_ignore) blk: { |
| 443 | 462 | const nul_file_path = "NUL"; |
| 444 | 463 | var fixed_buffer_mem: [nul_file_path.len + 1]u8 = undefined; |
| 445 | 464 | var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); |
| 446 | break :blk try os.windowsOpen(&fixed_allocator.allocator, "NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ, | |
| 447 | windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL); | |
| 465 | break :blk try os.windowsOpen(&fixed_allocator.allocator, "NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ, windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL); | |
| 448 | 466 | } else blk: { |
| 449 | 467 | break :blk undefined; |
| 450 | 468 | }; |
| 451 | defer { if (any_ignore) os.close(nul_handle); } | |
| 469 | defer { | |
| 470 | if (any_ignore) os.close(nul_handle); | |
| 471 | } | |
| 452 | 472 | if (any_ignore) { |
| 453 | 473 | try windowsSetHandleInfo(nul_handle, windows.HANDLE_FLAG_INHERIT, 0); |
| 454 | 474 | } |
| 455 | 475 | |
| 456 | ||
| 457 | 476 | var g_hChildStd_IN_Rd: ?windows.HANDLE = null; |
| 458 | 477 | var g_hChildStd_IN_Wr: ?windows.HANDLE = null; |
| 459 | 478 | switch (self.stdin_behavior) { |
| ... | ... | @@ -470,7 +489,9 @@ pub const ChildProcess = struct { |
| 470 | 489 | g_hChildStd_IN_Rd = null; |
| 471 | 490 | }, |
| 472 | 491 | } |
| 473 | errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); }; | |
| 492 | errdefer if (self.stdin_behavior == StdIo.Pipe) { | |
| 493 | windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); | |
| 494 | }; | |
| 474 | 495 | |
| 475 | 496 | var g_hChildStd_OUT_Rd: ?windows.HANDLE = null; |
| 476 | 497 | var g_hChildStd_OUT_Wr: ?windows.HANDLE = null; |
| ... | ... | @@ -488,7 +509,9 @@ pub const ChildProcess = struct { |
| 488 | 509 | g_hChildStd_OUT_Wr = null; |
| 489 | 510 | }, |
| 490 | 511 | } |
| 491 | errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); }; | |
| 512 | errdefer if (self.stdin_behavior == StdIo.Pipe) { | |
| 513 | windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); | |
| 514 | }; | |
| 492 | 515 | |
| 493 | 516 | var g_hChildStd_ERR_Rd: ?windows.HANDLE = null; |
| 494 | 517 | var g_hChildStd_ERR_Wr: ?windows.HANDLE = null; |
| ... | ... | @@ -506,12 +529,14 @@ pub const ChildProcess = struct { |
| 506 | 529 | g_hChildStd_ERR_Wr = null; |
| 507 | 530 | }, |
| 508 | 531 | } |
| 509 | errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); }; | |
| 532 | errdefer if (self.stdin_behavior == StdIo.Pipe) { | |
| 533 | windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); | |
| 534 | }; | |
| 510 | 535 | |
| 511 | 536 | const cmd_line = try windowsCreateCommandLine(self.allocator, self.argv); |
| 512 | 537 | defer self.allocator.free(cmd_line); |
| 513 | 538 | |
| 514 | var siStartInfo = windows.STARTUPINFOA { | |
| 539 | var siStartInfo = windows.STARTUPINFOA{ | |
| 515 | 540 | .cb = @sizeOf(windows.STARTUPINFOA), |
| 516 | 541 | .hStdError = g_hChildStd_ERR_Wr, |
| 517 | 542 | .hStdOutput = g_hChildStd_OUT_Wr, |
| ... | ... | @@ -534,19 +559,11 @@ pub const ChildProcess = struct { |
| 534 | 559 | }; |
| 535 | 560 | var piProcInfo: windows.PROCESS_INFORMATION = undefined; |
| 536 | 561 | |
| 537 | const cwd_slice = if (self.cwd) |cwd| | |
| 538 | try cstr.addNullByte(self.allocator, cwd) | |
| 539 | else | |
| 540 | null | |
| 541 | ; | |
| 562 | const cwd_slice = if (self.cwd) |cwd| try cstr.addNullByte(self.allocator, cwd) else null; | |
| 542 | 563 | defer if (cwd_slice) |cwd| self.allocator.free(cwd); |
| 543 | 564 | const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null; |
| 544 | 565 | |
| 545 | const maybe_envp_buf = if (self.env_map) |env_map| | |
| 546 | try os.createWindowsEnvBlock(self.allocator, env_map) | |
| 547 | else | |
| 548 | null | |
| 549 | ; | |
| 566 | const maybe_envp_buf = if (self.env_map) |env_map| try os.createWindowsEnvBlock(self.allocator, env_map) else null; | |
| 550 | 567 | defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf); |
| 551 | 568 | const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null; |
| 552 | 569 | |
| ... | ... | @@ -563,11 +580,8 @@ pub const ChildProcess = struct { |
| 563 | 580 | }; |
| 564 | 581 | defer self.allocator.free(app_name); |
| 565 | 582 | |
| 566 | windowsCreateProcess(app_name.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, | |
| 567 | &siStartInfo, &piProcInfo) catch |no_path_err| | |
| 568 | { | |
| 569 | if (no_path_err != error.FileNotFound) | |
| 570 | return no_path_err; | |
| 583 | windowsCreateProcess(app_name.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, &siStartInfo, &piProcInfo) catch |no_path_err| { | |
| 584 | if (no_path_err != error.FileNotFound) return no_path_err; | |
| 571 | 585 | |
| 572 | 586 | const PATH = try os.getEnvVarOwned(self.allocator, "PATH"); |
| 573 | 587 | defer self.allocator.free(PATH); |
| ... | ... | @@ -577,9 +591,7 @@ pub const ChildProcess = struct { |
| 577 | 591 | const joined_path = try os.path.join(self.allocator, search_path, app_name); |
| 578 | 592 | defer self.allocator.free(joined_path); |
| 579 | 593 | |
| 580 | if (windowsCreateProcess(joined_path.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, | |
| 581 | &siStartInfo, &piProcInfo)) |_| | |
| 582 | { | |
| 594 | if (windowsCreateProcess(joined_path.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, &siStartInfo, &piProcInfo)) |_| { | |
| 583 | 595 | break; |
| 584 | 596 | } else |err| if (err == error.FileNotFound) { |
| 585 | 597 | continue; |
| ... | ... | @@ -609,9 +621,15 @@ pub const ChildProcess = struct { |
| 609 | 621 | self.thread_handle = piProcInfo.hThread; |
| 610 | 622 | self.term = null; |
| 611 | 623 | |
| 612 | if (self.stdin_behavior == StdIo.Pipe) { os.close(??g_hChildStd_IN_Rd); } | |
| 613 | if (self.stderr_behavior == StdIo.Pipe) { os.close(??g_hChildStd_ERR_Wr); } | |
| 614 | if (self.stdout_behavior == StdIo.Pipe) { os.close(??g_hChildStd_OUT_Wr); } | |
| 624 | if (self.stdin_behavior == StdIo.Pipe) { | |
| 625 | os.close(??g_hChildStd_IN_Rd); | |
| 626 | } | |
| 627 | if (self.stderr_behavior == StdIo.Pipe) { | |
| 628 | os.close(??g_hChildStd_ERR_Wr); | |
| 629 | } | |
| 630 | if (self.stdout_behavior == StdIo.Pipe) { | |
| 631 | os.close(??g_hChildStd_OUT_Wr); | |
| 632 | } | |
| 615 | 633 | } |
| 616 | 634 | |
| 617 | 635 | fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) !void { |
| ... | ... | @@ -622,18 +640,14 @@ pub const ChildProcess = struct { |
| 622 | 640 | StdIo.Ignore => try os.posixDup2(dev_null_fd, std_fileno), |
| 623 | 641 | } |
| 624 | 642 | } |
| 625 | ||
| 626 | 643 | }; |
| 627 | 644 | |
| 628 | fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, | |
| 629 | lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void | |
| 630 | { | |
| 631 | if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, | |
| 632 | @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) | |
| 633 | { | |
| 645 | fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void { | |
| 646 | if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) { | |
| 634 | 647 | const err = windows.GetLastError(); |
| 635 | 648 | return switch (err) { |
| 636 | windows.ERROR.FILE_NOT_FOUND, windows.ERROR.PATH_NOT_FOUND => error.FileNotFound, | |
| 649 | windows.ERROR.FILE_NOT_FOUND, | |
| 650 | windows.ERROR.PATH_NOT_FOUND => error.FileNotFound, | |
| 637 | 651 | windows.ERROR.INVALID_PARAMETER => unreachable, |
| 638 | 652 | windows.ERROR.INVALID_NAME => error.InvalidName, |
| 639 | 653 | else => os.unexpectedErrorWindows(err), |
| ... | ... | @@ -641,9 +655,6 @@ fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ? |
| 641 | 655 | } |
| 642 | 656 | } |
| 643 | 657 | |
| 644 | ||
| 645 | ||
| 646 | ||
| 647 | 658 | /// Caller must dealloc. |
| 648 | 659 | /// Guarantees a null byte at result[result.len]. |
| 649 | 660 | fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) ![]u8 { |
| ... | ... | @@ -651,8 +662,7 @@ fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) |
| 651 | 662 | defer buf.deinit(); |
| 652 | 663 | |
| 653 | 664 | for (argv) |arg, arg_i| { |
| 654 | if (arg_i != 0) | |
| 655 | try buf.appendByte(' '); | |
| 665 | if (arg_i != 0) try buf.appendByte(' '); | |
| 656 | 666 | if (mem.indexOfAny(u8, arg, " \t\n\"") == null) { |
| 657 | 667 | try buf.append(arg); |
| 658 | 668 | continue; |
| ... | ... | @@ -686,7 +696,6 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void { |
| 686 | 696 | if (wr) |h| os.close(h); |
| 687 | 697 | } |
| 688 | 698 | |
| 689 | ||
| 690 | 699 | // TODO: workaround for bug where the `const` from `&const` is dropped when the type is |
| 691 | 700 | // a namespace field lookup |
| 692 | 701 | const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES; |
| ... | ... | @@ -715,8 +724,8 @@ fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const S |
| 715 | 724 | try windowsMakePipe(&rd_h, &wr_h, sattr); |
| 716 | 725 | errdefer windowsDestroyPipe(rd_h, wr_h); |
| 717 | 726 | try windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0); |
| 718 | *rd = rd_h; | |
| 719 | *wr = wr_h; | |
| 727 | rd.* = rd_h; | |
| 728 | wr.* = wr_h; | |
| 720 | 729 | } |
| 721 | 730 | |
| 722 | 731 | fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) !void { |
| ... | ... | @@ -725,8 +734,8 @@ fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const |
| 725 | 734 | try windowsMakePipe(&rd_h, &wr_h, sattr); |
| 726 | 735 | errdefer windowsDestroyPipe(rd_h, wr_h); |
| 727 | 736 | try windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0); |
| 728 | *rd = rd_h; | |
| 729 | *wr = wr_h; | |
| 737 | rd.* = rd_h; | |
| 738 | wr.* = wr_h; | |
| 730 | 739 | } |
| 731 | 740 | |
| 732 | 741 | fn makePipe() ![2]i32 { |
| ... | ... | @@ -734,7 +743,8 @@ fn makePipe() ![2]i32 { |
| 734 | 743 | const err = posix.getErrno(posix.pipe(&fds)); |
| 735 | 744 | if (err > 0) { |
| 736 | 745 | return switch (err) { |
| 737 | posix.EMFILE, posix.ENFILE => error.SystemResources, | |
| 746 | posix.EMFILE, | |
| 747 | posix.ENFILE => error.SystemResources, | |
| 738 | 748 | else => os.unexpectedErrorPosix(err), |
| 739 | 749 | }; |
| 740 | 750 | } |
| ... | ... | @@ -742,8 +752,8 @@ fn makePipe() ![2]i32 { |
| 742 | 752 | } |
| 743 | 753 | |
| 744 | 754 | fn destroyPipe(pipe: &const [2]i32) void { |
| 745 | os.close((*pipe)[0]); | |
| 746 | os.close((*pipe)[1]); | |
| 755 | os.close((pipe.*)[0]); | |
| 756 | os.close((pipe.*)[1]); | |
| 747 | 757 | } |
| 748 | 758 | |
| 749 | 759 | // Child of fork calls this to report an error to the fork parent. |
std/segmented_list.zig+30-24| ... | ... | @@ -93,7 +93,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 93 | 93 | |
| 94 | 94 | /// Deinitialize with `deinit` |
| 95 | 95 | pub fn init(allocator: &Allocator) Self { |
| 96 | return Self { | |
| 96 | return Self{ | |
| 97 | 97 | .allocator = allocator, |
| 98 | 98 | .len = 0, |
| 99 | 99 | .prealloc_segment = undefined, |
| ... | ... | @@ -104,7 +104,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 104 | 104 | pub fn deinit(self: &Self) void { |
| 105 | 105 | self.freeShelves(ShelfIndex(self.dynamic_segments.len), 0); |
| 106 | 106 | self.allocator.free(self.dynamic_segments); |
| 107 | *self = undefined; | |
| 107 | self.* = undefined; | |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | 110 | pub fn at(self: &Self, i: usize) &T { |
| ... | ... | @@ -118,7 +118,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 118 | 118 | |
| 119 | 119 | pub fn push(self: &Self, item: &const T) !void { |
| 120 | 120 | const new_item_ptr = try self.addOne(); |
| 121 | *new_item_ptr = *item; | |
| 121 | new_item_ptr.* = item.*; | |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | 124 | pub fn pushMany(self: &Self, items: []const T) !void { |
| ... | ... | @@ -128,11 +128,10 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 128 | 128 | } |
| 129 | 129 | |
| 130 | 130 | pub fn pop(self: &Self) ?T { |
| 131 | if (self.len == 0) | |
| 132 | return null; | |
| 131 | if (self.len == 0) return null; | |
| 133 | 132 | |
| 134 | 133 | const index = self.len - 1; |
| 135 | const result = *self.uncheckedAt(index); | |
| 134 | const result = self.uncheckedAt(index).*; | |
| 136 | 135 | self.len = index; |
| 137 | 136 | return result; |
| 138 | 137 | } |
| ... | ... | @@ -245,8 +244,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 245 | 244 | shelf_size: usize, |
| 246 | 245 | |
| 247 | 246 | pub fn next(it: &Iterator) ?&T { |
| 248 | if (it.index >= it.list.len) | |
| 249 | return null; | |
| 247 | if (it.index >= it.list.len) return null; | |
| 250 | 248 | if (it.index < prealloc_item_count) { |
| 251 | 249 | const ptr = &it.list.prealloc_segment[it.index]; |
| 252 | 250 | it.index += 1; |
| ... | ... | @@ -270,12 +268,10 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 270 | 268 | } |
| 271 | 269 | |
| 272 | 270 | pub fn prev(it: &Iterator) ?&T { |
| 273 | if (it.index == 0) | |
| 274 | return null; | |
| 271 | if (it.index == 0) return null; | |
| 275 | 272 | |
| 276 | 273 | it.index -= 1; |
| 277 | if (it.index < prealloc_item_count) | |
| 278 | return &it.list.prealloc_segment[it.index]; | |
| 274 | if (it.index < prealloc_item_count) return &it.list.prealloc_segment[it.index]; | |
| 279 | 275 | |
| 280 | 276 | if (it.box_index == 0) { |
| 281 | 277 | it.shelf_index -= 1; |
| ... | ... | @@ -290,7 +286,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 290 | 286 | }; |
| 291 | 287 | |
| 292 | 288 | pub fn iterator(self: &Self, start_index: usize) Iterator { |
| 293 | var it = Iterator { | |
| 289 | var it = Iterator{ | |
| 294 | 290 | .list = self, |
| 295 | 291 | .index = start_index, |
| 296 | 292 | .shelf_index = undefined, |
| ... | ... | @@ -324,25 +320,31 @@ fn testSegmentedList(comptime prealloc: usize, allocator: &Allocator) !void { |
| 324 | 320 | var list = SegmentedList(i32, prealloc).init(allocator); |
| 325 | 321 | defer list.deinit(); |
| 326 | 322 | |
| 327 | {var i: usize = 0; while (i < 100) : (i += 1) { | |
| 328 | try list.push(i32(i + 1)); | |
| 329 | assert(list.len == i + 1); | |
| 330 | }} | |
| 323 | { | |
| 324 | var i: usize = 0; | |
| 325 | while (i < 100) : (i += 1) { | |
| 326 | try list.push(i32(i + 1)); | |
| 327 | assert(list.len == i + 1); | |
| 328 | } | |
| 329 | } | |
| 331 | 330 | |
| 332 | {var i: usize = 0; while (i < 100) : (i += 1) { | |
| 333 | assert(*list.at(i) == i32(i + 1)); | |
| 334 | }} | |
| 331 | { | |
| 332 | var i: usize = 0; | |
| 333 | while (i < 100) : (i += 1) { | |
| 334 | assert(list.at(i).* == i32(i + 1)); | |
| 335 | } | |
| 336 | } | |
| 335 | 337 | |
| 336 | 338 | { |
| 337 | 339 | var it = list.iterator(0); |
| 338 | 340 | var x: i32 = 0; |
| 339 | 341 | while (it.next()) |item| { |
| 340 | 342 | x += 1; |
| 341 | assert(*item == x); | |
| 343 | assert(item.* == x); | |
| 342 | 344 | } |
| 343 | 345 | assert(x == 100); |
| 344 | 346 | while (it.prev()) |item| : (x -= 1) { |
| 345 | assert(*item == x); | |
| 347 | assert(item.* == x); | |
| 346 | 348 | } |
| 347 | 349 | assert(x == 0); |
| 348 | 350 | } |
| ... | ... | @@ -350,14 +352,18 @@ fn testSegmentedList(comptime prealloc: usize, allocator: &Allocator) !void { |
| 350 | 352 | assert(??list.pop() == 100); |
| 351 | 353 | assert(list.len == 99); |
| 352 | 354 | |
| 353 | try list.pushMany([]i32 { 1, 2, 3 }); | |
| 355 | try list.pushMany([]i32{ | |
| 356 | 1, | |
| 357 | 2, | |
| 358 | 3, | |
| 359 | }); | |
| 354 | 360 | assert(list.len == 102); |
| 355 | 361 | assert(??list.pop() == 3); |
| 356 | 362 | assert(??list.pop() == 2); |
| 357 | 363 | assert(??list.pop() == 1); |
| 358 | 364 | assert(list.len == 99); |
| 359 | 365 | |
| 360 | try list.pushMany([]const i32 {}); | |
| 366 | try list.pushMany([]const i32{}); | |
| 361 | 367 | assert(list.len == 99); |
| 362 | 368 | |
| 363 | 369 | var i: i32 = 99; |
std/sort.zig+398-164| ... | ... | @@ -5,15 +5,18 @@ const math = std.math; |
| 5 | 5 | const builtin = @import("builtin"); |
| 6 | 6 | |
| 7 | 7 | /// Stable in-place sort. O(n) best case, O(pow(n, 2)) worst case. O(1) memory (no allocator required). |
| 8 | pub fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void { | |
| 9 | {var i: usize = 1; while (i < items.len) : (i += 1) { | |
| 10 | const x = items[i]; | |
| 11 | var j: usize = i; | |
| 12 | while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) { | |
| 13 | items[j] = items[j - 1]; | |
| 8 | pub fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) void { | |
| 9 | { | |
| 10 | var i: usize = 1; | |
| 11 | while (i < items.len) : (i += 1) { | |
| 12 | const x = items[i]; | |
| 13 | var j: usize = i; | |
| 14 | while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) { | |
| 15 | items[j] = items[j - 1]; | |
| 16 | } | |
| 17 | items[j] = x; | |
| 14 | 18 | } |
| 15 | items[j] = x; | |
| 16 | }} | |
| 19 | } | |
| 17 | 20 | } |
| 18 | 21 | |
| 19 | 22 | const Range = struct { |
| ... | ... | @@ -21,7 +24,10 @@ const Range = struct { |
| 21 | 24 | end: usize, |
| 22 | 25 | |
| 23 | 26 | fn init(start: usize, end: usize) Range { |
| 24 | return Range { .start = start, .end = end }; | |
| 27 | return Range{ | |
| 28 | .start = start, | |
| 29 | .end = end, | |
| 30 | }; | |
| 25 | 31 | } |
| 26 | 32 | |
| 27 | 33 | fn length(self: &const Range) usize { |
| ... | ... | @@ -29,7 +35,6 @@ const Range = struct { |
| 29 | 35 | } |
| 30 | 36 | }; |
| 31 | 37 | |
| 32 | ||
| 33 | 38 | const Iterator = struct { |
| 34 | 39 | size: usize, |
| 35 | 40 | power_of_two: usize, |
| ... | ... | @@ -42,7 +47,7 @@ const Iterator = struct { |
| 42 | 47 | fn init(size2: usize, min_level: usize) Iterator { |
| 43 | 48 | const power_of_two = math.floorPowerOfTwo(usize, size2); |
| 44 | 49 | const denominator = power_of_two / min_level; |
| 45 | return Iterator { | |
| 50 | return Iterator{ | |
| 46 | 51 | .numerator = 0, |
| 47 | 52 | .decimal = 0, |
| 48 | 53 | .size = size2, |
| ... | ... | @@ -68,7 +73,10 @@ const Iterator = struct { |
| 68 | 73 | self.decimal += 1; |
| 69 | 74 | } |
| 70 | 75 | |
| 71 | return Range {.start = start, .end = self.decimal}; | |
| 76 | return Range{ | |
| 77 | .start = start, | |
| 78 | .end = self.decimal, | |
| 79 | }; | |
| 72 | 80 | } |
| 73 | 81 | |
| 74 | 82 | fn finished(self: &Iterator) bool { |
| ... | ... | @@ -100,7 +108,7 @@ const Pull = struct { |
| 100 | 108 | |
| 101 | 109 | /// Stable in-place sort. O(n) best case, O(n*log(n)) worst case and average case. O(1) memory (no allocator required). |
| 102 | 110 | /// Currently implemented as block sort. |
| 103 | pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void { | |
| 111 | pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) void { | |
| 104 | 112 | // Implementation ported from https://github.com/BonzaiThePenguin/WikiSort/blob/master/WikiSort.c |
| 105 | 113 | var cache: [512]T = undefined; |
| 106 | 114 | |
| ... | ... | @@ -123,7 +131,16 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 123 | 131 | // http://pages.ripco.net/~jgamble/nw.html |
| 124 | 132 | var iterator = Iterator.init(items.len, 4); |
| 125 | 133 | while (!iterator.finished()) { |
| 126 | var order = []u8{0, 1, 2, 3, 4, 5, 6, 7}; | |
| 134 | var order = []u8{ | |
| 135 | 0, | |
| 136 | 1, | |
| 137 | 2, | |
| 138 | 3, | |
| 139 | 4, | |
| 140 | 5, | |
| 141 | 6, | |
| 142 | 7, | |
| 143 | }; | |
| 127 | 144 | const range = iterator.nextRange(); |
| 128 | 145 | |
| 129 | 146 | const sliced_items = items[range.start..]; |
| ... | ... | @@ -149,56 +166,56 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 149 | 166 | swap(T, sliced_items, lessThan, &order, 3, 5); |
| 150 | 167 | swap(T, sliced_items, lessThan, &order, 3, 4); |
| 151 | 168 | }, |
| 152 | 7 => { | |
| 153 | swap(T, sliced_items, lessThan, &order, 1, 2); | |
| 154 | swap(T, sliced_items, lessThan, &order, 3, 4); | |
| 155 | swap(T, sliced_items, lessThan, &order, 5, 6); | |
| 156 | swap(T, sliced_items, lessThan, &order, 0, 2); | |
| 157 | swap(T, sliced_items, lessThan, &order, 3, 5); | |
| 158 | swap(T, sliced_items, lessThan, &order, 4, 6); | |
| 159 | swap(T, sliced_items, lessThan, &order, 0, 1); | |
| 160 | swap(T, sliced_items, lessThan, &order, 4, 5); | |
| 161 | swap(T, sliced_items, lessThan, &order, 2, 6); | |
| 162 | swap(T, sliced_items, lessThan, &order, 0, 4); | |
| 163 | swap(T, sliced_items, lessThan, &order, 1, 5); | |
| 164 | swap(T, sliced_items, lessThan, &order, 0, 3); | |
| 165 | swap(T, sliced_items, lessThan, &order, 2, 5); | |
| 166 | swap(T, sliced_items, lessThan, &order, 1, 3); | |
| 167 | swap(T, sliced_items, lessThan, &order, 2, 4); | |
| 168 | swap(T, sliced_items, lessThan, &order, 2, 3); | |
| 169 | }, | |
| 170 | 6 => { | |
| 171 | swap(T, sliced_items, lessThan, &order, 1, 2); | |
| 172 | swap(T, sliced_items, lessThan, &order, 4, 5); | |
| 173 | swap(T, sliced_items, lessThan, &order, 0, 2); | |
| 174 | swap(T, sliced_items, lessThan, &order, 3, 5); | |
| 175 | swap(T, sliced_items, lessThan, &order, 0, 1); | |
| 176 | swap(T, sliced_items, lessThan, &order, 3, 4); | |
| 177 | swap(T, sliced_items, lessThan, &order, 2, 5); | |
| 178 | swap(T, sliced_items, lessThan, &order, 0, 3); | |
| 179 | swap(T, sliced_items, lessThan, &order, 1, 4); | |
| 180 | swap(T, sliced_items, lessThan, &order, 2, 4); | |
| 181 | swap(T, sliced_items, lessThan, &order, 1, 3); | |
| 182 | swap(T, sliced_items, lessThan, &order, 2, 3); | |
| 183 | }, | |
| 184 | 5 => { | |
| 185 | swap(T, sliced_items, lessThan, &order, 0, 1); | |
| 186 | swap(T, sliced_items, lessThan, &order, 3, 4); | |
| 187 | swap(T, sliced_items, lessThan, &order, 2, 4); | |
| 188 | swap(T, sliced_items, lessThan, &order, 2, 3); | |
| 189 | swap(T, sliced_items, lessThan, &order, 1, 4); | |
| 190 | swap(T, sliced_items, lessThan, &order, 0, 3); | |
| 191 | swap(T, sliced_items, lessThan, &order, 0, 2); | |
| 192 | swap(T, sliced_items, lessThan, &order, 1, 3); | |
| 193 | swap(T, sliced_items, lessThan, &order, 1, 2); | |
| 194 | }, | |
| 195 | 4 => { | |
| 196 | swap(T, sliced_items, lessThan, &order, 0, 1); | |
| 197 | swap(T, sliced_items, lessThan, &order, 2, 3); | |
| 198 | swap(T, sliced_items, lessThan, &order, 0, 2); | |
| 199 | swap(T, sliced_items, lessThan, &order, 1, 3); | |
| 200 | swap(T, sliced_items, lessThan, &order, 1, 2); | |
| 201 | }, | |
| 169 | 7 => { | |
| 170 | swap(T, sliced_items, lessThan, &order, 1, 2); | |
| 171 | swap(T, sliced_items, lessThan, &order, 3, 4); | |
| 172 | swap(T, sliced_items, lessThan, &order, 5, 6); | |
| 173 | swap(T, sliced_items, lessThan, &order, 0, 2); | |
| 174 | swap(T, sliced_items, lessThan, &order, 3, 5); | |
| 175 | swap(T, sliced_items, lessThan, &order, 4, 6); | |
| 176 | swap(T, sliced_items, lessThan, &order, 0, 1); | |
| 177 | swap(T, sliced_items, lessThan, &order, 4, 5); | |
| 178 | swap(T, sliced_items, lessThan, &order, 2, 6); | |
| 179 | swap(T, sliced_items, lessThan, &order, 0, 4); | |
| 180 | swap(T, sliced_items, lessThan, &order, 1, 5); | |
| 181 | swap(T, sliced_items, lessThan, &order, 0, 3); | |
| 182 | swap(T, sliced_items, lessThan, &order, 2, 5); | |
| 183 | swap(T, sliced_items, lessThan, &order, 1, 3); | |
| 184 | swap(T, sliced_items, lessThan, &order, 2, 4); | |
| 185 | swap(T, sliced_items, lessThan, &order, 2, 3); | |
| 186 | }, | |
| 187 | 6 => { | |
| 188 | swap(T, sliced_items, lessThan, &order, 1, 2); | |
| 189 | swap(T, sliced_items, lessThan, &order, 4, 5); | |
| 190 | swap(T, sliced_items, lessThan, &order, 0, 2); | |
| 191 | swap(T, sliced_items, lessThan, &order, 3, 5); | |
| 192 | swap(T, sliced_items, lessThan, &order, 0, 1); | |
| 193 | swap(T, sliced_items, lessThan, &order, 3, 4); | |
| 194 | swap(T, sliced_items, lessThan, &order, 2, 5); | |
| 195 | swap(T, sliced_items, lessThan, &order, 0, 3); | |
| 196 | swap(T, sliced_items, lessThan, &order, 1, 4); | |
| 197 | swap(T, sliced_items, lessThan, &order, 2, 4); | |
| 198 | swap(T, sliced_items, lessThan, &order, 1, 3); | |
| 199 | swap(T, sliced_items, lessThan, &order, 2, 3); | |
| 200 | }, | |
| 201 | 5 => { | |
| 202 | swap(T, sliced_items, lessThan, &order, 0, 1); | |
| 203 | swap(T, sliced_items, lessThan, &order, 3, 4); | |
| 204 | swap(T, sliced_items, lessThan, &order, 2, 4); | |
| 205 | swap(T, sliced_items, lessThan, &order, 2, 3); | |
| 206 | swap(T, sliced_items, lessThan, &order, 1, 4); | |
| 207 | swap(T, sliced_items, lessThan, &order, 0, 3); | |
| 208 | swap(T, sliced_items, lessThan, &order, 0, 2); | |
| 209 | swap(T, sliced_items, lessThan, &order, 1, 3); | |
| 210 | swap(T, sliced_items, lessThan, &order, 1, 2); | |
| 211 | }, | |
| 212 | 4 => { | |
| 213 | swap(T, sliced_items, lessThan, &order, 0, 1); | |
| 214 | swap(T, sliced_items, lessThan, &order, 2, 3); | |
| 215 | swap(T, sliced_items, lessThan, &order, 0, 2); | |
| 216 | swap(T, sliced_items, lessThan, &order, 1, 3); | |
| 217 | swap(T, sliced_items, lessThan, &order, 1, 2); | |
| 218 | }, | |
| 202 | 219 | else => {}, |
| 203 | 220 | } |
| 204 | 221 | } |
| ... | ... | @@ -273,7 +290,6 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 273 | 290 | // we merged two levels at the same time, so we're done with this level already |
| 274 | 291 | // (iterator.nextLevel() is called again at the bottom of this outer merge loop) |
| 275 | 292 | _ = iterator.nextLevel(); |
| 276 | ||
| 277 | 293 | } else { |
| 278 | 294 | iterator.begin(); |
| 279 | 295 | while (!iterator.finished()) { |
| ... | ... | @@ -303,7 +319,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 303 | 319 | // 8. redistribute the two internal buffers back into the items |
| 304 | 320 | |
| 305 | 321 | var block_size: usize = math.sqrt(iterator.length()); |
| 306 | var buffer_size = iterator.length()/block_size + 1; | |
| 322 | var buffer_size = iterator.length() / block_size + 1; | |
| 307 | 323 | |
| 308 | 324 | // as an optimization, we really only need to pull out the internal buffers once for each level of merges |
| 309 | 325 | // after that we can reuse the same buffers over and over, then redistribute it when we're finished with this level |
| ... | ... | @@ -316,8 +332,18 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 316 | 332 | var start: usize = 0; |
| 317 | 333 | var pull_index: usize = 0; |
| 318 | 334 | var pull = []Pull{ |
| 319 | Pull {.from = 0, .to = 0, .count = 0, .range = Range.init(0, 0),}, | |
| 320 | Pull {.from = 0, .to = 0, .count = 0, .range = Range.init(0, 0),}, | |
| 335 | Pull{ | |
| 336 | .from = 0, | |
| 337 | .to = 0, | |
| 338 | .count = 0, | |
| 339 | .range = Range.init(0, 0), | |
| 340 | }, | |
| 341 | Pull{ | |
| 342 | .from = 0, | |
| 343 | .to = 0, | |
| 344 | .count = 0, | |
| 345 | .range = Range.init(0, 0), | |
| 346 | }, | |
| 321 | 347 | }; |
| 322 | 348 | |
| 323 | 349 | var buffer1 = Range.init(0, 0); |
| ... | ... | @@ -355,7 +381,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 355 | 381 | // these values will be pulled out to the start of A |
| 356 | 382 | last = A.start; |
| 357 | 383 | count = 1; |
| 358 | while (count < find) : ({last = index; count += 1;}) { | |
| 384 | while (count < find) : ({ | |
| 385 | last = index; | |
| 386 | count += 1; | |
| 387 | }) { | |
| 359 | 388 | index = findLastForward(T, items, items[last], Range.init(last + 1, A.end), lessThan, find - count); |
| 360 | 389 | if (index == A.end) break; |
| 361 | 390 | } |
| ... | ... | @@ -363,7 +392,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 363 | 392 | |
| 364 | 393 | if (count >= buffer_size) { |
| 365 | 394 | // keep track of the range within the items where we'll need to "pull out" these values to create the internal buffer |
| 366 | pull[pull_index] = Pull { | |
| 395 | pull[pull_index] = Pull{ | |
| 367 | 396 | .range = Range.init(A.start, B.end), |
| 368 | 397 | .count = count, |
| 369 | 398 | .from = index, |
| ... | ... | @@ -398,7 +427,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 398 | 427 | } else if (pull_index == 0 and count > buffer1.length()) { |
| 399 | 428 | // keep track of the largest buffer we were able to find |
| 400 | 429 | buffer1 = Range.init(A.start, A.start + count); |
| 401 | pull[pull_index] = Pull { | |
| 430 | pull[pull_index] = Pull{ | |
| 402 | 431 | .range = Range.init(A.start, B.end), |
| 403 | 432 | .count = count, |
| 404 | 433 | .from = index, |
| ... | ... | @@ -410,7 +439,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 410 | 439 | // these values will be pulled out to the end of B |
| 411 | 440 | last = B.end - 1; |
| 412 | 441 | count = 1; |
| 413 | while (count < find) : ({last = index - 1; count += 1;}) { | |
| 442 | while (count < find) : ({ | |
| 443 | last = index - 1; | |
| 444 | count += 1; | |
| 445 | }) { | |
| 414 | 446 | index = findFirstBackward(T, items, items[last], Range.init(B.start, last), lessThan, find - count); |
| 415 | 447 | if (index == B.start) break; |
| 416 | 448 | } |
| ... | ... | @@ -418,7 +450,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 418 | 450 | |
| 419 | 451 | if (count >= buffer_size) { |
| 420 | 452 | // keep track of the range within the items where we'll need to "pull out" these values to create the internal buffe |
| 421 | pull[pull_index] = Pull { | |
| 453 | pull[pull_index] = Pull{ | |
| 422 | 454 | .range = Range.init(A.start, B.end), |
| 423 | 455 | .count = count, |
| 424 | 456 | .from = index, |
| ... | ... | @@ -457,7 +489,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 457 | 489 | } else if (pull_index == 0 and count > buffer1.length()) { |
| 458 | 490 | // keep track of the largest buffer we were able to find |
| 459 | 491 | buffer1 = Range.init(B.end - count, B.end); |
| 460 | pull[pull_index] = Pull { | |
| 492 | pull[pull_index] = Pull{ | |
| 461 | 493 | .range = Range.init(A.start, B.end), |
| 462 | 494 | .count = count, |
| 463 | 495 | .from = index, |
| ... | ... | @@ -496,7 +528,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 496 | 528 | |
| 497 | 529 | // adjust block_size and buffer_size based on the values we were able to pull out |
| 498 | 530 | buffer_size = buffer1.length(); |
| 499 | block_size = iterator.length()/buffer_size + 1; | |
| 531 | block_size = iterator.length() / buffer_size + 1; | |
| 500 | 532 | |
| 501 | 533 | // the first buffer NEEDS to be large enough to tag each of the evenly sized A blocks, |
| 502 | 534 | // so this was originally here to test the math for adjusting block_size above |
| ... | ... | @@ -547,7 +579,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 547 | 579 | // swap the first value of each A block with the value in buffer1 |
| 548 | 580 | var indexA = buffer1.start; |
| 549 | 581 | index = firstA.end; |
| 550 | while (index < blockA.end) : ({indexA += 1; index += block_size;}) { | |
| 582 | while (index < blockA.end) : ({ | |
| 583 | indexA += 1; | |
| 584 | index += block_size; | |
| 585 | }) { | |
| 551 | 586 | mem.swap(T, &items[indexA], &items[index]); |
| 552 | 587 | } |
| 553 | 588 | |
| ... | ... | @@ -626,9 +661,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 626 | 661 | |
| 627 | 662 | // if there are no more A blocks remaining, this step is finished! |
| 628 | 663 | blockA.start += block_size; |
| 629 | if (blockA.length() == 0) | |
| 630 | break; | |
| 631 | ||
| 664 | if (blockA.length() == 0) break; | |
| 632 | 665 | } else if (blockB.length() < block_size) { |
| 633 | 666 | // move the last B block, which is unevenly sized, to before the remaining A blocks, by using a rotation |
| 634 | 667 | // the cache is disabled here since it might contain the contents of the previous A block |
| ... | ... | @@ -709,7 +742,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 709 | 742 | } |
| 710 | 743 | |
| 711 | 744 | // merge operation without a buffer |
| 712 | fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T,&const T)bool) void { | |
| 745 | fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T, &const T) bool) void { | |
| 713 | 746 | if (A_arg.length() == 0 or B_arg.length() == 0) return; |
| 714 | 747 | |
| 715 | 748 | // this just repeatedly binary searches into B and rotates A into position. |
| ... | ... | @@ -730,8 +763,8 @@ fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const |
| 730 | 763 | // again, this is NOT a general-purpose solution – it only works well in this case! |
| 731 | 764 | // kind of like how the O(n^2) insertion sort is used in some places |
| 732 | 765 | |
| 733 | var A = *A_arg; | |
| 734 | var B = *B_arg; | |
| 766 | var A = A_arg.*; | |
| 767 | var B = B_arg.*; | |
| 735 | 768 | |
| 736 | 769 | while (true) { |
| 737 | 770 | // find the first place in B where the first item in A needs to be inserted |
| ... | ... | @@ -751,7 +784,7 @@ fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const |
| 751 | 784 | } |
| 752 | 785 | |
| 753 | 786 | // merge operation using an internal buffer |
| 754 | fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, buffer: &const Range) void { | |
| 787 | fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, buffer: &const Range) void { | |
| 755 | 788 | // whenever we find a value to add to the final array, swap it with the value that's already in that spot |
| 756 | 789 | // when this algorithm is finished, 'buffer' will contain its original contents, but in a different order |
| 757 | 790 | var A_count: usize = 0; |
| ... | ... | @@ -787,9 +820,9 @@ fn blockSwap(comptime T: type, items: []T, start1: usize, start2: usize, block_s |
| 787 | 820 | |
| 788 | 821 | // combine a linear search with a binary search to reduce the number of comparisons in situations |
| 789 | 822 | // where have some idea as to how many unique values there are and where the next value might be |
| 790 | fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 823 | fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { | |
| 791 | 824 | if (range.length() == 0) return range.start; |
| 792 | const skip = math.max(range.length()/unique, usize(1)); | |
| 825 | const skip = math.max(range.length() / unique, usize(1)); | |
| 793 | 826 | |
| 794 | 827 | var index = range.start + skip; |
| 795 | 828 | while (lessThan(items[index - 1], value)) : (index += skip) { |
| ... | ... | @@ -801,9 +834,9 @@ fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const |
| 801 | 834 | return binaryFirst(T, items, value, Range.init(index - skip, index), lessThan); |
| 802 | 835 | } |
| 803 | 836 | |
| 804 | fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 837 | fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { | |
| 805 | 838 | if (range.length() == 0) return range.start; |
| 806 | const skip = math.max(range.length()/unique, usize(1)); | |
| 839 | const skip = math.max(range.length() / unique, usize(1)); | |
| 807 | 840 | |
| 808 | 841 | var index = range.end - skip; |
| 809 | 842 | while (index > range.start and !lessThan(items[index - 1], value)) : (index -= skip) { |
| ... | ... | @@ -815,9 +848,9 @@ fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &cons |
| 815 | 848 | return binaryFirst(T, items, value, Range.init(index, index + skip), lessThan); |
| 816 | 849 | } |
| 817 | 850 | |
| 818 | fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 851 | fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { | |
| 819 | 852 | if (range.length() == 0) return range.start; |
| 820 | const skip = math.max(range.length()/unique, usize(1)); | |
| 853 | const skip = math.max(range.length() / unique, usize(1)); | |
| 821 | 854 | |
| 822 | 855 | var index = range.start + skip; |
| 823 | 856 | while (!lessThan(value, items[index - 1])) : (index += skip) { |
| ... | ... | @@ -829,9 +862,9 @@ fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const |
| 829 | 862 | return binaryLast(T, items, value, Range.init(index - skip, index), lessThan); |
| 830 | 863 | } |
| 831 | 864 | |
| 832 | fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 865 | fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { | |
| 833 | 866 | if (range.length() == 0) return range.start; |
| 834 | const skip = math.max(range.length()/unique, usize(1)); | |
| 867 | const skip = math.max(range.length() / unique, usize(1)); | |
| 835 | 868 | |
| 836 | 869 | var index = range.end - skip; |
| 837 | 870 | while (index > range.start and lessThan(value, items[index - 1])) : (index -= skip) { |
| ... | ... | @@ -843,12 +876,12 @@ fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const |
| 843 | 876 | return binaryLast(T, items, value, Range.init(index, index + skip), lessThan); |
| 844 | 877 | } |
| 845 | 878 | |
| 846 | fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize { | |
| 879 | fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool) usize { | |
| 847 | 880 | var start = range.start; |
| 848 | 881 | var end = range.end - 1; |
| 849 | 882 | if (range.start >= range.end) return range.end; |
| 850 | 883 | while (start < end) { |
| 851 | const mid = start + (end - start)/2; | |
| 884 | const mid = start + (end - start) / 2; | |
| 852 | 885 | if (lessThan(items[mid], value)) { |
| 853 | 886 | start = mid + 1; |
| 854 | 887 | } else { |
| ... | ... | @@ -861,12 +894,12 @@ fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Rang |
| 861 | 894 | return start; |
| 862 | 895 | } |
| 863 | 896 | |
| 864 | fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize { | |
| 897 | fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool) usize { | |
| 865 | 898 | var start = range.start; |
| 866 | 899 | var end = range.end - 1; |
| 867 | 900 | if (range.start >= range.end) return range.end; |
| 868 | 901 | while (start < end) { |
| 869 | const mid = start + (end - start)/2; | |
| 902 | const mid = start + (end - start) / 2; | |
| 870 | 903 | if (!lessThan(value, items[mid])) { |
| 871 | 904 | start = mid + 1; |
| 872 | 905 | } else { |
| ... | ... | @@ -879,7 +912,7 @@ fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range |
| 879 | 912 | return start; |
| 880 | 913 | } |
| 881 | 914 | |
| 882 | fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, into: []T) void { | |
| 915 | fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, into: []T) void { | |
| 883 | 916 | var A_index: usize = A.start; |
| 884 | 917 | var B_index: usize = B.start; |
| 885 | 918 | const A_last = A.end; |
| ... | ... | @@ -909,7 +942,7 @@ fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, less |
| 909 | 942 | } |
| 910 | 943 | } |
| 911 | 944 | |
| 912 | fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, cache: []T) void { | |
| 945 | fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, cache: []T) void { | |
| 913 | 946 | // A fits into the cache, so use that instead of the internal buffer |
| 914 | 947 | var A_index: usize = 0; |
| 915 | 948 | var B_index: usize = B.start; |
| ... | ... | @@ -937,29 +970,27 @@ fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, |
| 937 | 970 | mem.copy(T, items[insert_index..], cache[A_index..A_last]); |
| 938 | 971 | } |
| 939 | 972 | |
| 940 | fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool, order: &[8]u8, x: usize, y: usize) void { | |
| 941 | if (lessThan(items[y], items[x]) or | |
| 942 | ((*order)[x] > (*order)[y] and !lessThan(items[x], items[y]))) | |
| 943 | { | |
| 973 | fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool, order: &[8]u8, x: usize, y: usize) void { | |
| 974 | if (lessThan(items[y], items[x]) or ((order.*)[x] > (order.*)[y] and !lessThan(items[x], items[y]))) { | |
| 944 | 975 | mem.swap(T, &items[x], &items[y]); |
| 945 | mem.swap(u8, &(*order)[x], &(*order)[y]); | |
| 976 | mem.swap(u8, &(order.*)[x], &(order.*)[y]); | |
| 946 | 977 | } |
| 947 | 978 | } |
| 948 | 979 | |
| 949 | 980 | fn i32asc(lhs: &const i32, rhs: &const i32) bool { |
| 950 | return *lhs < *rhs; | |
| 981 | return lhs.* < rhs.*; | |
| 951 | 982 | } |
| 952 | 983 | |
| 953 | 984 | fn i32desc(lhs: &const i32, rhs: &const i32) bool { |
| 954 | return *rhs < *lhs; | |
| 985 | return rhs.* < lhs.*; | |
| 955 | 986 | } |
| 956 | 987 | |
| 957 | 988 | fn u8asc(lhs: &const u8, rhs: &const u8) bool { |
| 958 | return *lhs < *rhs; | |
| 989 | return lhs.* < rhs.*; | |
| 959 | 990 | } |
| 960 | 991 | |
| 961 | 992 | fn u8desc(lhs: &const u8, rhs: &const u8) bool { |
| 962 | return *rhs < *lhs; | |
| 993 | return rhs.* < lhs.*; | |
| 963 | 994 | } |
| 964 | 995 | |
| 965 | 996 | test "stable sort" { |
| ... | ... | @@ -967,44 +998,125 @@ test "stable sort" { |
| 967 | 998 | comptime testStableSort(); |
| 968 | 999 | } |
| 969 | 1000 | fn testStableSort() void { |
| 970 | var expected = []IdAndValue { | |
| 971 | IdAndValue{.id = 0, .value = 0}, | |
| 972 | IdAndValue{.id = 1, .value = 0}, | |
| 973 | IdAndValue{.id = 2, .value = 0}, | |
| 974 | IdAndValue{.id = 0, .value = 1}, | |
| 975 | IdAndValue{.id = 1, .value = 1}, | |
| 976 | IdAndValue{.id = 2, .value = 1}, | |
| 977 | IdAndValue{.id = 0, .value = 2}, | |
| 978 | IdAndValue{.id = 1, .value = 2}, | |
| 979 | IdAndValue{.id = 2, .value = 2}, | |
| 1001 | var expected = []IdAndValue{ | |
| 1002 | IdAndValue{ | |
| 1003 | .id = 0, | |
| 1004 | .value = 0, | |
| 1005 | }, | |
| 1006 | IdAndValue{ | |
| 1007 | .id = 1, | |
| 1008 | .value = 0, | |
| 1009 | }, | |
| 1010 | IdAndValue{ | |
| 1011 | .id = 2, | |
| 1012 | .value = 0, | |
| 1013 | }, | |
| 1014 | IdAndValue{ | |
| 1015 | .id = 0, | |
| 1016 | .value = 1, | |
| 1017 | }, | |
| 1018 | IdAndValue{ | |
| 1019 | .id = 1, | |
| 1020 | .value = 1, | |
| 1021 | }, | |
| 1022 | IdAndValue{ | |
| 1023 | .id = 2, | |
| 1024 | .value = 1, | |
| 1025 | }, | |
| 1026 | IdAndValue{ | |
| 1027 | .id = 0, | |
| 1028 | .value = 2, | |
| 1029 | }, | |
| 1030 | IdAndValue{ | |
| 1031 | .id = 1, | |
| 1032 | .value = 2, | |
| 1033 | }, | |
| 1034 | IdAndValue{ | |
| 1035 | .id = 2, | |
| 1036 | .value = 2, | |
| 1037 | }, | |
| 980 | 1038 | }; |
| 981 | var cases = [][9]IdAndValue { | |
| 982 | []IdAndValue { | |
| 983 | IdAndValue{.id = 0, .value = 0}, | |
| 984 | IdAndValue{.id = 0, .value = 1}, | |
| 985 | IdAndValue{.id = 0, .value = 2}, | |
| 986 | IdAndValue{.id = 1, .value = 0}, | |
| 987 | IdAndValue{.id = 1, .value = 1}, | |
| 988 | IdAndValue{.id = 1, .value = 2}, | |
| 989 | IdAndValue{.id = 2, .value = 0}, | |
| 990 | IdAndValue{.id = 2, .value = 1}, | |
| 991 | IdAndValue{.id = 2, .value = 2}, | |
| 1039 | var cases = [][9]IdAndValue{ | |
| 1040 | []IdAndValue{ | |
| 1041 | IdAndValue{ | |
| 1042 | .id = 0, | |
| 1043 | .value = 0, | |
| 1044 | }, | |
| 1045 | IdAndValue{ | |
| 1046 | .id = 0, | |
| 1047 | .value = 1, | |
| 1048 | }, | |
| 1049 | IdAndValue{ | |
| 1050 | .id = 0, | |
| 1051 | .value = 2, | |
| 1052 | }, | |
| 1053 | IdAndValue{ | |
| 1054 | .id = 1, | |
| 1055 | .value = 0, | |
| 1056 | }, | |
| 1057 | IdAndValue{ | |
| 1058 | .id = 1, | |
| 1059 | .value = 1, | |
| 1060 | }, | |
| 1061 | IdAndValue{ | |
| 1062 | .id = 1, | |
| 1063 | .value = 2, | |
| 1064 | }, | |
| 1065 | IdAndValue{ | |
| 1066 | .id = 2, | |
| 1067 | .value = 0, | |
| 1068 | }, | |
| 1069 | IdAndValue{ | |
| 1070 | .id = 2, | |
| 1071 | .value = 1, | |
| 1072 | }, | |
| 1073 | IdAndValue{ | |
| 1074 | .id = 2, | |
| 1075 | .value = 2, | |
| 1076 | }, | |
| 992 | 1077 | }, |
| 993 | []IdAndValue { | |
| 994 | IdAndValue{.id = 0, .value = 2}, | |
| 995 | IdAndValue{.id = 0, .value = 1}, | |
| 996 | IdAndValue{.id = 0, .value = 0}, | |
| 997 | IdAndValue{.id = 1, .value = 2}, | |
| 998 | IdAndValue{.id = 1, .value = 1}, | |
| 999 | IdAndValue{.id = 1, .value = 0}, | |
| 1000 | IdAndValue{.id = 2, .value = 2}, | |
| 1001 | IdAndValue{.id = 2, .value = 1}, | |
| 1002 | IdAndValue{.id = 2, .value = 0}, | |
| 1078 | []IdAndValue{ | |
| 1079 | IdAndValue{ | |
| 1080 | .id = 0, | |
| 1081 | .value = 2, | |
| 1082 | }, | |
| 1083 | IdAndValue{ | |
| 1084 | .id = 0, | |
| 1085 | .value = 1, | |
| 1086 | }, | |
| 1087 | IdAndValue{ | |
| 1088 | .id = 0, | |
| 1089 | .value = 0, | |
| 1090 | }, | |
| 1091 | IdAndValue{ | |
| 1092 | .id = 1, | |
| 1093 | .value = 2, | |
| 1094 | }, | |
| 1095 | IdAndValue{ | |
| 1096 | .id = 1, | |
| 1097 | .value = 1, | |
| 1098 | }, | |
| 1099 | IdAndValue{ | |
| 1100 | .id = 1, | |
| 1101 | .value = 0, | |
| 1102 | }, | |
| 1103 | IdAndValue{ | |
| 1104 | .id = 2, | |
| 1105 | .value = 2, | |
| 1106 | }, | |
| 1107 | IdAndValue{ | |
| 1108 | .id = 2, | |
| 1109 | .value = 1, | |
| 1110 | }, | |
| 1111 | IdAndValue{ | |
| 1112 | .id = 2, | |
| 1113 | .value = 0, | |
| 1114 | }, | |
| 1003 | 1115 | }, |
| 1004 | 1116 | }; |
| 1005 | 1117 | for (cases) |*case| { |
| 1006 | insertionSort(IdAndValue, (*case)[0..], cmpByValue); | |
| 1007 | for (*case) |item, i| { | |
| 1118 | insertionSort(IdAndValue, (case.*)[0..], cmpByValue); | |
| 1119 | for (case.*) |item, i| { | |
| 1008 | 1120 | assert(item.id == expected[i].id); |
| 1009 | 1121 | assert(item.value == expected[i].value); |
| 1010 | 1122 | } |
| ... | ... | @@ -1019,13 +1131,31 @@ fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) bool { |
| 1019 | 1131 | } |
| 1020 | 1132 | |
| 1021 | 1133 | test "std.sort" { |
| 1022 | const u8cases = [][]const []const u8 { | |
| 1023 | [][]const u8{"", ""}, | |
| 1024 | [][]const u8{"a", "a"}, | |
| 1025 | [][]const u8{"az", "az"}, | |
| 1026 | [][]const u8{"za", "az"}, | |
| 1027 | [][]const u8{"asdf", "adfs"}, | |
| 1028 | [][]const u8{"one", "eno"}, | |
| 1134 | const u8cases = [][]const []const u8{ | |
| 1135 | [][]const u8{ | |
| 1136 | "", | |
| 1137 | "", | |
| 1138 | }, | |
| 1139 | [][]const u8{ | |
| 1140 | "a", | |
| 1141 | "a", | |
| 1142 | }, | |
| 1143 | [][]const u8{ | |
| 1144 | "az", | |
| 1145 | "az", | |
| 1146 | }, | |
| 1147 | [][]const u8{ | |
| 1148 | "za", | |
| 1149 | "az", | |
| 1150 | }, | |
| 1151 | [][]const u8{ | |
| 1152 | "asdf", | |
| 1153 | "adfs", | |
| 1154 | }, | |
| 1155 | [][]const u8{ | |
| 1156 | "one", | |
| 1157 | "eno", | |
| 1158 | }, | |
| 1029 | 1159 | }; |
| 1030 | 1160 | |
| 1031 | 1161 | for (u8cases) |case| { |
| ... | ... | @@ -1036,13 +1166,59 @@ test "std.sort" { |
| 1036 | 1166 | assert(mem.eql(u8, slice, case[1])); |
| 1037 | 1167 | } |
| 1038 | 1168 | |
| 1039 | const i32cases = [][]const []const i32 { | |
| 1040 | [][]const i32{[]i32{}, []i32{}}, | |
| 1041 | [][]const i32{[]i32{1}, []i32{1}}, | |
| 1042 | [][]const i32{[]i32{0, 1}, []i32{0, 1}}, | |
| 1043 | [][]const i32{[]i32{1, 0}, []i32{0, 1}}, | |
| 1044 | [][]const i32{[]i32{1, -1, 0}, []i32{-1, 0, 1}}, | |
| 1045 | [][]const i32{[]i32{2, 1, 3}, []i32{1, 2, 3}}, | |
| 1169 | const i32cases = [][]const []const i32{ | |
| 1170 | [][]const i32{ | |
| 1171 | []i32{}, | |
| 1172 | []i32{}, | |
| 1173 | }, | |
| 1174 | [][]const i32{ | |
| 1175 | []i32{1}, | |
| 1176 | []i32{1}, | |
| 1177 | }, | |
| 1178 | [][]const i32{ | |
| 1179 | []i32{ | |
| 1180 | 0, | |
| 1181 | 1, | |
| 1182 | }, | |
| 1183 | []i32{ | |
| 1184 | 0, | |
| 1185 | 1, | |
| 1186 | }, | |
| 1187 | }, | |
| 1188 | [][]const i32{ | |
| 1189 | []i32{ | |
| 1190 | 1, | |
| 1191 | 0, | |
| 1192 | }, | |
| 1193 | []i32{ | |
| 1194 | 0, | |
| 1195 | 1, | |
| 1196 | }, | |
| 1197 | }, | |
| 1198 | [][]const i32{ | |
| 1199 | []i32{ | |
| 1200 | 1, | |
| 1201 | -1, | |
| 1202 | 0, | |
| 1203 | }, | |
| 1204 | []i32{ | |
| 1205 | -1, | |
| 1206 | 0, | |
| 1207 | 1, | |
| 1208 | }, | |
| 1209 | }, | |
| 1210 | [][]const i32{ | |
| 1211 | []i32{ | |
| 1212 | 2, | |
| 1213 | 1, | |
| 1214 | 3, | |
| 1215 | }, | |
| 1216 | []i32{ | |
| 1217 | 1, | |
| 1218 | 2, | |
| 1219 | 3, | |
| 1220 | }, | |
| 1221 | }, | |
| 1046 | 1222 | }; |
| 1047 | 1223 | |
| 1048 | 1224 | for (i32cases) |case| { |
| ... | ... | @@ -1055,13 +1231,59 @@ test "std.sort" { |
| 1055 | 1231 | } |
| 1056 | 1232 | |
| 1057 | 1233 | test "std.sort descending" { |
| 1058 | const rev_cases = [][]const []const i32 { | |
| 1059 | [][]const i32{[]i32{}, []i32{}}, | |
| 1060 | [][]const i32{[]i32{1}, []i32{1}}, | |
| 1061 | [][]const i32{[]i32{0, 1}, []i32{1, 0}}, | |
| 1062 | [][]const i32{[]i32{1, 0}, []i32{1, 0}}, | |
| 1063 | [][]const i32{[]i32{1, -1, 0}, []i32{1, 0, -1}}, | |
| 1064 | [][]const i32{[]i32{2, 1, 3}, []i32{3, 2, 1}}, | |
| 1234 | const rev_cases = [][]const []const i32{ | |
| 1235 | [][]const i32{ | |
| 1236 | []i32{}, | |
| 1237 | []i32{}, | |
| 1238 | }, | |
| 1239 | [][]const i32{ | |
| 1240 | []i32{1}, | |
| 1241 | []i32{1}, | |
| 1242 | }, | |
| 1243 | [][]const i32{ | |
| 1244 | []i32{ | |
| 1245 | 0, | |
| 1246 | 1, | |
| 1247 | }, | |
| 1248 | []i32{ | |
| 1249 | 1, | |
| 1250 | 0, | |
| 1251 | }, | |
| 1252 | }, | |
| 1253 | [][]const i32{ | |
| 1254 | []i32{ | |
| 1255 | 1, | |
| 1256 | 0, | |
| 1257 | }, | |
| 1258 | []i32{ | |
| 1259 | 1, | |
| 1260 | 0, | |
| 1261 | }, | |
| 1262 | }, | |
| 1263 | [][]const i32{ | |
| 1264 | []i32{ | |
| 1265 | 1, | |
| 1266 | -1, | |
| 1267 | 0, | |
| 1268 | }, | |
| 1269 | []i32{ | |
| 1270 | 1, | |
| 1271 | 0, | |
| 1272 | -1, | |
| 1273 | }, | |
| 1274 | }, | |
| 1275 | [][]const i32{ | |
| 1276 | []i32{ | |
| 1277 | 2, | |
| 1278 | 1, | |
| 1279 | 3, | |
| 1280 | }, | |
| 1281 | []i32{ | |
| 1282 | 3, | |
| 1283 | 2, | |
| 1284 | 1, | |
| 1285 | }, | |
| 1286 | }, | |
| 1065 | 1287 | }; |
| 1066 | 1288 | |
| 1067 | 1289 | for (rev_cases) |case| { |
| ... | ... | @@ -1074,10 +1296,22 @@ test "std.sort descending" { |
| 1074 | 1296 | } |
| 1075 | 1297 | |
| 1076 | 1298 | test "another sort case" { |
| 1077 | var arr = []i32{ 5, 3, 1, 2, 4 }; | |
| 1299 | var arr = []i32{ | |
| 1300 | 5, | |
| 1301 | 3, | |
| 1302 | 1, | |
| 1303 | 2, | |
| 1304 | 4, | |
| 1305 | }; | |
| 1078 | 1306 | sort(i32, arr[0..], i32asc); |
| 1079 | 1307 | |
| 1080 | assert(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 })); | |
| 1308 | assert(mem.eql(i32, arr, []i32{ | |
| 1309 | 1, | |
| 1310 | 2, | |
| 1311 | 3, | |
| 1312 | 4, | |
| 1313 | 5, | |
| 1314 | })); | |
| 1081 | 1315 | } |
| 1082 | 1316 | |
| 1083 | 1317 | test "sort fuzz testing" { |
| ... | ... | @@ -1112,7 +1346,7 @@ fn fuzzTest(rng: &std.rand.Random) void { |
| 1112 | 1346 | } |
| 1113 | 1347 | } |
| 1114 | 1348 | |
| 1115 | pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T { | |
| 1349 | pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) T { | |
| 1116 | 1350 | var i: usize = 0; |
| 1117 | 1351 | var smallest = items[0]; |
| 1118 | 1352 | for (items[1..]) |item| { |
| ... | ... | @@ -1123,7 +1357,7 @@ pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const |
| 1123 | 1357 | return smallest; |
| 1124 | 1358 | } |
| 1125 | 1359 | |
| 1126 | pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T { | |
| 1360 | pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) T { | |
| 1127 | 1361 | var i: usize = 0; |
| 1128 | 1362 | var biggest = items[0]; |
| 1129 | 1363 | for (items[1..]) |item| { |