authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-10 00:29:49-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-10 00:29:49-04:00
log4787127cf6418f7a819c9d6f07a9046d76e0de65
tree05e2a1d04722ec0a364a5c87278175c27ff7400d
parent6928badd850f9fcebdcc0b13287db2c81d2293c0

partial conversion to post-fix pointer deref using zig fmt


30 files changed, 1620 insertions(+), 1064 deletions(-)

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