mirror of
https://github.com/ziglang/zig.git
synced 2024-11-16 00:57:04 +00:00
partial conversion to post-fix pointer deref using zig fmt
This commit is contained in:
parent
6928badd85
commit
4787127cf6
@ -70,7 +70,7 @@ test "std.atomic.queue" {
|
||||
|
||||
var queue: Queue(i32) = undefined;
|
||||
queue.init();
|
||||
var context = Context {
|
||||
var context = Context{
|
||||
.allocator = a,
|
||||
.queue = &queue,
|
||||
.put_sum = 0,
|
||||
@ -81,16 +81,18 @@ test "std.atomic.queue" {
|
||||
|
||||
var putters: [put_thread_count]&std.os.Thread = undefined;
|
||||
for (putters) |*t| {
|
||||
*t = try std.os.spawnThread(&context, startPuts);
|
||||
t.* = try std.os.spawnThread(&context, startPuts);
|
||||
}
|
||||
var getters: [put_thread_count]&std.os.Thread = undefined;
|
||||
for (getters) |*t| {
|
||||
*t = try std.os.spawnThread(&context, startGets);
|
||||
t.* = try std.os.spawnThread(&context, startGets);
|
||||
}
|
||||
|
||||
for (putters) |t| t.wait();
|
||||
for (putters) |t|
|
||||
t.wait();
|
||||
_ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
|
||||
for (getters) |t| t.wait();
|
||||
for (getters) |t|
|
||||
t.wait();
|
||||
|
||||
std.debug.assert(context.put_sum == context.get_sum);
|
||||
std.debug.assert(context.get_count == puts_per_thread * put_thread_count);
|
||||
|
@ -14,9 +14,7 @@ pub fn Stack(comptime T: type) type {
|
||||
};
|
||||
|
||||
pub fn init() Self {
|
||||
return Self {
|
||||
.root = null,
|
||||
};
|
||||
return Self{ .root = null };
|
||||
}
|
||||
|
||||
/// 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" {
|
||||
var a = &fixed_buffer_allocator.allocator;
|
||||
|
||||
var stack = Stack(i32).init();
|
||||
var context = Context {
|
||||
var context = Context{
|
||||
.allocator = a,
|
||||
.stack = &stack,
|
||||
.put_sum = 0,
|
||||
@ -86,16 +84,18 @@ test "std.atomic.stack" {
|
||||
|
||||
var putters: [put_thread_count]&std.os.Thread = undefined;
|
||||
for (putters) |*t| {
|
||||
*t = try std.os.spawnThread(&context, startPuts);
|
||||
t.* = try std.os.spawnThread(&context, startPuts);
|
||||
}
|
||||
var getters: [put_thread_count]&std.os.Thread = undefined;
|
||||
for (getters) |*t| {
|
||||
*t = try std.os.spawnThread(&context, startGets);
|
||||
t.* = try std.os.spawnThread(&context, startGets);
|
||||
}
|
||||
|
||||
for (putters) |t| t.wait();
|
||||
for (putters) |t|
|
||||
t.wait();
|
||||
_ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
|
||||
for (getters) |t| t.wait();
|
||||
for (getters) |t|
|
||||
t.wait();
|
||||
|
||||
std.debug.assert(context.put_sum == context.get_sum);
|
||||
std.debug.assert(context.get_count == puts_per_thread * put_thread_count);
|
||||
|
@ -31,9 +31,7 @@ pub const Buffer = struct {
|
||||
/// * ::replaceContentsBuffer
|
||||
/// * ::resize
|
||||
pub fn initNull(allocator: &Allocator) Buffer {
|
||||
return Buffer {
|
||||
.list = ArrayList(u8).init(allocator),
|
||||
};
|
||||
return Buffer{ .list = ArrayList(u8).init(allocator) };
|
||||
}
|
||||
|
||||
/// Must deinitialize with deinit.
|
||||
@ -45,9 +43,7 @@ pub const Buffer = struct {
|
||||
/// allocated with `allocator`.
|
||||
/// Must deinitialize with deinit.
|
||||
pub fn fromOwnedSlice(allocator: &Allocator, slice: []u8) Buffer {
|
||||
var self = Buffer {
|
||||
.list = ArrayList(u8).fromOwnedSlice(allocator, slice),
|
||||
};
|
||||
var self = Buffer{ .list = ArrayList(u8).fromOwnedSlice(allocator, slice) };
|
||||
self.list.append(0);
|
||||
return self;
|
||||
}
|
||||
@ -57,11 +53,10 @@ pub const Buffer = struct {
|
||||
pub fn toOwnedSlice(self: &Buffer) []u8 {
|
||||
const allocator = self.list.allocator;
|
||||
const result = allocator.shrink(u8, self.list.items, self.len());
|
||||
*self = initNull(allocator);
|
||||
self.* = initNull(allocator);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
pub fn deinit(self: &Buffer) void {
|
||||
self.list.deinit();
|
||||
}
|
||||
|
207
std/build.zig
207
std/build.zig
@ -82,10 +82,8 @@ pub const Builder = struct {
|
||||
description: []const u8,
|
||||
};
|
||||
|
||||
pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8,
|
||||
cache_root: []const u8) Builder
|
||||
{
|
||||
var self = Builder {
|
||||
pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder {
|
||||
var self = Builder{
|
||||
.zig_exe = zig_exe,
|
||||
.build_root = build_root,
|
||||
.cache_root = os.path.relative(allocator, build_root, cache_root) catch unreachable,
|
||||
@ -112,12 +110,12 @@ pub const Builder = struct {
|
||||
.lib_dir = undefined,
|
||||
.exe_dir = undefined,
|
||||
.installed_files = ArrayList([]const u8).init(allocator),
|
||||
.uninstall_tls = TopLevelStep {
|
||||
.uninstall_tls = TopLevelStep{
|
||||
.step = Step.init("uninstall", allocator, makeUninstall),
|
||||
.description = "Remove build artifacts from prefix path",
|
||||
},
|
||||
.have_uninstall_step = false,
|
||||
.install_tls = TopLevelStep {
|
||||
.install_tls = TopLevelStep{
|
||||
.step = Step.initNoOp("install", allocator),
|
||||
.description = "Copy build artifacts to prefix path",
|
||||
},
|
||||
@ -151,9 +149,7 @@ pub const Builder = struct {
|
||||
return LibExeObjStep.createObject(self, name, root_src);
|
||||
}
|
||||
|
||||
pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8,
|
||||
ver: &const Version) &LibExeObjStep
|
||||
{
|
||||
pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8, ver: &const Version) &LibExeObjStep {
|
||||
return LibExeObjStep.createSharedLibrary(self, name, root_src, ver);
|
||||
}
|
||||
|
||||
@ -163,7 +159,7 @@ pub const Builder = struct {
|
||||
|
||||
pub fn addTest(self: &Builder, root_src: []const u8) &TestStep {
|
||||
const test_step = self.allocator.create(TestStep) catch unreachable;
|
||||
*test_step = TestStep.init(self, root_src);
|
||||
test_step.* = TestStep.init(self, root_src);
|
||||
return test_step;
|
||||
}
|
||||
|
||||
@ -190,33 +186,31 @@ pub const Builder = struct {
|
||||
}
|
||||
|
||||
/// ::argv is copied.
|
||||
pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
|
||||
argv: []const []const u8) &CommandStep
|
||||
{
|
||||
pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) &CommandStep {
|
||||
return CommandStep.create(self, cwd, env_map, argv);
|
||||
}
|
||||
|
||||
pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) &WriteFileStep {
|
||||
const write_file_step = self.allocator.create(WriteFileStep) catch unreachable;
|
||||
*write_file_step = WriteFileStep.init(self, file_path, data);
|
||||
write_file_step.* = WriteFileStep.init(self, file_path, data);
|
||||
return write_file_step;
|
||||
}
|
||||
|
||||
pub fn addLog(self: &Builder, comptime format: []const u8, args: ...) &LogStep {
|
||||
const data = self.fmt(format, args);
|
||||
const log_step = self.allocator.create(LogStep) catch unreachable;
|
||||
*log_step = LogStep.init(self, data);
|
||||
log_step.* = LogStep.init(self, data);
|
||||
return log_step;
|
||||
}
|
||||
|
||||
pub fn addRemoveDirTree(self: &Builder, dir_path: []const u8) &RemoveDirStep {
|
||||
const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable;
|
||||
*remove_dir_step = RemoveDirStep.init(self, dir_path);
|
||||
remove_dir_step.* = RemoveDirStep.init(self, dir_path);
|
||||
return remove_dir_step;
|
||||
}
|
||||
|
||||
pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) Version {
|
||||
return Version {
|
||||
return Version{
|
||||
.major = major,
|
||||
.minor = minor,
|
||||
.patch = patch,
|
||||
@ -254,8 +248,7 @@ pub const Builder = struct {
|
||||
}
|
||||
|
||||
pub fn getInstallStep(self: &Builder) &Step {
|
||||
if (self.have_install_step)
|
||||
return &self.install_tls.step;
|
||||
if (self.have_install_step) return &self.install_tls.step;
|
||||
|
||||
self.top_level_steps.append(&self.install_tls) catch unreachable;
|
||||
self.have_install_step = true;
|
||||
@ -263,8 +256,7 @@ pub const Builder = struct {
|
||||
}
|
||||
|
||||
pub fn getUninstallStep(self: &Builder) &Step {
|
||||
if (self.have_uninstall_step)
|
||||
return &self.uninstall_tls.step;
|
||||
if (self.have_uninstall_step) return &self.uninstall_tls.step;
|
||||
|
||||
self.top_level_steps.append(&self.uninstall_tls) catch unreachable;
|
||||
self.have_uninstall_step = true;
|
||||
@ -360,7 +352,7 @@ pub const Builder = struct {
|
||||
|
||||
pub fn option(self: &Builder, comptime T: type, name: []const u8, description: []const u8) ?T {
|
||||
const type_id = comptime typeToEnum(T);
|
||||
const available_option = AvailableOption {
|
||||
const available_option = AvailableOption{
|
||||
.name = name,
|
||||
.type_id = type_id,
|
||||
.description = description,
|
||||
@ -413,7 +405,7 @@ pub const Builder = struct {
|
||||
|
||||
pub fn step(self: &Builder, name: []const u8, description: []const u8) &Step {
|
||||
const step_info = self.allocator.create(TopLevelStep) catch unreachable;
|
||||
*step_info = TopLevelStep {
|
||||
step_info.* = TopLevelStep{
|
||||
.step = Step.initNoOp(name, self.allocator),
|
||||
.description = description,
|
||||
};
|
||||
@ -446,9 +438,9 @@ pub const Builder = struct {
|
||||
}
|
||||
|
||||
pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) bool {
|
||||
if (self.user_input_options.put(name, UserInputOption {
|
||||
if (self.user_input_options.put(name, UserInputOption{
|
||||
.name = name,
|
||||
.value = UserValue { .Scalar = value },
|
||||
.value = UserValue{ .Scalar = value },
|
||||
.used = false,
|
||||
}) catch unreachable) |*prev_value| {
|
||||
// option already exists
|
||||
@ -458,18 +450,18 @@ pub const Builder = struct {
|
||||
var list = ArrayList([]const u8).init(self.allocator);
|
||||
list.append(s) catch unreachable;
|
||||
list.append(value) catch unreachable;
|
||||
_ = self.user_input_options.put(name, UserInputOption {
|
||||
_ = self.user_input_options.put(name, UserInputOption{
|
||||
.name = name,
|
||||
.value = UserValue { .List = list },
|
||||
.value = UserValue{ .List = list },
|
||||
.used = false,
|
||||
}) catch unreachable;
|
||||
},
|
||||
UserValue.List => |*list| {
|
||||
// append to the list
|
||||
list.append(value) catch unreachable;
|
||||
_ = self.user_input_options.put(name, UserInputOption {
|
||||
_ = self.user_input_options.put(name, UserInputOption{
|
||||
.name = name,
|
||||
.value = UserValue { .List = *list },
|
||||
.value = UserValue{ .List = list.* },
|
||||
.used = false,
|
||||
}) catch unreachable;
|
||||
},
|
||||
@ -483,9 +475,9 @@ pub const Builder = struct {
|
||||
}
|
||||
|
||||
pub fn addUserInputFlag(self: &Builder, name: []const u8) bool {
|
||||
if (self.user_input_options.put(name, UserInputOption {
|
||||
if (self.user_input_options.put(name, UserInputOption{
|
||||
.name = name,
|
||||
.value = UserValue {.Flag = {} },
|
||||
.value = UserValue{ .Flag = {} },
|
||||
.used = false,
|
||||
}) catch unreachable) |*prev_value| {
|
||||
switch (prev_value.value) {
|
||||
@ -556,9 +548,7 @@ pub const Builder = struct {
|
||||
warn("\n");
|
||||
}
|
||||
|
||||
fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
|
||||
argv: []const []const u8) !void
|
||||
{
|
||||
fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) !void {
|
||||
if (self.verbose) {
|
||||
printCmd(cwd, argv);
|
||||
}
|
||||
@ -617,7 +607,7 @@ pub const Builder = struct {
|
||||
self.pushInstalledFile(full_dest_path);
|
||||
|
||||
const install_step = self.allocator.create(InstallFileStep) catch unreachable;
|
||||
*install_step = InstallFileStep.init(self, src_path, full_dest_path);
|
||||
install_step.* = InstallFileStep.init(self, src_path, full_dest_path);
|
||||
return install_step;
|
||||
}
|
||||
|
||||
@ -659,25 +649,23 @@ pub const Builder = struct {
|
||||
if (builtin.environ == builtin.Environ.msvc) {
|
||||
return "cl.exe";
|
||||
} else {
|
||||
return os.getEnvVarOwned(self.allocator, "CC") catch |err|
|
||||
return os.getEnvVarOwned(self.allocator, "CC") catch |err|
|
||||
if (err == error.EnvironmentVariableNotFound)
|
||||
([]const u8)("cc")
|
||||
else
|
||||
debug.panic("Unable to get environment variable: {}", err)
|
||||
;
|
||||
debug.panic("Unable to get environment variable: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 {
|
||||
// TODO report error for ambiguous situations
|
||||
const exe_extension = (Target { .Native = {}}).exeFileExt();
|
||||
const exe_extension = (Target{ .Native = {} }).exeFileExt();
|
||||
for (self.search_prefixes.toSliceConst()) |search_prefix| {
|
||||
for (names) |name| {
|
||||
if (os.path.isAbsolute(name)) {
|
||||
return name;
|
||||
}
|
||||
const full_path = try os.path.join(self.allocator, search_prefix, "bin",
|
||||
self.fmt("{}{}", name, exe_extension));
|
||||
const full_path = try os.path.join(self.allocator, search_prefix, "bin", self.fmt("{}{}", name, exe_extension));
|
||||
if (os.path.real(self.allocator, full_path)) |real_path| {
|
||||
return real_path;
|
||||
} else |_| {
|
||||
@ -761,7 +749,7 @@ pub const Target = union(enum) {
|
||||
Cross: CrossTarget,
|
||||
|
||||
pub fn oFileExt(self: &const Target) []const u8 {
|
||||
const environ = switch (*self) {
|
||||
const environ = switch (self.*) {
|
||||
Target.Native => builtin.environ,
|
||||
Target.Cross => |t| t.environ,
|
||||
};
|
||||
@ -786,7 +774,7 @@ pub const Target = union(enum) {
|
||||
}
|
||||
|
||||
pub fn getOs(self: &const Target) builtin.Os {
|
||||
return switch (*self) {
|
||||
return switch (self.*) {
|
||||
Target.Native => builtin.os,
|
||||
Target.Cross => |t| t.os,
|
||||
};
|
||||
@ -794,7 +782,8 @@ pub const Target = union(enum) {
|
||||
|
||||
pub fn isDarwin(self: &const Target) bool {
|
||||
return switch (self.getOs()) {
|
||||
builtin.Os.ios, builtin.Os.macosx => true,
|
||||
builtin.Os.ios,
|
||||
builtin.Os.macosx => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
@ -860,61 +849,57 @@ pub const LibExeObjStep = struct {
|
||||
Obj,
|
||||
};
|
||||
|
||||
pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8,
|
||||
ver: &const Version) &LibExeObjStep
|
||||
{
|
||||
pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8, ver: &const Version) &LibExeObjStep {
|
||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||
*self = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
|
||||
self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn createCSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) &LibExeObjStep {
|
||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||
*self = initC(builder, name, Kind.Lib, version, false);
|
||||
self.* = initC(builder, name, Kind.Lib, version, false);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep {
|
||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||
*self = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
|
||||
self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn createCStaticLibrary(builder: &Builder, name: []const u8) &LibExeObjStep {
|
||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||
*self = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true);
|
||||
self.* = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) &LibExeObjStep {
|
||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||
*self = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
|
||||
self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn createCObject(builder: &Builder, name: []const u8, src: []const u8) &LibExeObjStep {
|
||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||
*self = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false);
|
||||
self.* = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false);
|
||||
self.object_src = src;
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep {
|
||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||
*self = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0));
|
||||
self.* = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0));
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn createCExecutable(builder: &Builder, name: []const u8) &LibExeObjStep {
|
||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||
*self = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false);
|
||||
self.* = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false);
|
||||
return self;
|
||||
}
|
||||
|
||||
fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind,
|
||||
static: bool, ver: &const Version) LibExeObjStep
|
||||
{
|
||||
var self = LibExeObjStep {
|
||||
fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, static: bool, ver: &const Version) LibExeObjStep {
|
||||
var self = LibExeObjStep{
|
||||
.strip = false,
|
||||
.builder = builder,
|
||||
.verbose_link = false,
|
||||
@ -930,7 +915,7 @@ pub const LibExeObjStep = struct {
|
||||
.step = Step.init(name, builder.allocator, make),
|
||||
.output_path = null,
|
||||
.output_h_path = null,
|
||||
.version = *ver,
|
||||
.version = ver.*,
|
||||
.out_filename = undefined,
|
||||
.out_h_filename = builder.fmt("{}.h", name),
|
||||
.major_only_filename = undefined,
|
||||
@ -953,11 +938,11 @@ pub const LibExeObjStep = struct {
|
||||
}
|
||||
|
||||
fn initC(builder: &Builder, name: []const u8, kind: Kind, version: &const Version, static: bool) LibExeObjStep {
|
||||
var self = LibExeObjStep {
|
||||
var self = LibExeObjStep{
|
||||
.builder = builder,
|
||||
.name = name,
|
||||
.kind = kind,
|
||||
.version = *version,
|
||||
.version = version.*,
|
||||
.static = static,
|
||||
.target = Target.Native,
|
||||
.cflags = ArrayList([]const u8).init(builder.allocator),
|
||||
@ -1005,9 +990,9 @@ pub const LibExeObjStep = struct {
|
||||
self.out_filename = self.builder.fmt("lib{}.a", self.name);
|
||||
} else {
|
||||
switch (self.target.getOs()) {
|
||||
builtin.Os.ios, builtin.Os.macosx => {
|
||||
self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib",
|
||||
self.name, self.version.major, self.version.minor, self.version.patch);
|
||||
builtin.Os.ios,
|
||||
builtin.Os.macosx => {
|
||||
self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch);
|
||||
self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major);
|
||||
self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name);
|
||||
},
|
||||
@ -1015,8 +1000,7 @@ pub const LibExeObjStep = struct {
|
||||
self.out_filename = self.builder.fmt("{}.dll", self.name);
|
||||
},
|
||||
else => {
|
||||
self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}",
|
||||
self.name, self.version.major, self.version.minor, self.version.patch);
|
||||
self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", self.name, self.version.major, self.version.minor, self.version.patch);
|
||||
self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major);
|
||||
self.name_only_filename = self.builder.fmt("lib{}.so", self.name);
|
||||
},
|
||||
@ -1026,16 +1010,12 @@ pub const LibExeObjStep = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os,
|
||||
target_environ: builtin.Environ) void
|
||||
{
|
||||
self.target = Target {
|
||||
.Cross = CrossTarget {
|
||||
.arch = target_arch,
|
||||
.os = target_os,
|
||||
.environ = target_environ,
|
||||
}
|
||||
};
|
||||
pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
|
||||
self.target = Target{ .Cross = CrossTarget{
|
||||
.arch = target_arch,
|
||||
.os = target_os,
|
||||
.environ = target_environ,
|
||||
} };
|
||||
self.computeOutFileNames();
|
||||
}
|
||||
|
||||
@ -1159,7 +1139,7 @@ pub const LibExeObjStep = struct {
|
||||
pub fn addPackagePath(self: &LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void {
|
||||
assert(self.is_zig);
|
||||
|
||||
self.packages.append(Pkg {
|
||||
self.packages.append(Pkg{
|
||||
.name = name,
|
||||
.path = pkg_index_path,
|
||||
}) catch unreachable;
|
||||
@ -1343,8 +1323,7 @@ pub const LibExeObjStep = struct {
|
||||
try builder.spawnChild(zig_args.toSliceConst());
|
||||
|
||||
if (self.kind == Kind.Lib and !self.static and self.target.wantSharedLibSymLinks()) {
|
||||
try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename,
|
||||
self.name_only_filename);
|
||||
try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1373,7 +1352,8 @@ pub const LibExeObjStep = struct {
|
||||
args.append("ssp-buffer-size=4") catch unreachable;
|
||||
}
|
||||
},
|
||||
builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {
|
||||
builtin.Mode.ReleaseFast,
|
||||
builtin.Mode.ReleaseSmall => {
|
||||
args.append("-O2") catch unreachable;
|
||||
args.append("-fno-stack-protector") catch unreachable;
|
||||
},
|
||||
@ -1505,8 +1485,7 @@ pub const LibExeObjStep = struct {
|
||||
}
|
||||
|
||||
if (!is_darwin) {
|
||||
const rpath_arg = builder.fmt("-Wl,-rpath,{}",
|
||||
os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable);
|
||||
const rpath_arg = builder.fmt("-Wl,-rpath,{}", os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable);
|
||||
defer builder.allocator.free(rpath_arg);
|
||||
cc_args.append(rpath_arg) catch unreachable;
|
||||
|
||||
@ -1535,8 +1514,7 @@ pub const LibExeObjStep = struct {
|
||||
try builder.spawnChild(cc_args.toSliceConst());
|
||||
|
||||
if (self.target.wantSharedLibSymLinks()) {
|
||||
try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename,
|
||||
self.name_only_filename);
|
||||
try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1581,8 +1559,7 @@ pub const LibExeObjStep = struct {
|
||||
cc_args.append("-o") catch unreachable;
|
||||
cc_args.append(output_path) catch unreachable;
|
||||
|
||||
const rpath_arg = builder.fmt("-Wl,-rpath,{}",
|
||||
os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable);
|
||||
const rpath_arg = builder.fmt("-Wl,-rpath,{}", os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable);
|
||||
defer builder.allocator.free(rpath_arg);
|
||||
cc_args.append(rpath_arg) catch unreachable;
|
||||
|
||||
@ -1635,7 +1612,7 @@ pub const TestStep = struct {
|
||||
|
||||
pub fn init(builder: &Builder, root_src: []const u8) TestStep {
|
||||
const step_name = builder.fmt("test {}", root_src);
|
||||
return TestStep {
|
||||
return TestStep{
|
||||
.step = Step.init(step_name, builder.allocator, make),
|
||||
.builder = builder,
|
||||
.root_src = root_src,
|
||||
@ -1644,7 +1621,7 @@ pub const TestStep = struct {
|
||||
.name_prefix = "",
|
||||
.filter = null,
|
||||
.link_libs = BufSet.init(builder.allocator),
|
||||
.target = Target { .Native = {} },
|
||||
.target = Target{ .Native = {} },
|
||||
.exec_cmd_args = null,
|
||||
.include_dirs = ArrayList([]const u8).init(builder.allocator),
|
||||
};
|
||||
@ -1674,16 +1651,12 @@ pub const TestStep = struct {
|
||||
self.filter = text;
|
||||
}
|
||||
|
||||
pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os,
|
||||
target_environ: builtin.Environ) void
|
||||
{
|
||||
self.target = Target {
|
||||
.Cross = CrossTarget {
|
||||
.arch = target_arch,
|
||||
.os = target_os,
|
||||
.environ = target_environ,
|
||||
}
|
||||
};
|
||||
pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
|
||||
self.target = Target{ .Cross = CrossTarget{
|
||||
.arch = target_arch,
|
||||
.os = target_os,
|
||||
.environ = target_environ,
|
||||
} };
|
||||
}
|
||||
|
||||
pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) void {
|
||||
@ -1789,11 +1762,9 @@ pub const CommandStep = struct {
|
||||
env_map: &const BufMap,
|
||||
|
||||
/// ::argv is copied.
|
||||
pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
|
||||
argv: []const []const u8) &CommandStep
|
||||
{
|
||||
pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) &CommandStep {
|
||||
const self = builder.allocator.create(CommandStep) catch unreachable;
|
||||
*self = CommandStep {
|
||||
self.* = CommandStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(argv[0], builder.allocator, make),
|
||||
.argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,
|
||||
@ -1828,7 +1799,7 @@ const InstallArtifactStep = struct {
|
||||
LibExeObjStep.Kind.Exe => builder.exe_dir,
|
||||
LibExeObjStep.Kind.Lib => builder.lib_dir,
|
||||
};
|
||||
*self = Self {
|
||||
self.* = Self{
|
||||
.builder = builder,
|
||||
.step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),
|
||||
.artifact = artifact,
|
||||
@ -1837,10 +1808,8 @@ const InstallArtifactStep = struct {
|
||||
self.step.dependOn(&artifact.step);
|
||||
builder.pushInstalledFile(self.dest_file);
|
||||
if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) {
|
||||
builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir,
|
||||
artifact.major_only_filename) catch unreachable);
|
||||
builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir,
|
||||
artifact.name_only_filename) catch unreachable);
|
||||
builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.major_only_filename) catch unreachable);
|
||||
builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.name_only_filename) catch unreachable);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -1859,8 +1828,7 @@ const InstallArtifactStep = struct {
|
||||
};
|
||||
try builder.copyFileMode(self.artifact.getOutputPath(), self.dest_file, mode);
|
||||
if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) {
|
||||
try doAtomicSymLinks(builder.allocator, self.dest_file,
|
||||
self.artifact.major_only_filename, self.artifact.name_only_filename);
|
||||
try doAtomicSymLinks(builder.allocator, self.dest_file, self.artifact.major_only_filename, self.artifact.name_only_filename);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1872,7 +1840,7 @@ pub const InstallFileStep = struct {
|
||||
dest_path: []const u8,
|
||||
|
||||
pub fn init(builder: &Builder, src_path: []const u8, dest_path: []const u8) InstallFileStep {
|
||||
return InstallFileStep {
|
||||
return InstallFileStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make),
|
||||
.src_path = src_path,
|
||||
@ -1893,7 +1861,7 @@ pub const WriteFileStep = struct {
|
||||
data: []const u8,
|
||||
|
||||
pub fn init(builder: &Builder, file_path: []const u8, data: []const u8) WriteFileStep {
|
||||
return WriteFileStep {
|
||||
return WriteFileStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(builder.fmt("writefile {}", file_path), builder.allocator, make),
|
||||
.file_path = file_path,
|
||||
@ -1922,7 +1890,7 @@ pub const LogStep = struct {
|
||||
data: []const u8,
|
||||
|
||||
pub fn init(builder: &Builder, data: []const u8) LogStep {
|
||||
return LogStep {
|
||||
return LogStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(builder.fmt("log {}", data), builder.allocator, make),
|
||||
.data = data,
|
||||
@ -1941,7 +1909,7 @@ pub const RemoveDirStep = struct {
|
||||
dir_path: []const u8,
|
||||
|
||||
pub fn init(builder: &Builder, dir_path: []const u8) RemoveDirStep {
|
||||
return RemoveDirStep {
|
||||
return RemoveDirStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(builder.fmt("RemoveDir {}", dir_path), builder.allocator, make),
|
||||
.dir_path = dir_path,
|
||||
@ -1966,8 +1934,8 @@ pub const Step = struct {
|
||||
loop_flag: bool,
|
||||
done_flag: bool,
|
||||
|
||||
pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)error!void) Step {
|
||||
return Step {
|
||||
pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn(&Step) error!void) Step {
|
||||
return Step{
|
||||
.name = name,
|
||||
.makeFn = makeFn,
|
||||
.dependencies = ArrayList(&Step).init(allocator),
|
||||
@ -1980,8 +1948,7 @@ pub const Step = struct {
|
||||
}
|
||||
|
||||
pub fn make(self: &Step) !void {
|
||||
if (self.done_flag)
|
||||
return;
|
||||
if (self.done_flag) return;
|
||||
|
||||
try self.makeFn(self);
|
||||
self.done_flag = true;
|
||||
@ -1994,9 +1961,7 @@ pub const Step = struct {
|
||||
fn makeNoOp(self: &Step) error!void {}
|
||||
};
|
||||
|
||||
fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8,
|
||||
filename_name_only: []const u8) !void
|
||||
{
|
||||
fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, filename_name_only: []const u8) !void {
|
||||
const out_dir = os.path.dirname(output_path);
|
||||
const out_basename = os.path.basename(output_path);
|
||||
// sym link for libfoo.so.1 to libfoo.so.1.2.3
|
||||
|
@ -6,11 +6,23 @@ const builtin = @import("builtin");
|
||||
const htest = @import("test.zig");
|
||||
|
||||
const RoundParam = struct {
|
||||
a: usize, b: usize, c: usize, d: usize, x: usize, y: usize,
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
d: usize,
|
||||
x: usize,
|
||||
y: usize,
|
||||
};
|
||||
|
||||
fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam {
|
||||
return RoundParam { .a = a, .b = b, .c = c, .d = d, .x = x, .y = y, };
|
||||
return RoundParam{
|
||||
.a = a,
|
||||
.b = b,
|
||||
.c = c,
|
||||
.d = d,
|
||||
.x = x,
|
||||
.y = y,
|
||||
};
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
@ -19,145 +31,153 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam {
|
||||
pub const Blake2s224 = Blake2s(224);
|
||||
pub const Blake2s256 = Blake2s(256);
|
||||
|
||||
fn Blake2s(comptime out_len: usize) type { return struct {
|
||||
const Self = this;
|
||||
const block_size = 64;
|
||||
const digest_size = out_len / 8;
|
||||
fn Blake2s(comptime out_len: usize) type {
|
||||
return struct {
|
||||
const Self = this;
|
||||
const block_size = 64;
|
||||
const digest_size = out_len / 8;
|
||||
|
||||
const iv = [8]u32 {
|
||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
|
||||
};
|
||||
const iv = [8]u32{
|
||||
0x6A09E667,
|
||||
0xBB67AE85,
|
||||
0x3C6EF372,
|
||||
0xA54FF53A,
|
||||
0x510E527F,
|
||||
0x9B05688C,
|
||||
0x1F83D9AB,
|
||||
0x5BE0CD19,
|
||||
};
|
||||
|
||||
const sigma = [10][16]u8 {
|
||||
[]const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
[]const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
|
||||
[]const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
|
||||
[]const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
|
||||
[]const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
|
||||
[]const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
|
||||
[]const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
|
||||
[]const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
|
||||
[]const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
|
||||
[]const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
|
||||
};
|
||||
const sigma = [10][16]u8{
|
||||
[]const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
[]const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
|
||||
[]const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
|
||||
[]const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
|
||||
[]const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
|
||||
[]const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
|
||||
[]const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
|
||||
[]const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
|
||||
[]const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
|
||||
[]const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
|
||||
};
|
||||
|
||||
h: [8]u32,
|
||||
t: u64,
|
||||
// Streaming cache
|
||||
buf: [64]u8,
|
||||
buf_len: u8,
|
||||
h: [8]u32,
|
||||
t: u64,
|
||||
// Streaming cache
|
||||
buf: [64]u8,
|
||||
buf_len: u8,
|
||||
|
||||
pub fn init() Self {
|
||||
debug.assert(8 <= out_len and out_len <= 512);
|
||||
pub fn init() Self {
|
||||
debug.assert(8 <= out_len and out_len <= 512);
|
||||
|
||||
var s: Self = undefined;
|
||||
s.reset();
|
||||
return s;
|
||||
}
|
||||
var s: Self = undefined;
|
||||
s.reset();
|
||||
return s;
|
||||
}
|
||||
|
||||
pub fn reset(d: &Self) void {
|
||||
mem.copy(u32, d.h[0..], iv[0..]);
|
||||
pub fn reset(d: &Self) void {
|
||||
mem.copy(u32, d.h[0..], iv[0..]);
|
||||
|
||||
// No key plus default parameters
|
||||
d.h[0] ^= 0x01010000 ^ u32(out_len >> 3);
|
||||
d.t = 0;
|
||||
d.buf_len = 0;
|
||||
}
|
||||
|
||||
pub fn hash(b: []const u8, out: []u8) void {
|
||||
var d = Self.init();
|
||||
d.update(b);
|
||||
d.final(out);
|
||||
}
|
||||
|
||||
pub fn update(d: &Self, b: []const u8) void {
|
||||
var off: usize = 0;
|
||||
|
||||
// Partial buffer exists from previous update. Copy into buffer then hash.
|
||||
if (d.buf_len != 0 and d.buf_len + b.len > 64) {
|
||||
off += 64 - d.buf_len;
|
||||
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
|
||||
d.t += 64;
|
||||
d.round(d.buf[0..], false);
|
||||
// No key plus default parameters
|
||||
d.h[0] ^= 0x01010000 ^ u32(out_len >> 3);
|
||||
d.t = 0;
|
||||
d.buf_len = 0;
|
||||
}
|
||||
|
||||
// Full middle blocks.
|
||||
while (off + 64 <= b.len) : (off += 64) {
|
||||
d.t += 64;
|
||||
d.round(b[off..off + 64], false);
|
||||
pub fn hash(b: []const u8, out: []u8) void {
|
||||
var d = Self.init();
|
||||
d.update(b);
|
||||
d.final(out);
|
||||
}
|
||||
|
||||
// Copy any remainder for next pass.
|
||||
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
|
||||
d.buf_len += u8(b[off..].len);
|
||||
}
|
||||
pub fn update(d: &Self, b: []const u8) void {
|
||||
var off: usize = 0;
|
||||
|
||||
pub fn final(d: &Self, out: []u8) void {
|
||||
debug.assert(out.len >= out_len / 8);
|
||||
// Partial buffer exists from previous update. Copy into buffer then hash.
|
||||
if (d.buf_len != 0 and d.buf_len + b.len > 64) {
|
||||
off += 64 - d.buf_len;
|
||||
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
|
||||
d.t += 64;
|
||||
d.round(d.buf[0..], false);
|
||||
d.buf_len = 0;
|
||||
}
|
||||
|
||||
mem.set(u8, d.buf[d.buf_len..], 0);
|
||||
d.t += d.buf_len;
|
||||
d.round(d.buf[0..], true);
|
||||
// Full middle blocks.
|
||||
while (off + 64 <= b.len) : (off += 64) {
|
||||
d.t += 64;
|
||||
d.round(b[off..off + 64], false);
|
||||
}
|
||||
|
||||
const rr = d.h[0 .. out_len / 32];
|
||||
|
||||
for (rr) |s, j| {
|
||||
mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Little);
|
||||
}
|
||||
}
|
||||
|
||||
fn round(d: &Self, b: []const u8, last: bool) void {
|
||||
debug.assert(b.len == 64);
|
||||
|
||||
var m: [16]u32 = undefined;
|
||||
var v: [16]u32 = undefined;
|
||||
|
||||
for (m) |*r, i| {
|
||||
*r = mem.readIntLE(u32, b[4*i .. 4*i + 4]);
|
||||
// Copy any remainder for next pass.
|
||||
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
|
||||
d.buf_len += u8(b[off..].len);
|
||||
}
|
||||
|
||||
var k: usize = 0;
|
||||
while (k < 8) : (k += 1) {
|
||||
v[k] = d.h[k];
|
||||
v[k+8] = iv[k];
|
||||
}
|
||||
pub fn final(d: &Self, out: []u8) void {
|
||||
debug.assert(out.len >= out_len / 8);
|
||||
|
||||
v[12] ^= @truncate(u32, d.t);
|
||||
v[13] ^= u32(d.t >> 32);
|
||||
if (last) v[14] = ~v[14];
|
||||
mem.set(u8, d.buf[d.buf_len..], 0);
|
||||
d.t += d.buf_len;
|
||||
d.round(d.buf[0..], true);
|
||||
|
||||
const rounds = comptime []RoundParam {
|
||||
Rp(0, 4, 8, 12, 0, 1),
|
||||
Rp(1, 5, 9, 13, 2, 3),
|
||||
Rp(2, 6, 10, 14, 4, 5),
|
||||
Rp(3, 7, 11, 15, 6, 7),
|
||||
Rp(0, 5, 10, 15, 8, 9),
|
||||
Rp(1, 6, 11, 12, 10, 11),
|
||||
Rp(2, 7, 8, 13, 12, 13),
|
||||
Rp(3, 4, 9, 14, 14, 15),
|
||||
};
|
||||
const rr = d.h[0..out_len / 32];
|
||||
|
||||
comptime var j: usize = 0;
|
||||
inline while (j < 10) : (j += 1) {
|
||||
inline for (rounds) |r| {
|
||||
v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]];
|
||||
v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16));
|
||||
v[r.c] = v[r.c] +% v[r.d];
|
||||
v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12));
|
||||
v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]];
|
||||
v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8));
|
||||
v[r.c] = v[r.c] +% v[r.d];
|
||||
v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7));
|
||||
for (rr) |s, j| {
|
||||
mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Little);
|
||||
}
|
||||
}
|
||||
|
||||
for (d.h) |*r, i| {
|
||||
*r ^= v[i] ^ v[i + 8];
|
||||
fn round(d: &Self, b: []const u8, last: bool) void {
|
||||
debug.assert(b.len == 64);
|
||||
|
||||
var m: [16]u32 = undefined;
|
||||
var v: [16]u32 = undefined;
|
||||
|
||||
for (m) |*r, i| {
|
||||
r.* = mem.readIntLE(u32, b[4 * i..4 * i + 4]);
|
||||
}
|
||||
|
||||
var k: usize = 0;
|
||||
while (k < 8) : (k += 1) {
|
||||
v[k] = d.h[k];
|
||||
v[k + 8] = iv[k];
|
||||
}
|
||||
|
||||
v[12] ^= @truncate(u32, d.t);
|
||||
v[13] ^= u32(d.t >> 32);
|
||||
if (last) v[14] = ~v[14];
|
||||
|
||||
const rounds = comptime []RoundParam{
|
||||
Rp(0, 4, 8, 12, 0, 1),
|
||||
Rp(1, 5, 9, 13, 2, 3),
|
||||
Rp(2, 6, 10, 14, 4, 5),
|
||||
Rp(3, 7, 11, 15, 6, 7),
|
||||
Rp(0, 5, 10, 15, 8, 9),
|
||||
Rp(1, 6, 11, 12, 10, 11),
|
||||
Rp(2, 7, 8, 13, 12, 13),
|
||||
Rp(3, 4, 9, 14, 14, 15),
|
||||
};
|
||||
|
||||
comptime var j: usize = 0;
|
||||
inline while (j < 10) : (j += 1) {
|
||||
inline for (rounds) |r| {
|
||||
v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]];
|
||||
v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16));
|
||||
v[r.c] = v[r.c] +% v[r.d];
|
||||
v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12));
|
||||
v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]];
|
||||
v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8));
|
||||
v[r.c] = v[r.c] +% v[r.d];
|
||||
v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7));
|
||||
}
|
||||
}
|
||||
|
||||
for (d.h) |*r, i| {
|
||||
r.* ^= v[i] ^ v[i + 8];
|
||||
}
|
||||
}
|
||||
}
|
||||
};}
|
||||
};
|
||||
}
|
||||
|
||||
test "blake2s224 single" {
|
||||
const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4";
|
||||
@ -230,7 +250,7 @@ test "blake2s256 streaming" {
|
||||
}
|
||||
|
||||
test "blake2s256 aligned final" {
|
||||
var block = []u8 {0} ** Blake2s256.block_size;
|
||||
var block = []u8{0} ** Blake2s256.block_size;
|
||||
var out: [Blake2s256.digest_size]u8 = undefined;
|
||||
|
||||
var h = Blake2s256.init();
|
||||
@ -238,154 +258,363 @@ test "blake2s256 aligned final" {
|
||||
h.final(out[0..]);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////
|
||||
// Blake2b
|
||||
|
||||
pub const Blake2b384 = Blake2b(384);
|
||||
pub const Blake2b512 = Blake2b(512);
|
||||
|
||||
fn Blake2b(comptime out_len: usize) type { return struct {
|
||||
const Self = this;
|
||||
const block_size = 128;
|
||||
const digest_size = out_len / 8;
|
||||
fn Blake2b(comptime out_len: usize) type {
|
||||
return struct {
|
||||
const Self = this;
|
||||
const block_size = 128;
|
||||
const digest_size = out_len / 8;
|
||||
|
||||
const iv = [8]u64 {
|
||||
0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
|
||||
0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
|
||||
0x510e527fade682d1, 0x9b05688c2b3e6c1f,
|
||||
0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
|
||||
};
|
||||
const iv = [8]u64{
|
||||
0x6a09e667f3bcc908,
|
||||
0xbb67ae8584caa73b,
|
||||
0x3c6ef372fe94f82b,
|
||||
0xa54ff53a5f1d36f1,
|
||||
0x510e527fade682d1,
|
||||
0x9b05688c2b3e6c1f,
|
||||
0x1f83d9abfb41bd6b,
|
||||
0x5be0cd19137e2179,
|
||||
};
|
||||
|
||||
const sigma = [12][16]u8 {
|
||||
[]const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
[]const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
|
||||
[]const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
|
||||
[]const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
|
||||
[]const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
|
||||
[]const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
|
||||
[]const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
|
||||
[]const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
|
||||
[]const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
|
||||
[]const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 },
|
||||
[]const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
[]const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
|
||||
};
|
||||
const sigma = [12][16]u8{
|
||||
[]const u8{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
},
|
||||
[]const u8{
|
||||
14,
|
||||
10,
|
||||
4,
|
||||
8,
|
||||
9,
|
||||
15,
|
||||
13,
|
||||
6,
|
||||
1,
|
||||
12,
|
||||
0,
|
||||
2,
|
||||
11,
|
||||
7,
|
||||
5,
|
||||
3,
|
||||
},
|
||||
[]const u8{
|
||||
11,
|
||||
8,
|
||||
12,
|
||||
0,
|
||||
5,
|
||||
2,
|
||||
15,
|
||||
13,
|
||||
10,
|
||||
14,
|
||||
3,
|
||||
6,
|
||||
7,
|
||||
1,
|
||||
9,
|
||||
4,
|
||||
},
|
||||
[]const u8{
|
||||
7,
|
||||
9,
|
||||
3,
|
||||
1,
|
||||
13,
|
||||
12,
|
||||
11,
|
||||
14,
|
||||
2,
|
||||
6,
|
||||
5,
|
||||
10,
|
||||
4,
|
||||
0,
|
||||
15,
|
||||
8,
|
||||
},
|
||||
[]const u8{
|
||||
9,
|
||||
0,
|
||||
5,
|
||||
7,
|
||||
2,
|
||||
4,
|
||||
10,
|
||||
15,
|
||||
14,
|
||||
1,
|
||||
11,
|
||||
12,
|
||||
6,
|
||||
8,
|
||||
3,
|
||||
13,
|
||||
},
|
||||
[]const u8{
|
||||
2,
|
||||
12,
|
||||
6,
|
||||
10,
|
||||
0,
|
||||
11,
|
||||
8,
|
||||
3,
|
||||
4,
|
||||
13,
|
||||
7,
|
||||
5,
|
||||
15,
|
||||
14,
|
||||
1,
|
||||
9,
|
||||
},
|
||||
[]const u8{
|
||||
12,
|
||||
5,
|
||||
1,
|
||||
15,
|
||||
14,
|
||||
13,
|
||||
4,
|
||||
10,
|
||||
0,
|
||||
7,
|
||||
6,
|
||||
3,
|
||||
9,
|
||||
2,
|
||||
8,
|
||||
11,
|
||||
},
|
||||
[]const u8{
|
||||
13,
|
||||
11,
|
||||
7,
|
||||
14,
|
||||
12,
|
||||
1,
|
||||
3,
|
||||
9,
|
||||
5,
|
||||
0,
|
||||
15,
|
||||
4,
|
||||
8,
|
||||
6,
|
||||
2,
|
||||
10,
|
||||
},
|
||||
[]const u8{
|
||||
6,
|
||||
15,
|
||||
14,
|
||||
9,
|
||||
11,
|
||||
3,
|
||||
0,
|
||||
8,
|
||||
12,
|
||||
2,
|
||||
13,
|
||||
7,
|
||||
1,
|
||||
4,
|
||||
10,
|
||||
5,
|
||||
},
|
||||
[]const u8{
|
||||
10,
|
||||
2,
|
||||
8,
|
||||
4,
|
||||
7,
|
||||
6,
|
||||
1,
|
||||
5,
|
||||
15,
|
||||
11,
|
||||
9,
|
||||
14,
|
||||
3,
|
||||
12,
|
||||
13,
|
||||
0,
|
||||
},
|
||||
[]const u8{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
},
|
||||
[]const u8{
|
||||
14,
|
||||
10,
|
||||
4,
|
||||
8,
|
||||
9,
|
||||
15,
|
||||
13,
|
||||
6,
|
||||
1,
|
||||
12,
|
||||
0,
|
||||
2,
|
||||
11,
|
||||
7,
|
||||
5,
|
||||
3,
|
||||
},
|
||||
};
|
||||
|
||||
h: [8]u64,
|
||||
t: u128,
|
||||
// Streaming cache
|
||||
buf: [128]u8,
|
||||
buf_len: u8,
|
||||
h: [8]u64,
|
||||
t: u128,
|
||||
// Streaming cache
|
||||
buf: [128]u8,
|
||||
buf_len: u8,
|
||||
|
||||
pub fn init() Self {
|
||||
debug.assert(8 <= out_len and out_len <= 512);
|
||||
pub fn init() Self {
|
||||
debug.assert(8 <= out_len and out_len <= 512);
|
||||
|
||||
var s: Self = undefined;
|
||||
s.reset();
|
||||
return s;
|
||||
}
|
||||
var s: Self = undefined;
|
||||
s.reset();
|
||||
return s;
|
||||
}
|
||||
|
||||
pub fn reset(d: &Self) void {
|
||||
mem.copy(u64, d.h[0..], iv[0..]);
|
||||
pub fn reset(d: &Self) void {
|
||||
mem.copy(u64, d.h[0..], iv[0..]);
|
||||
|
||||
// No key plus default parameters
|
||||
d.h[0] ^= 0x01010000 ^ (out_len >> 3);
|
||||
d.t = 0;
|
||||
d.buf_len = 0;
|
||||
}
|
||||
|
||||
pub fn hash(b: []const u8, out: []u8) void {
|
||||
var d = Self.init();
|
||||
d.update(b);
|
||||
d.final(out);
|
||||
}
|
||||
|
||||
pub fn update(d: &Self, b: []const u8) void {
|
||||
var off: usize = 0;
|
||||
|
||||
// Partial buffer exists from previous update. Copy into buffer then hash.
|
||||
if (d.buf_len != 0 and d.buf_len + b.len > 128) {
|
||||
off += 128 - d.buf_len;
|
||||
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
|
||||
d.t += 128;
|
||||
d.round(d.buf[0..], false);
|
||||
// No key plus default parameters
|
||||
d.h[0] ^= 0x01010000 ^ (out_len >> 3);
|
||||
d.t = 0;
|
||||
d.buf_len = 0;
|
||||
}
|
||||
|
||||
// Full middle blocks.
|
||||
while (off + 128 <= b.len) : (off += 128) {
|
||||
d.t += 128;
|
||||
d.round(b[off..off + 128], false);
|
||||
pub fn hash(b: []const u8, out: []u8) void {
|
||||
var d = Self.init();
|
||||
d.update(b);
|
||||
d.final(out);
|
||||
}
|
||||
|
||||
// Copy any remainder for next pass.
|
||||
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
|
||||
d.buf_len += u8(b[off..].len);
|
||||
}
|
||||
pub fn update(d: &Self, b: []const u8) void {
|
||||
var off: usize = 0;
|
||||
|
||||
pub fn final(d: &Self, out: []u8) void {
|
||||
mem.set(u8, d.buf[d.buf_len..], 0);
|
||||
d.t += d.buf_len;
|
||||
d.round(d.buf[0..], true);
|
||||
// Partial buffer exists from previous update. Copy into buffer then hash.
|
||||
if (d.buf_len != 0 and d.buf_len + b.len > 128) {
|
||||
off += 128 - d.buf_len;
|
||||
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
|
||||
d.t += 128;
|
||||
d.round(d.buf[0..], false);
|
||||
d.buf_len = 0;
|
||||
}
|
||||
|
||||
const rr = d.h[0 .. out_len / 64];
|
||||
// Full middle blocks.
|
||||
while (off + 128 <= b.len) : (off += 128) {
|
||||
d.t += 128;
|
||||
d.round(b[off..off + 128], false);
|
||||
}
|
||||
|
||||
for (rr) |s, j| {
|
||||
mem.writeInt(out[8*j .. 8*j + 8], s, builtin.Endian.Little);
|
||||
}
|
||||
}
|
||||
|
||||
fn round(d: &Self, b: []const u8, last: bool) void {
|
||||
debug.assert(b.len == 128);
|
||||
|
||||
var m: [16]u64 = undefined;
|
||||
var v: [16]u64 = undefined;
|
||||
|
||||
for (m) |*r, i| {
|
||||
*r = mem.readIntLE(u64, b[8*i .. 8*i + 8]);
|
||||
// Copy any remainder for next pass.
|
||||
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
|
||||
d.buf_len += u8(b[off..].len);
|
||||
}
|
||||
|
||||
var k: usize = 0;
|
||||
while (k < 8) : (k += 1) {
|
||||
v[k] = d.h[k];
|
||||
v[k+8] = iv[k];
|
||||
}
|
||||
pub fn final(d: &Self, out: []u8) void {
|
||||
mem.set(u8, d.buf[d.buf_len..], 0);
|
||||
d.t += d.buf_len;
|
||||
d.round(d.buf[0..], true);
|
||||
|
||||
v[12] ^= @truncate(u64, d.t);
|
||||
v[13] ^= u64(d.t >> 64);
|
||||
if (last) v[14] = ~v[14];
|
||||
const rr = d.h[0..out_len / 64];
|
||||
|
||||
const rounds = comptime []RoundParam {
|
||||
Rp(0, 4, 8, 12, 0, 1),
|
||||
Rp(1, 5, 9, 13, 2, 3),
|
||||
Rp(2, 6, 10, 14, 4, 5),
|
||||
Rp(3, 7, 11, 15, 6, 7),
|
||||
Rp(0, 5, 10, 15, 8, 9),
|
||||
Rp(1, 6, 11, 12, 10, 11),
|
||||
Rp(2, 7, 8, 13, 12, 13),
|
||||
Rp(3, 4, 9, 14, 14, 15),
|
||||
};
|
||||
|
||||
comptime var j: usize = 0;
|
||||
inline while (j < 12) : (j += 1) {
|
||||
inline for (rounds) |r| {
|
||||
v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]];
|
||||
v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32));
|
||||
v[r.c] = v[r.c] +% v[r.d];
|
||||
v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24));
|
||||
v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]];
|
||||
v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16));
|
||||
v[r.c] = v[r.c] +% v[r.d];
|
||||
v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63));
|
||||
for (rr) |s, j| {
|
||||
mem.writeInt(out[8 * j..8 * j + 8], s, builtin.Endian.Little);
|
||||
}
|
||||
}
|
||||
|
||||
for (d.h) |*r, i| {
|
||||
*r ^= v[i] ^ v[i + 8];
|
||||
fn round(d: &Self, b: []const u8, last: bool) void {
|
||||
debug.assert(b.len == 128);
|
||||
|
||||
var m: [16]u64 = undefined;
|
||||
var v: [16]u64 = undefined;
|
||||
|
||||
for (m) |*r, i| {
|
||||
r.* = mem.readIntLE(u64, b[8 * i..8 * i + 8]);
|
||||
}
|
||||
|
||||
var k: usize = 0;
|
||||
while (k < 8) : (k += 1) {
|
||||
v[k] = d.h[k];
|
||||
v[k + 8] = iv[k];
|
||||
}
|
||||
|
||||
v[12] ^= @truncate(u64, d.t);
|
||||
v[13] ^= u64(d.t >> 64);
|
||||
if (last) v[14] = ~v[14];
|
||||
|
||||
const rounds = comptime []RoundParam{
|
||||
Rp(0, 4, 8, 12, 0, 1),
|
||||
Rp(1, 5, 9, 13, 2, 3),
|
||||
Rp(2, 6, 10, 14, 4, 5),
|
||||
Rp(3, 7, 11, 15, 6, 7),
|
||||
Rp(0, 5, 10, 15, 8, 9),
|
||||
Rp(1, 6, 11, 12, 10, 11),
|
||||
Rp(2, 7, 8, 13, 12, 13),
|
||||
Rp(3, 4, 9, 14, 14, 15),
|
||||
};
|
||||
|
||||
comptime var j: usize = 0;
|
||||
inline while (j < 12) : (j += 1) {
|
||||
inline for (rounds) |r| {
|
||||
v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]];
|
||||
v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32));
|
||||
v[r.c] = v[r.c] +% v[r.d];
|
||||
v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24));
|
||||
v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]];
|
||||
v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16));
|
||||
v[r.c] = v[r.c] +% v[r.d];
|
||||
v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63));
|
||||
}
|
||||
}
|
||||
|
||||
for (d.h) |*r, i| {
|
||||
r.* ^= v[i] ^ v[i + 8];
|
||||
}
|
||||
}
|
||||
}
|
||||
};}
|
||||
};
|
||||
}
|
||||
|
||||
test "blake2b384 single" {
|
||||
const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100";
|
||||
@ -458,7 +687,7 @@ test "blake2b512 streaming" {
|
||||
}
|
||||
|
||||
test "blake2b512 aligned final" {
|
||||
var block = []u8 {0} ** Blake2b512.block_size;
|
||||
var block = []u8{0} ** Blake2b512.block_size;
|
||||
var out: [Blake2b512.digest_size]u8 = undefined;
|
||||
|
||||
var h = Blake2b512.init();
|
||||
|
@ -29,12 +29,12 @@ pub fn Hmac(comptime H: type) type {
|
||||
|
||||
var o_key_pad: [H.block_size]u8 = undefined;
|
||||
for (o_key_pad) |*b, i| {
|
||||
*b = scratch[i] ^ 0x5c;
|
||||
b.* = scratch[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
var i_key_pad: [H.block_size]u8 = undefined;
|
||||
for (i_key_pad) |*b, i| {
|
||||
*b = scratch[i] ^ 0x36;
|
||||
b.* = scratch[i] ^ 0x36;
|
||||
}
|
||||
|
||||
// HMAC(k, m) = H(o_key_pad | H(i_key_pad | message)) where | is concatenation
|
||||
|
@ -10,148 +10,228 @@ pub const Sha3_256 = Keccak(256, 0x06);
|
||||
pub const Sha3_384 = Keccak(384, 0x06);
|
||||
pub const Sha3_512 = Keccak(512, 0x06);
|
||||
|
||||
fn Keccak(comptime bits: usize, comptime delim: u8) type { return struct {
|
||||
const Self = this;
|
||||
const block_size = 200;
|
||||
const digest_size = bits / 8;
|
||||
fn Keccak(comptime bits: usize, comptime delim: u8) type {
|
||||
return struct {
|
||||
const Self = this;
|
||||
const block_size = 200;
|
||||
const digest_size = bits / 8;
|
||||
|
||||
s: [200]u8,
|
||||
offset: usize,
|
||||
rate: usize,
|
||||
s: [200]u8,
|
||||
offset: usize,
|
||||
rate: usize,
|
||||
|
||||
pub fn init() Self {
|
||||
var d: Self = undefined;
|
||||
d.reset();
|
||||
return d;
|
||||
}
|
||||
pub fn init() Self {
|
||||
var d: Self = undefined;
|
||||
d.reset();
|
||||
return d;
|
||||
}
|
||||
|
||||
pub fn reset(d: &Self) void {
|
||||
mem.set(u8, d.s[0..], 0);
|
||||
d.offset = 0;
|
||||
d.rate = 200 - (bits / 4);
|
||||
}
|
||||
pub fn reset(d: &Self) void {
|
||||
mem.set(u8, d.s[0..], 0);
|
||||
d.offset = 0;
|
||||
d.rate = 200 - (bits / 4);
|
||||
}
|
||||
|
||||
pub fn hash(b: []const u8, out: []u8) void {
|
||||
var d = Self.init();
|
||||
d.update(b);
|
||||
d.final(out);
|
||||
}
|
||||
pub fn hash(b: []const u8, out: []u8) void {
|
||||
var d = Self.init();
|
||||
d.update(b);
|
||||
d.final(out);
|
||||
}
|
||||
|
||||
pub fn update(d: &Self, b: []const u8) void {
|
||||
var ip: usize = 0;
|
||||
var len = b.len;
|
||||
var rate = d.rate - d.offset;
|
||||
var offset = d.offset;
|
||||
pub fn update(d: &Self, b: []const u8) void {
|
||||
var ip: usize = 0;
|
||||
var len = b.len;
|
||||
var rate = d.rate - d.offset;
|
||||
var offset = d.offset;
|
||||
|
||||
// absorb
|
||||
while (len >= rate) {
|
||||
for (d.s[offset .. offset + rate]) |*r, i|
|
||||
*r ^= b[ip..][i];
|
||||
// absorb
|
||||
while (len >= rate) {
|
||||
for (d.s[offset..offset + rate]) |*r, i|
|
||||
r.* ^= b[ip..][i];
|
||||
|
||||
keccak_f(1600, d.s[0..]);
|
||||
|
||||
ip += rate;
|
||||
len -= rate;
|
||||
rate = d.rate;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
for (d.s[offset..offset + len]) |*r, i|
|
||||
r.* ^= b[ip..][i];
|
||||
|
||||
d.offset = offset + len;
|
||||
}
|
||||
|
||||
pub fn final(d: &Self, out: []u8) void {
|
||||
// padding
|
||||
d.s[d.offset] ^= delim;
|
||||
d.s[d.rate - 1] ^= 0x80;
|
||||
|
||||
keccak_f(1600, d.s[0..]);
|
||||
|
||||
ip += rate;
|
||||
len -= rate;
|
||||
rate = d.rate;
|
||||
offset = 0;
|
||||
// squeeze
|
||||
var op: usize = 0;
|
||||
var len: usize = bits / 8;
|
||||
|
||||
while (len >= d.rate) {
|
||||
mem.copy(u8, out[op..], d.s[0..d.rate]);
|
||||
keccak_f(1600, d.s[0..]);
|
||||
op += d.rate;
|
||||
len -= d.rate;
|
||||
}
|
||||
|
||||
mem.copy(u8, out[op..], d.s[0..len]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for (d.s[offset .. offset + len]) |*r, i|
|
||||
*r ^= b[ip..][i];
|
||||
|
||||
d.offset = offset + len;
|
||||
}
|
||||
|
||||
pub fn final(d: &Self, out: []u8) void {
|
||||
// padding
|
||||
d.s[d.offset] ^= delim;
|
||||
d.s[d.rate - 1] ^= 0x80;
|
||||
|
||||
keccak_f(1600, d.s[0..]);
|
||||
|
||||
// squeeze
|
||||
var op: usize = 0;
|
||||
var len: usize = bits / 8;
|
||||
|
||||
while (len >= d.rate) {
|
||||
mem.copy(u8, out[op..], d.s[0..d.rate]);
|
||||
keccak_f(1600, d.s[0..]);
|
||||
op += d.rate;
|
||||
len -= d.rate;
|
||||
}
|
||||
|
||||
mem.copy(u8, out[op..], d.s[0..len]);
|
||||
}
|
||||
};}
|
||||
|
||||
const RC = []const u64 {
|
||||
0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
|
||||
0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
|
||||
0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
|
||||
0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
|
||||
0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
|
||||
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
|
||||
const RC = []const u64{
|
||||
0x0000000000000001,
|
||||
0x0000000000008082,
|
||||
0x800000000000808a,
|
||||
0x8000000080008000,
|
||||
0x000000000000808b,
|
||||
0x0000000080000001,
|
||||
0x8000000080008081,
|
||||
0x8000000000008009,
|
||||
0x000000000000008a,
|
||||
0x0000000000000088,
|
||||
0x0000000080008009,
|
||||
0x000000008000000a,
|
||||
0x000000008000808b,
|
||||
0x800000000000008b,
|
||||
0x8000000000008089,
|
||||
0x8000000000008003,
|
||||
0x8000000000008002,
|
||||
0x8000000000000080,
|
||||
0x000000000000800a,
|
||||
0x800000008000000a,
|
||||
0x8000000080008081,
|
||||
0x8000000000008080,
|
||||
0x0000000080000001,
|
||||
0x8000000080008008,
|
||||
};
|
||||
|
||||
const ROTC = []const usize {
|
||||
1, 3, 6, 10, 15, 21, 28, 36,
|
||||
45, 55, 2, 14, 27, 41, 56, 8,
|
||||
25, 43, 62, 18, 39, 61, 20, 44
|
||||
const ROTC = []const usize{
|
||||
1,
|
||||
3,
|
||||
6,
|
||||
10,
|
||||
15,
|
||||
21,
|
||||
28,
|
||||
36,
|
||||
45,
|
||||
55,
|
||||
2,
|
||||
14,
|
||||
27,
|
||||
41,
|
||||
56,
|
||||
8,
|
||||
25,
|
||||
43,
|
||||
62,
|
||||
18,
|
||||
39,
|
||||
61,
|
||||
20,
|
||||
44,
|
||||
};
|
||||
|
||||
const PIL = []const usize {
|
||||
10, 7, 11, 17, 18, 3, 5, 16,
|
||||
8, 21, 24, 4, 15, 23, 19, 13,
|
||||
12, 2, 20, 14, 22, 9, 6, 1
|
||||
const PIL = []const usize{
|
||||
10,
|
||||
7,
|
||||
11,
|
||||
17,
|
||||
18,
|
||||
3,
|
||||
5,
|
||||
16,
|
||||
8,
|
||||
21,
|
||||
24,
|
||||
4,
|
||||
15,
|
||||
23,
|
||||
19,
|
||||
13,
|
||||
12,
|
||||
2,
|
||||
20,
|
||||
14,
|
||||
22,
|
||||
9,
|
||||
6,
|
||||
1,
|
||||
};
|
||||
|
||||
const M5 = []const usize {
|
||||
0, 1, 2, 3, 4, 0, 1, 2, 3, 4
|
||||
const M5 = []const usize{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
};
|
||||
|
||||
fn keccak_f(comptime F: usize, d: []u8) void {
|
||||
debug.assert(d.len == F / 8);
|
||||
|
||||
const B = F / 25;
|
||||
const no_rounds = comptime x: { break :x 12 + 2 * math.log2(B); };
|
||||
const no_rounds = comptime x: {
|
||||
break :x 12 + 2 * math.log2(B);
|
||||
};
|
||||
|
||||
var s = []const u64 {0} ** 25;
|
||||
var t = []const u64 {0} ** 1;
|
||||
var c = []const u64 {0} ** 5;
|
||||
var s = []const u64{0} ** 25;
|
||||
var t = []const u64{0} ** 1;
|
||||
var c = []const u64{0} ** 5;
|
||||
|
||||
for (s) |*r, i| {
|
||||
*r = mem.readIntLE(u64, d[8*i .. 8*i + 8]);
|
||||
r.* = mem.readIntLE(u64, d[8 * i..8 * i + 8]);
|
||||
}
|
||||
|
||||
comptime var x: usize = 0;
|
||||
comptime var y: usize = 0;
|
||||
for (RC[0..no_rounds]) |round| {
|
||||
// theta
|
||||
x = 0; inline while (x < 5) : (x += 1) {
|
||||
c[x] = s[x] ^ s[x+5] ^ s[x+10] ^ s[x+15] ^ s[x+20];
|
||||
x = 0;
|
||||
inline while (x < 5) : (x += 1) {
|
||||
c[x] = s[x] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20];
|
||||
}
|
||||
x = 0; inline while (x < 5) : (x += 1) {
|
||||
t[0] = c[M5[x+4]] ^ math.rotl(u64, c[M5[x+1]], usize(1));
|
||||
y = 0; inline while (y < 5) : (y += 1) {
|
||||
s[x + y*5] ^= t[0];
|
||||
x = 0;
|
||||
inline while (x < 5) : (x += 1) {
|
||||
t[0] = c[M5[x + 4]] ^ math.rotl(u64, c[M5[x + 1]], usize(1));
|
||||
y = 0;
|
||||
inline while (y < 5) : (y += 1) {
|
||||
s[x + y * 5] ^= t[0];
|
||||
}
|
||||
}
|
||||
|
||||
// rho+pi
|
||||
t[0] = s[1];
|
||||
x = 0; inline while (x < 24) : (x += 1) {
|
||||
x = 0;
|
||||
inline while (x < 24) : (x += 1) {
|
||||
c[0] = s[PIL[x]];
|
||||
s[PIL[x]] = math.rotl(u64, t[0], ROTC[x]);
|
||||
t[0] = c[0];
|
||||
}
|
||||
|
||||
// chi
|
||||
y = 0; inline while (y < 5) : (y += 1) {
|
||||
x = 0; inline while (x < 5) : (x += 1) {
|
||||
c[x] = s[x + y*5];
|
||||
y = 0;
|
||||
inline while (y < 5) : (y += 1) {
|
||||
x = 0;
|
||||
inline while (x < 5) : (x += 1) {
|
||||
c[x] = s[x + y * 5];
|
||||
}
|
||||
x = 0; inline while (x < 5) : (x += 1) {
|
||||
s[x + y*5] = c[x] ^ (~c[M5[x+1]] & c[M5[x+2]]);
|
||||
x = 0;
|
||||
inline while (x < 5) : (x += 1) {
|
||||
s[x + y * 5] = c[x] ^ (~c[M5[x + 1]] & c[M5[x + 2]]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,11 +240,10 @@ fn keccak_f(comptime F: usize, d: []u8) void {
|
||||
}
|
||||
|
||||
for (s) |r, i| {
|
||||
mem.writeInt(d[8*i .. 8*i + 8], r, builtin.Endian.Little);
|
||||
mem.writeInt(d[8 * i..8 * i + 8], r, builtin.Endian.Little);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
test "sha3-224 single" {
|
||||
htest.assertEqualHash(Sha3_224, "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", "");
|
||||
htest.assertEqualHash(Sha3_224, "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", "abc");
|
||||
@ -192,7 +271,7 @@ test "sha3-224 streaming" {
|
||||
}
|
||||
|
||||
test "sha3-256 single" {
|
||||
htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" , "");
|
||||
htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", "");
|
||||
htest.assertEqualHash(Sha3_256, "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", "abc");
|
||||
htest.assertEqualHash(Sha3_256, "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
|
||||
}
|
||||
@ -218,7 +297,7 @@ test "sha3-256 streaming" {
|
||||
}
|
||||
|
||||
test "sha3-256 aligned final" {
|
||||
var block = []u8 {0} ** Sha3_256.block_size;
|
||||
var block = []u8{0} ** Sha3_256.block_size;
|
||||
var out: [Sha3_256.digest_size]u8 = undefined;
|
||||
|
||||
var h = Sha3_256.init();
|
||||
@ -228,7 +307,7 @@ test "sha3-256 aligned final" {
|
||||
|
||||
test "sha3-384 single" {
|
||||
const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004";
|
||||
htest.assertEqualHash(Sha3_384, h1 , "");
|
||||
htest.assertEqualHash(Sha3_384, h1, "");
|
||||
const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25";
|
||||
htest.assertEqualHash(Sha3_384, h2, "abc");
|
||||
const h3 = "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7";
|
||||
@ -259,7 +338,7 @@ test "sha3-384 streaming" {
|
||||
|
||||
test "sha3-512 single" {
|
||||
const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26";
|
||||
htest.assertEqualHash(Sha3_512, h1 , "");
|
||||
htest.assertEqualHash(Sha3_512, h1, "");
|
||||
const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0";
|
||||
htest.assertEqualHash(Sha3_512, h2, "abc");
|
||||
const h3 = "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185";
|
||||
@ -289,7 +368,7 @@ test "sha3-512 streaming" {
|
||||
}
|
||||
|
||||
test "sha3-512 aligned final" {
|
||||
var block = []u8 {0} ** Sha3_512.block_size;
|
||||
var block = []u8{0} ** Sha3_512.block_size;
|
||||
var out: [Sha3_512.digest_size]u8 = undefined;
|
||||
|
||||
var h = Sha3_512.init();
|
||||
|
@ -6,7 +6,7 @@ const mem = std.mem;
|
||||
const posix = std.os.posix;
|
||||
|
||||
pub const TcpServer = struct {
|
||||
handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File) void,
|
||||
handleRequestFn: async<&mem.Allocator> fn(&TcpServer, &const std.net.Address, &const std.os.File) void,
|
||||
|
||||
loop: &Loop,
|
||||
sockfd: i32,
|
||||
@ -18,13 +18,11 @@ pub const TcpServer = struct {
|
||||
const PromiseNode = std.LinkedList(promise).Node;
|
||||
|
||||
pub fn init(loop: &Loop) !TcpServer {
|
||||
const sockfd = try std.os.posixSocket(posix.AF_INET,
|
||||
posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK,
|
||||
posix.PROTO_tcp);
|
||||
const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
|
||||
errdefer std.os.close(sockfd);
|
||||
|
||||
// TODO can't initialize handler coroutine here because we need well defined copy elision
|
||||
return TcpServer {
|
||||
return TcpServer{
|
||||
.loop = loop,
|
||||
.sockfd = sockfd,
|
||||
.accept_coro = null,
|
||||
@ -34,9 +32,7 @@ pub const TcpServer = struct {
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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 {
|
||||
self.handleRequestFn = handleRequestFn;
|
||||
|
||||
try std.os.posixBind(self.sockfd, &address.os_addr);
|
||||
@ -48,7 +44,6 @@ pub const TcpServer = struct {
|
||||
|
||||
try self.loop.addFd(self.sockfd, ??self.accept_coro);
|
||||
errdefer self.loop.removeFd(self.sockfd);
|
||||
|
||||
}
|
||||
|
||||
pub fn deinit(self: &TcpServer) void {
|
||||
@ -60,9 +55,7 @@ pub const TcpServer = struct {
|
||||
pub async fn handler(self: &TcpServer) void {
|
||||
while (true) {
|
||||
var accepted_addr: std.net.Address = undefined;
|
||||
if (std.os.posixAccept(self.sockfd, &accepted_addr.os_addr,
|
||||
posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd|
|
||||
{
|
||||
if (std.os.posixAccept(self.sockfd, &accepted_addr.os_addr, posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| {
|
||||
var socket = std.os.File.openHandle(accepted_fd);
|
||||
_ = async<self.loop.allocator> self.handleRequestFn(self, accepted_addr, socket) catch |err| switch (err) {
|
||||
error.OutOfMemory => {
|
||||
@ -110,7 +103,7 @@ pub const Loop = struct {
|
||||
|
||||
fn init(allocator: &mem.Allocator) !Loop {
|
||||
const epollfd = try std.os.linuxEpollCreate(std.os.linux.EPOLL_CLOEXEC);
|
||||
return Loop {
|
||||
return Loop{
|
||||
.keep_running = true,
|
||||
.allocator = allocator,
|
||||
.epollfd = epollfd,
|
||||
@ -118,11 +111,9 @@ pub const Loop = struct {
|
||||
}
|
||||
|
||||
pub fn addFd(self: &Loop, fd: i32, prom: promise) !void {
|
||||
var ev = std.os.linux.epoll_event {
|
||||
.events = std.os.linux.EPOLLIN|std.os.linux.EPOLLOUT|std.os.linux.EPOLLET,
|
||||
.data = std.os.linux.epoll_data {
|
||||
.ptr = @ptrToInt(prom),
|
||||
},
|
||||
var ev = std.os.linux.epoll_event{
|
||||
.events = std.os.linux.EPOLLIN | std.os.linux.EPOLLOUT | std.os.linux.EPOLLET,
|
||||
.data = std.os.linux.epoll_data{ .ptr = @ptrToInt(prom) },
|
||||
};
|
||||
try std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_ADD, fd, &ev);
|
||||
}
|
||||
@ -157,9 +148,9 @@ pub const Loop = struct {
|
||||
};
|
||||
|
||||
pub async fn connect(loop: &Loop, _address: &const std.net.Address) !std.os.File {
|
||||
var address = *_address; // TODO https://github.com/zig-lang/zig/issues/733
|
||||
var address = _address.*; // TODO https://github.com/zig-lang/zig/issues/733
|
||||
|
||||
const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK, posix.PROTO_tcp);
|
||||
const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
|
||||
errdefer std.os.close(sockfd);
|
||||
|
||||
try std.os.posixConnectAsync(sockfd, &address.os_addr);
|
||||
@ -179,11 +170,9 @@ test "listen on a port, send bytes, receive bytes" {
|
||||
|
||||
const Self = this;
|
||||
|
||||
async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address,
|
||||
_socket: &const std.os.File) void
|
||||
{
|
||||
async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, _socket: &const std.os.File) void {
|
||||
const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
|
||||
var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733
|
||||
var socket = _socket.*; // TODO https://github.com/zig-lang/zig/issues/733
|
||||
defer socket.close();
|
||||
const next_handler = async errorableHandler(self, _addr, socket) catch |err| switch (err) {
|
||||
error.OutOfMemory => @panic("unable to handle connection: out of memory"),
|
||||
@ -191,14 +180,14 @@ test "listen on a port, send bytes, receive bytes" {
|
||||
(await next_handler) catch |err| {
|
||||
std.debug.panic("unable to handle connection: {}\n", err);
|
||||
};
|
||||
suspend |p| { cancel p; }
|
||||
suspend |p| {
|
||||
cancel p;
|
||||
}
|
||||
}
|
||||
|
||||
async fn errorableHandler(self: &Self, _addr: &const std.net.Address,
|
||||
_socket: &const std.os.File) !void
|
||||
{
|
||||
const addr = *_addr; // TODO https://github.com/zig-lang/zig/issues/733
|
||||
var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733
|
||||
async fn errorableHandler(self: &Self, _addr: &const std.net.Address, _socket: &const std.os.File) !void {
|
||||
const addr = _addr.*; // TODO https://github.com/zig-lang/zig/issues/733
|
||||
var socket = _socket.*; // TODO https://github.com/zig-lang/zig/issues/733
|
||||
|
||||
var adapter = std.io.FileOutStream.init(&socket);
|
||||
var stream = &adapter.stream;
|
||||
@ -210,9 +199,7 @@ test "listen on a port, send bytes, receive bytes" {
|
||||
const addr = std.net.Address.initIp4(ip4addr, 0);
|
||||
|
||||
var loop = try Loop.init(std.debug.global_allocator);
|
||||
var server = MyServer {
|
||||
.tcp_server = try TcpServer.init(&loop),
|
||||
};
|
||||
var server = MyServer{ .tcp_server = try TcpServer.init(&loop) };
|
||||
defer server.tcp_server.deinit();
|
||||
try server.tcp_server.listen(addr, MyServer.handler);
|
||||
|
||||
|
@ -9,9 +9,9 @@ const std = @import("../index.zig");
|
||||
const debug = std.debug;
|
||||
|
||||
pub const Polynomial = struct {
|
||||
const IEEE = 0xedb88320;
|
||||
const IEEE = 0xedb88320;
|
||||
const Castagnoli = 0x82f63b78;
|
||||
const Koopman = 0xeb31d82e;
|
||||
const Koopman = 0xeb31d82e;
|
||||
};
|
||||
|
||||
// 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 {
|
||||
|
||||
for (tables[0]) |*e, i| {
|
||||
var crc = u32(i);
|
||||
var j: usize = 0; while (j < 8) : (j += 1) {
|
||||
var j: usize = 0;
|
||||
while (j < 8) : (j += 1) {
|
||||
if (crc & 1 == 1) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
} else {
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
}
|
||||
*e = crc;
|
||||
e.* = crc;
|
||||
}
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < 256) : (i += 1) {
|
||||
var crc = tables[0][i];
|
||||
var j: usize = 1; while (j < 8) : (j += 1) {
|
||||
var j: usize = 1;
|
||||
while (j < 8) : (j += 1) {
|
||||
const index = @truncate(u8, crc);
|
||||
crc = tables[0][index] ^ (crc >> 8);
|
||||
tables[j][i] = crc;
|
||||
@ -53,22 +55,21 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
|
||||
crc: u32,
|
||||
|
||||
pub fn init() Self {
|
||||
return Self {
|
||||
.crc = 0xffffffff,
|
||||
};
|
||||
return Self{ .crc = 0xffffffff };
|
||||
}
|
||||
|
||||
pub fn update(self: &Self, input: []const u8) void {
|
||||
var i: usize = 0;
|
||||
while (i + 8 <= input.len) : (i += 8) {
|
||||
const p = input[i..i+8];
|
||||
const p = input[i..i + 8];
|
||||
|
||||
// Unrolling this way gives ~50Mb/s increase
|
||||
self.crc ^= (u32(p[0]) << 0);
|
||||
self.crc ^= (u32(p[1]) << 8);
|
||||
self.crc ^= (u32(p[0]) << 0);
|
||||
self.crc ^= (u32(p[1]) << 8);
|
||||
self.crc ^= (u32(p[2]) << 16);
|
||||
self.crc ^= (u32(p[3]) << 24);
|
||||
|
||||
|
||||
self.crc =
|
||||
lookup_tables[0][p[7]] ^
|
||||
lookup_tables[1][p[6]] ^
|
||||
@ -123,14 +124,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
|
||||
|
||||
for (table) |*e, i| {
|
||||
var crc = u32(i * 16);
|
||||
var j: usize = 0; while (j < 8) : (j += 1) {
|
||||
var j: usize = 0;
|
||||
while (j < 8) : (j += 1) {
|
||||
if (crc & 1 == 1) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
} else {
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
}
|
||||
*e = crc;
|
||||
e.* = crc;
|
||||
}
|
||||
|
||||
break :block table;
|
||||
@ -139,9 +141,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
|
||||
crc: u32,
|
||||
|
||||
pub fn init() Self {
|
||||
return Self {
|
||||
.crc = 0xffffffff,
|
||||
};
|
||||
return Self{ .crc = 0xffffffff };
|
||||
}
|
||||
|
||||
pub fn update(self: &Self, input: []const u8) void {
|
||||
|
@ -9,10 +9,7 @@ const builtin = @import("builtin");
|
||||
const want_modification_safety = builtin.mode != builtin.Mode.ReleaseFast;
|
||||
const debug_u32 = if (want_modification_safety) u32 else void;
|
||||
|
||||
pub fn HashMap(comptime K: type, comptime V: type,
|
||||
comptime hash: fn(key: K)u32,
|
||||
comptime eql: fn(a: K, b: K)bool) type
|
||||
{
|
||||
pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn(key: K) u32, comptime eql: fn(a: K, b: K) bool) type {
|
||||
return struct {
|
||||
entries: []Entry,
|
||||
size: usize,
|
||||
@ -65,7 +62,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
||||
};
|
||||
|
||||
pub fn init(allocator: &Allocator) Self {
|
||||
return Self {
|
||||
return Self{
|
||||
.entries = []Entry{},
|
||||
.allocator = allocator,
|
||||
.size = 0,
|
||||
@ -129,34 +126,36 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
||||
if (hm.entries.len == 0) return null;
|
||||
hm.incrementModificationCount();
|
||||
const start_index = hm.keyToIndex(key);
|
||||
{var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
|
||||
const index = (start_index + roll_over) % hm.entries.len;
|
||||
var entry = &hm.entries[index];
|
||||
{
|
||||
var roll_over: usize = 0;
|
||||
while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
|
||||
const index = (start_index + roll_over) % hm.entries.len;
|
||||
var entry = &hm.entries[index];
|
||||
|
||||
if (!entry.used)
|
||||
return null;
|
||||
if (!entry.used) return null;
|
||||
|
||||
if (!eql(entry.key, key)) continue;
|
||||
if (!eql(entry.key, key)) continue;
|
||||
|
||||
while (roll_over < hm.entries.len) : (roll_over += 1) {
|
||||
const next_index = (start_index + roll_over + 1) % hm.entries.len;
|
||||
const next_entry = &hm.entries[next_index];
|
||||
if (!next_entry.used or next_entry.distance_from_start_index == 0) {
|
||||
entry.used = false;
|
||||
hm.size -= 1;
|
||||
return entry;
|
||||
while (roll_over < hm.entries.len) : (roll_over += 1) {
|
||||
const next_index = (start_index + roll_over + 1) % hm.entries.len;
|
||||
const next_entry = &hm.entries[next_index];
|
||||
if (!next_entry.used or next_entry.distance_from_start_index == 0) {
|
||||
entry.used = false;
|
||||
hm.size -= 1;
|
||||
return entry;
|
||||
}
|
||||
entry.* = next_entry.*;
|
||||
entry.distance_from_start_index -= 1;
|
||||
entry = next_entry;
|
||||
}
|
||||
*entry = *next_entry;
|
||||
entry.distance_from_start_index -= 1;
|
||||
entry = next_entry;
|
||||
unreachable; // shifting everything in the table
|
||||
}
|
||||
unreachable; // shifting everything in the table
|
||||
}}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn iterator(hm: &const Self) Iterator {
|
||||
return Iterator {
|
||||
return Iterator{
|
||||
.hm = hm,
|
||||
.count = 0,
|
||||
.index = 0,
|
||||
@ -182,21 +181,23 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
||||
/// Returns the value that was already there.
|
||||
fn internalPut(hm: &Self, orig_key: K, orig_value: &const V) ?V {
|
||||
var key = orig_key;
|
||||
var value = *orig_value;
|
||||
var value = orig_value.*;
|
||||
const start_index = hm.keyToIndex(key);
|
||||
var roll_over: usize = 0;
|
||||
var distance_from_start_index: usize = 0;
|
||||
while (roll_over < hm.entries.len) : ({roll_over += 1; distance_from_start_index += 1;}) {
|
||||
while (roll_over < hm.entries.len) : ({
|
||||
roll_over += 1;
|
||||
distance_from_start_index += 1;
|
||||
}) {
|
||||
const index = (start_index + roll_over) % hm.entries.len;
|
||||
const entry = &hm.entries[index];
|
||||
|
||||
if (entry.used and !eql(entry.key, key)) {
|
||||
if (entry.distance_from_start_index < distance_from_start_index) {
|
||||
// robin hood to the rescue
|
||||
const tmp = *entry;
|
||||
hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index,
|
||||
distance_from_start_index);
|
||||
*entry = Entry {
|
||||
const tmp = entry.*;
|
||||
hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index, distance_from_start_index);
|
||||
entry.* = Entry{
|
||||
.used = true,
|
||||
.distance_from_start_index = distance_from_start_index,
|
||||
.key = key,
|
||||
@ -219,7 +220,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
||||
}
|
||||
|
||||
hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index);
|
||||
*entry = Entry {
|
||||
entry.* = Entry{
|
||||
.used = true,
|
||||
.distance_from_start_index = distance_from_start_index,
|
||||
.key = key,
|
||||
@ -232,13 +233,16 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
||||
|
||||
fn internalGet(hm: &const Self, key: K) ?&Entry {
|
||||
const start_index = hm.keyToIndex(key);
|
||||
{var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
|
||||
const index = (start_index + roll_over) % hm.entries.len;
|
||||
const entry = &hm.entries[index];
|
||||
{
|
||||
var roll_over: usize = 0;
|
||||
while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
|
||||
const index = (start_index + roll_over) % hm.entries.len;
|
||||
const entry = &hm.entries[index];
|
||||
|
||||
if (!entry.used) return null;
|
||||
if (eql(entry.key, key)) return entry;
|
||||
}}
|
||||
if (!entry.used) return null;
|
||||
if (eql(entry.key, key)) return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -282,11 +286,19 @@ test "iterator hash map" {
|
||||
assert((reset_map.put(2, 22) catch unreachable) == null);
|
||||
assert((reset_map.put(3, 33) catch unreachable) == null);
|
||||
|
||||
var keys = []i32 { 1, 2, 3 };
|
||||
var values = []i32 { 11, 22, 33 };
|
||||
var keys = []i32{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
};
|
||||
var values = []i32{
|
||||
11,
|
||||
22,
|
||||
33,
|
||||
};
|
||||
|
||||
var it = reset_map.iterator();
|
||||
var count : usize = 0;
|
||||
var count: usize = 0;
|
||||
while (it.next()) |next| {
|
||||
assert(next.key == keys[count]);
|
||||
assert(next.value == values[count]);
|
||||
@ -305,7 +317,7 @@ test "iterator hash map" {
|
||||
}
|
||||
|
||||
it.reset();
|
||||
var entry = ?? it.next();
|
||||
var entry = ??it.next();
|
||||
assert(entry.key == keys[0]);
|
||||
assert(entry.value == values[0]);
|
||||
}
|
||||
|
207
std/json.zig
207
std/json.zig
@ -35,7 +35,7 @@ pub const Token = struct {
|
||||
};
|
||||
|
||||
pub fn init(id: Id, count: usize, offset: u1) Token {
|
||||
return Token {
|
||||
return Token{
|
||||
.id = id,
|
||||
.offset = offset,
|
||||
.string_has_escape = false,
|
||||
@ -45,7 +45,7 @@ pub const Token = struct {
|
||||
}
|
||||
|
||||
pub fn initString(count: usize, has_unicode_escape: bool) Token {
|
||||
return Token {
|
||||
return Token{
|
||||
.id = Id.String,
|
||||
.offset = 0,
|
||||
.string_has_escape = has_unicode_escape,
|
||||
@ -55,7 +55,7 @@ pub const Token = struct {
|
||||
}
|
||||
|
||||
pub fn initNumber(count: usize, number_is_integer: bool) Token {
|
||||
return Token {
|
||||
return Token{
|
||||
.id = Id.Number,
|
||||
.offset = 0,
|
||||
.string_has_escape = false,
|
||||
@ -66,7 +66,7 @@ pub const Token = struct {
|
||||
|
||||
// A marker token is a zero-length
|
||||
pub fn initMarker(id: Id) Token {
|
||||
return Token {
|
||||
return Token{
|
||||
.id = id,
|
||||
.offset = 0,
|
||||
.string_has_escape = false,
|
||||
@ -77,7 +77,7 @@ pub const Token = struct {
|
||||
|
||||
// Slice into the underlying input string.
|
||||
pub fn slice(self: &const Token, input: []const u8, i: usize) []const u8 {
|
||||
return input[i + self.offset - self.count .. i + self.offset];
|
||||
return input[i + self.offset - self.count..i + self.offset];
|
||||
}
|
||||
};
|
||||
|
||||
@ -105,8 +105,8 @@ const StreamingJsonParser = struct {
|
||||
stack: u256,
|
||||
stack_used: u8,
|
||||
|
||||
const object_bit = 0;
|
||||
const array_bit = 1;
|
||||
const object_bit = 0;
|
||||
const array_bit = 1;
|
||||
const max_stack_size = @maxValue(u8);
|
||||
|
||||
pub fn init() StreamingJsonParser {
|
||||
@ -120,7 +120,7 @@ const StreamingJsonParser = struct {
|
||||
p.count = 0;
|
||||
// Set before ever read in main transition function
|
||||
p.after_string_state = undefined;
|
||||
p.after_value_state = State.ValueEnd; // handle end of values normally
|
||||
p.after_value_state = State.ValueEnd; // handle end of values normally
|
||||
p.stack = 0;
|
||||
p.stack_used = 0;
|
||||
p.complete = false;
|
||||
@ -181,7 +181,7 @@ const StreamingJsonParser = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const Error = error {
|
||||
pub const Error = error{
|
||||
InvalidTopLevel,
|
||||
TooManyNestedItems,
|
||||
TooManyClosingItems,
|
||||
@ -206,8 +206,8 @@ const StreamingJsonParser = struct {
|
||||
//
|
||||
// There is currently no error recovery on a bad stream.
|
||||
pub fn feed(p: &StreamingJsonParser, c: u8, token1: &?Token, token2: &?Token) Error!void {
|
||||
*token1 = null;
|
||||
*token2 = null;
|
||||
token1.* = null;
|
||||
token2.* = null;
|
||||
p.count += 1;
|
||||
|
||||
// unlikely
|
||||
@ -228,7 +228,7 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.ValueBegin;
|
||||
p.after_string_state = State.ObjectSeparator;
|
||||
|
||||
*token = Token.initMarker(Token.Id.ObjectBegin);
|
||||
token.* = Token.initMarker(Token.Id.ObjectBegin);
|
||||
},
|
||||
'[' => {
|
||||
p.stack <<= 1;
|
||||
@ -238,7 +238,7 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.ValueBegin;
|
||||
p.after_string_state = State.ValueEnd;
|
||||
|
||||
*token = Token.initMarker(Token.Id.ArrayBegin);
|
||||
token.* = Token.initMarker(Token.Id.ArrayBegin);
|
||||
},
|
||||
'-' => {
|
||||
p.number_is_integer = true;
|
||||
@ -281,7 +281,10 @@ const StreamingJsonParser = struct {
|
||||
p.after_value_state = State.TopLevelEnd;
|
||||
p.count = 0;
|
||||
},
|
||||
0x09, 0x0A, 0x0D, 0x20 => {
|
||||
0x09,
|
||||
0x0A,
|
||||
0x0D,
|
||||
0x20 => {
|
||||
// whitespace
|
||||
},
|
||||
else => {
|
||||
@ -290,7 +293,10 @@ const StreamingJsonParser = struct {
|
||||
},
|
||||
|
||||
State.TopLevelEnd => switch (c) {
|
||||
0x09, 0x0A, 0x0D, 0x20 => {
|
||||
0x09,
|
||||
0x0A,
|
||||
0x0D,
|
||||
0x20 => {
|
||||
// whitespace
|
||||
},
|
||||
else => {
|
||||
@ -324,7 +330,7 @@ const StreamingJsonParser = struct {
|
||||
else => {},
|
||||
}
|
||||
|
||||
*token = Token.initMarker(Token.Id.ObjectEnd);
|
||||
token.* = Token.initMarker(Token.Id.ObjectEnd);
|
||||
},
|
||||
']' => {
|
||||
if (p.stack & 1 != array_bit) {
|
||||
@ -348,7 +354,7 @@ const StreamingJsonParser = struct {
|
||||
else => {},
|
||||
}
|
||||
|
||||
*token = Token.initMarker(Token.Id.ArrayEnd);
|
||||
token.* = Token.initMarker(Token.Id.ArrayEnd);
|
||||
},
|
||||
'{' => {
|
||||
if (p.stack_used == max_stack_size) {
|
||||
@ -362,7 +368,7 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.ValueBegin;
|
||||
p.after_string_state = State.ObjectSeparator;
|
||||
|
||||
*token = Token.initMarker(Token.Id.ObjectBegin);
|
||||
token.* = Token.initMarker(Token.Id.ObjectBegin);
|
||||
},
|
||||
'[' => {
|
||||
if (p.stack_used == max_stack_size) {
|
||||
@ -376,7 +382,7 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.ValueBegin;
|
||||
p.after_string_state = State.ValueEnd;
|
||||
|
||||
*token = Token.initMarker(Token.Id.ArrayBegin);
|
||||
token.* = Token.initMarker(Token.Id.ArrayBegin);
|
||||
},
|
||||
'-' => {
|
||||
p.state = State.Number;
|
||||
@ -406,7 +412,10 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.NullLiteral1;
|
||||
p.count = 0;
|
||||
},
|
||||
0x09, 0x0A, 0x0D, 0x20 => {
|
||||
0x09,
|
||||
0x0A,
|
||||
0x0D,
|
||||
0x20 => {
|
||||
// whitespace
|
||||
},
|
||||
else => {
|
||||
@ -428,7 +437,7 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.ValueBegin;
|
||||
p.after_string_state = State.ObjectSeparator;
|
||||
|
||||
*token = Token.initMarker(Token.Id.ObjectBegin);
|
||||
token.* = Token.initMarker(Token.Id.ObjectBegin);
|
||||
},
|
||||
'[' => {
|
||||
if (p.stack_used == max_stack_size) {
|
||||
@ -442,7 +451,7 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.ValueBegin;
|
||||
p.after_string_state = State.ValueEnd;
|
||||
|
||||
*token = Token.initMarker(Token.Id.ArrayBegin);
|
||||
token.* = Token.initMarker(Token.Id.ArrayBegin);
|
||||
},
|
||||
'-' => {
|
||||
p.state = State.Number;
|
||||
@ -472,7 +481,10 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.NullLiteral1;
|
||||
p.count = 0;
|
||||
},
|
||||
0x09, 0x0A, 0x0D, 0x20 => {
|
||||
0x09,
|
||||
0x0A,
|
||||
0x0D,
|
||||
0x20 => {
|
||||
// whitespace
|
||||
},
|
||||
else => {
|
||||
@ -501,7 +513,7 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.TopLevelEnd;
|
||||
}
|
||||
|
||||
*token = Token.initMarker(Token.Id.ArrayEnd);
|
||||
token.* = Token.initMarker(Token.Id.ArrayEnd);
|
||||
},
|
||||
'}' => {
|
||||
if (p.stack_used == 0) {
|
||||
@ -519,9 +531,12 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.TopLevelEnd;
|
||||
}
|
||||
|
||||
*token = Token.initMarker(Token.Id.ObjectEnd);
|
||||
token.* = Token.initMarker(Token.Id.ObjectEnd);
|
||||
},
|
||||
0x09, 0x0A, 0x0D, 0x20 => {
|
||||
0x09,
|
||||
0x0A,
|
||||
0x0D,
|
||||
0x20 => {
|
||||
// whitespace
|
||||
},
|
||||
else => {
|
||||
@ -534,7 +549,10 @@ const StreamingJsonParser = struct {
|
||||
p.state = State.ValueBegin;
|
||||
p.after_string_state = State.ValueEnd;
|
||||
},
|
||||
0x09, 0x0A, 0x0D, 0x20 => {
|
||||
0x09,
|
||||
0x0A,
|
||||
0x0D,
|
||||
0x20 => {
|
||||
// whitespace
|
||||
},
|
||||
else => {
|
||||
@ -553,12 +571,15 @@ const StreamingJsonParser = struct {
|
||||
p.complete = true;
|
||||
}
|
||||
|
||||
*token = Token.initString(p.count - 1, p.string_has_escape);
|
||||
token.* = Token.initString(p.count - 1, p.string_has_escape);
|
||||
},
|
||||
'\\' => {
|
||||
p.state = State.StringEscapeCharacter;
|
||||
},
|
||||
0x20, 0x21, 0x23 ... 0x5B, 0x5D ... 0x7F => {
|
||||
0x20,
|
||||
0x21,
|
||||
0x23 ... 0x5B,
|
||||
0x5D ... 0x7F => {
|
||||
// non-control ascii
|
||||
},
|
||||
0xC0 ... 0xDF => {
|
||||
@ -599,7 +620,14 @@ const StreamingJsonParser = struct {
|
||||
// The current JSONTestSuite tests rely on both of this behaviour being present
|
||||
// however, so we default to the status quo where both are accepted until this
|
||||
// is further clarified.
|
||||
'"', '\\', '/', 'b', 'f', 'n', 'r', 't' => {
|
||||
'"',
|
||||
'\\',
|
||||
'/',
|
||||
'b',
|
||||
'f',
|
||||
'n',
|
||||
'r',
|
||||
't' => {
|
||||
p.string_has_escape = true;
|
||||
p.state = State.String;
|
||||
},
|
||||
@ -613,28 +641,36 @@ const StreamingJsonParser = struct {
|
||||
},
|
||||
|
||||
State.StringEscapeHexUnicode4 => switch (c) {
|
||||
'0' ... '9', 'A' ... 'F', 'a' ... 'f' => {
|
||||
'0' ... '9',
|
||||
'A' ... 'F',
|
||||
'a' ... 'f' => {
|
||||
p.state = State.StringEscapeHexUnicode3;
|
||||
},
|
||||
else => return error.InvalidUnicodeHexSymbol,
|
||||
},
|
||||
|
||||
State.StringEscapeHexUnicode3 => switch (c) {
|
||||
'0' ... '9', 'A' ... 'F', 'a' ... 'f' => {
|
||||
'0' ... '9',
|
||||
'A' ... 'F',
|
||||
'a' ... 'f' => {
|
||||
p.state = State.StringEscapeHexUnicode2;
|
||||
},
|
||||
else => return error.InvalidUnicodeHexSymbol,
|
||||
},
|
||||
|
||||
State.StringEscapeHexUnicode2 => switch (c) {
|
||||
'0' ... '9', 'A' ... 'F', 'a' ... 'f' => {
|
||||
'0' ... '9',
|
||||
'A' ... 'F',
|
||||
'a' ... 'f' => {
|
||||
p.state = State.StringEscapeHexUnicode1;
|
||||
},
|
||||
else => return error.InvalidUnicodeHexSymbol,
|
||||
},
|
||||
|
||||
State.StringEscapeHexUnicode1 => switch (c) {
|
||||
'0' ... '9', 'A' ... 'F', 'a' ... 'f' => {
|
||||
'0' ... '9',
|
||||
'A' ... 'F',
|
||||
'a' ... 'f' => {
|
||||
p.state = State.String;
|
||||
},
|
||||
else => return error.InvalidUnicodeHexSymbol,
|
||||
@ -662,13 +698,14 @@ const StreamingJsonParser = struct {
|
||||
p.number_is_integer = false;
|
||||
p.state = State.NumberFractionalRequired;
|
||||
},
|
||||
'e', 'E' => {
|
||||
'e',
|
||||
'E' => {
|
||||
p.number_is_integer = false;
|
||||
p.state = State.NumberExponent;
|
||||
},
|
||||
else => {
|
||||
p.state = p.after_value_state;
|
||||
*token = Token.initNumber(p.count, p.number_is_integer);
|
||||
token.* = Token.initNumber(p.count, p.number_is_integer);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
@ -681,7 +718,8 @@ const StreamingJsonParser = struct {
|
||||
p.number_is_integer = false;
|
||||
p.state = State.NumberFractionalRequired;
|
||||
},
|
||||
'e', 'E' => {
|
||||
'e',
|
||||
'E' => {
|
||||
p.number_is_integer = false;
|
||||
p.state = State.NumberExponent;
|
||||
},
|
||||
@ -690,7 +728,7 @@ const StreamingJsonParser = struct {
|
||||
},
|
||||
else => {
|
||||
p.state = p.after_value_state;
|
||||
*token = Token.initNumber(p.count, p.number_is_integer);
|
||||
token.* = Token.initNumber(p.count, p.number_is_integer);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
@ -714,13 +752,14 @@ const StreamingJsonParser = struct {
|
||||
'0' ... '9' => {
|
||||
// another digit
|
||||
},
|
||||
'e', 'E' => {
|
||||
'e',
|
||||
'E' => {
|
||||
p.number_is_integer = false;
|
||||
p.state = State.NumberExponent;
|
||||
},
|
||||
else => {
|
||||
p.state = p.after_value_state;
|
||||
*token = Token.initNumber(p.count, p.number_is_integer);
|
||||
token.* = Token.initNumber(p.count, p.number_is_integer);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
@ -729,20 +768,22 @@ const StreamingJsonParser = struct {
|
||||
State.NumberMaybeExponent => {
|
||||
p.complete = p.after_value_state == State.TopLevelEnd;
|
||||
switch (c) {
|
||||
'e', 'E' => {
|
||||
'e',
|
||||
'E' => {
|
||||
p.number_is_integer = false;
|
||||
p.state = State.NumberExponent;
|
||||
},
|
||||
else => {
|
||||
p.state = p.after_value_state;
|
||||
*token = Token.initNumber(p.count, p.number_is_integer);
|
||||
token.* = Token.initNumber(p.count, p.number_is_integer);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
State.NumberExponent => switch (c) {
|
||||
'-', '+', => {
|
||||
'-',
|
||||
'+' => {
|
||||
p.complete = false;
|
||||
p.state = State.NumberExponentDigitsRequired;
|
||||
},
|
||||
@ -773,7 +814,7 @@ const StreamingJsonParser = struct {
|
||||
},
|
||||
else => {
|
||||
p.state = p.after_value_state;
|
||||
*token = Token.initNumber(p.count, p.number_is_integer);
|
||||
token.* = Token.initNumber(p.count, p.number_is_integer);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
@ -793,7 +834,7 @@ const StreamingJsonParser = struct {
|
||||
'e' => {
|
||||
p.state = p.after_value_state;
|
||||
p.complete = p.state == State.TopLevelEnd;
|
||||
*token = Token.init(Token.Id.True, p.count + 1, 1);
|
||||
token.* = Token.init(Token.Id.True, p.count + 1, 1);
|
||||
},
|
||||
else => {
|
||||
return error.InvalidLiteral;
|
||||
@ -819,7 +860,7 @@ const StreamingJsonParser = struct {
|
||||
'e' => {
|
||||
p.state = p.after_value_state;
|
||||
p.complete = p.state == State.TopLevelEnd;
|
||||
*token = Token.init(Token.Id.False, p.count + 1, 1);
|
||||
token.* = Token.init(Token.Id.False, p.count + 1, 1);
|
||||
},
|
||||
else => {
|
||||
return error.InvalidLiteral;
|
||||
@ -840,7 +881,7 @@ const StreamingJsonParser = struct {
|
||||
'l' => {
|
||||
p.state = p.after_value_state;
|
||||
p.complete = p.state == State.TopLevelEnd;
|
||||
*token = Token.init(Token.Id.Null, p.count + 1, 1);
|
||||
token.* = Token.init(Token.Id.Null, p.count + 1, 1);
|
||||
},
|
||||
else => {
|
||||
return error.InvalidLiteral;
|
||||
@ -895,7 +936,7 @@ pub const Value = union(enum) {
|
||||
Object: ObjectMap,
|
||||
|
||||
pub fn dump(self: &const Value) void {
|
||||
switch (*self) {
|
||||
switch (self.*) {
|
||||
Value.Null => {
|
||||
std.debug.warn("null");
|
||||
},
|
||||
@ -950,7 +991,7 @@ pub const Value = union(enum) {
|
||||
}
|
||||
|
||||
fn dumpIndentLevel(self: &const Value, indent: usize, level: usize) void {
|
||||
switch (*self) {
|
||||
switch (self.*) {
|
||||
Value.Null => {
|
||||
std.debug.warn("null");
|
||||
},
|
||||
@ -1027,7 +1068,7 @@ const JsonParser = struct {
|
||||
};
|
||||
|
||||
pub fn init(allocator: &Allocator, copy_strings: bool) JsonParser {
|
||||
return JsonParser {
|
||||
return JsonParser{
|
||||
.allocator = allocator,
|
||||
.state = State.Simple,
|
||||
.copy_strings = copy_strings,
|
||||
@ -1082,7 +1123,7 @@ const JsonParser = struct {
|
||||
|
||||
std.debug.assert(p.stack.len == 1);
|
||||
|
||||
return ValueTree {
|
||||
return ValueTree{
|
||||
.arena = arena,
|
||||
.root = p.stack.at(0),
|
||||
};
|
||||
@ -1115,11 +1156,11 @@ const JsonParser = struct {
|
||||
|
||||
switch (token.id) {
|
||||
Token.Id.ObjectBegin => {
|
||||
try p.stack.append(Value { .Object = ObjectMap.init(allocator) });
|
||||
try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });
|
||||
p.state = State.ObjectKey;
|
||||
},
|
||||
Token.Id.ArrayBegin => {
|
||||
try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) });
|
||||
try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) });
|
||||
p.state = State.ArrayValue;
|
||||
},
|
||||
Token.Id.String => {
|
||||
@ -1133,12 +1174,12 @@ const JsonParser = struct {
|
||||
p.state = State.ObjectKey;
|
||||
},
|
||||
Token.Id.True => {
|
||||
_ = try object.put(key, Value { .Bool = true });
|
||||
_ = try object.put(key, Value{ .Bool = true });
|
||||
_ = p.stack.pop();
|
||||
p.state = State.ObjectKey;
|
||||
},
|
||||
Token.Id.False => {
|
||||
_ = try object.put(key, Value { .Bool = false });
|
||||
_ = try object.put(key, Value{ .Bool = false });
|
||||
_ = p.stack.pop();
|
||||
p.state = State.ObjectKey;
|
||||
},
|
||||
@ -1165,11 +1206,11 @@ const JsonParser = struct {
|
||||
try p.pushToParent(value);
|
||||
},
|
||||
Token.Id.ObjectBegin => {
|
||||
try p.stack.append(Value { .Object = ObjectMap.init(allocator) });
|
||||
try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });
|
||||
p.state = State.ObjectKey;
|
||||
},
|
||||
Token.Id.ArrayBegin => {
|
||||
try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) });
|
||||
try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) });
|
||||
p.state = State.ArrayValue;
|
||||
},
|
||||
Token.Id.String => {
|
||||
@ -1179,10 +1220,10 @@ const JsonParser = struct {
|
||||
try array.append(try p.parseNumber(token, input, i));
|
||||
},
|
||||
Token.Id.True => {
|
||||
try array.append(Value { .Bool = true });
|
||||
try array.append(Value{ .Bool = true });
|
||||
},
|
||||
Token.Id.False => {
|
||||
try array.append(Value { .Bool = false });
|
||||
try array.append(Value{ .Bool = false });
|
||||
},
|
||||
Token.Id.Null => {
|
||||
try array.append(Value.Null);
|
||||
@ -1194,11 +1235,11 @@ const JsonParser = struct {
|
||||
},
|
||||
State.Simple => switch (token.id) {
|
||||
Token.Id.ObjectBegin => {
|
||||
try p.stack.append(Value { .Object = ObjectMap.init(allocator) });
|
||||
try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });
|
||||
p.state = State.ObjectKey;
|
||||
},
|
||||
Token.Id.ArrayBegin => {
|
||||
try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) });
|
||||
try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) });
|
||||
p.state = State.ArrayValue;
|
||||
},
|
||||
Token.Id.String => {
|
||||
@ -1208,15 +1249,16 @@ const JsonParser = struct {
|
||||
try p.stack.append(try p.parseNumber(token, input, i));
|
||||
},
|
||||
Token.Id.True => {
|
||||
try p.stack.append(Value { .Bool = true });
|
||||
try p.stack.append(Value{ .Bool = true });
|
||||
},
|
||||
Token.Id.False => {
|
||||
try p.stack.append(Value { .Bool = false });
|
||||
try p.stack.append(Value{ .Bool = false });
|
||||
},
|
||||
Token.Id.Null => {
|
||||
try p.stack.append(Value.Null);
|
||||
},
|
||||
Token.Id.ObjectEnd, Token.Id.ArrayEnd => {
|
||||
Token.Id.ObjectEnd,
|
||||
Token.Id.ArrayEnd => {
|
||||
unreachable;
|
||||
},
|
||||
},
|
||||
@ -1248,15 +1290,14 @@ const JsonParser = struct {
|
||||
// TODO: We don't strictly have to copy values which do not contain any escape
|
||||
// characters if flagged with the option.
|
||||
const slice = token.slice(input, i);
|
||||
return Value { .String = try mem.dupe(p.allocator, u8, slice) };
|
||||
return Value{ .String = try mem.dupe(p.allocator, u8, slice) };
|
||||
}
|
||||
|
||||
fn parseNumber(p: &JsonParser, token: &const Token, input: []const u8, i: usize) !Value {
|
||||
return if (token.number_is_integer)
|
||||
Value { .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }
|
||||
Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }
|
||||
else
|
||||
@panic("TODO: fmt.parseFloat not yet implemented")
|
||||
;
|
||||
@panic("TODO: fmt.parseFloat not yet implemented");
|
||||
}
|
||||
};
|
||||
|
||||
@ -1267,21 +1308,21 @@ test "json parser dynamic" {
|
||||
defer p.deinit();
|
||||
|
||||
const s =
|
||||
\\{
|
||||
\\ "Image": {
|
||||
\\ "Width": 800,
|
||||
\\ "Height": 600,
|
||||
\\ "Title": "View from 15th Floor",
|
||||
\\ "Thumbnail": {
|
||||
\\ "Url": "http://www.example.com/image/481989943",
|
||||
\\ "Height": 125,
|
||||
\\ "Width": 100
|
||||
\\ },
|
||||
\\ "Animated" : false,
|
||||
\\ "IDs": [116, 943, 234, 38793]
|
||||
\\ }
|
||||
\\}
|
||||
;
|
||||
\\{
|
||||
\\ "Image": {
|
||||
\\ "Width": 800,
|
||||
\\ "Height": 600,
|
||||
\\ "Title": "View from 15th Floor",
|
||||
\\ "Thumbnail": {
|
||||
\\ "Url": "http://www.example.com/image/481989943",
|
||||
\\ "Height": 125,
|
||||
\\ "Width": 100
|
||||
\\ },
|
||||
\\ "Animated" : false,
|
||||
\\ "IDs": [116, 943, 234, 38793]
|
||||
\\ }
|
||||
\\}
|
||||
;
|
||||
|
||||
var tree = try p.parse(s);
|
||||
defer tree.deinit();
|
||||
|
@ -16,7 +16,7 @@ pub fn acos(x: var) @typeOf(x) {
|
||||
}
|
||||
|
||||
fn r32(z: f32) f32 {
|
||||
const pS0 = 1.6666586697e-01;
|
||||
const pS0 = 1.6666586697e-01;
|
||||
const pS1 = -4.2743422091e-02;
|
||||
const pS2 = -8.6563630030e-03;
|
||||
const qS1 = -7.0662963390e-01;
|
||||
@ -74,16 +74,16 @@ fn acos32(x: f32) f32 {
|
||||
}
|
||||
|
||||
fn r64(z: f64) f64 {
|
||||
const pS0: f64 = 1.66666666666666657415e-01;
|
||||
const pS0: f64 = 1.66666666666666657415e-01;
|
||||
const pS1: f64 = -3.25565818622400915405e-01;
|
||||
const pS2: f64 = 2.01212532134862925881e-01;
|
||||
const pS2: f64 = 2.01212532134862925881e-01;
|
||||
const pS3: f64 = -4.00555345006794114027e-02;
|
||||
const pS4: f64 = 7.91534994289814532176e-04;
|
||||
const pS5: f64 = 3.47933107596021167570e-05;
|
||||
const pS4: f64 = 7.91534994289814532176e-04;
|
||||
const pS5: f64 = 3.47933107596021167570e-05;
|
||||
const qS1: f64 = -2.40339491173441421878e+00;
|
||||
const qS2: f64 = 2.02094576023350569471e+00;
|
||||
const qS2: f64 = 2.02094576023350569471e+00;
|
||||
const qS3: f64 = -6.88283971605453293030e-01;
|
||||
const qS4: f64 = 7.70381505559019352791e-02;
|
||||
const qS4: f64 = 7.70381505559019352791e-02;
|
||||
|
||||
const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
|
||||
const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
|
||||
|
@ -17,7 +17,7 @@ pub fn asin(x: var) @typeOf(x) {
|
||||
}
|
||||
|
||||
fn r32(z: f32) f32 {
|
||||
const pS0 = 1.6666586697e-01;
|
||||
const pS0 = 1.6666586697e-01;
|
||||
const pS1 = -4.2743422091e-02;
|
||||
const pS2 = -8.6563630030e-03;
|
||||
const qS1 = -7.0662963390e-01;
|
||||
@ -37,9 +37,9 @@ fn asin32(x: f32) f32 {
|
||||
if (ix >= 0x3F800000) {
|
||||
// |x| >= 1
|
||||
if (ix == 0x3F800000) {
|
||||
return x * pio2 + 0x1.0p-120; // asin(+-1) = +-pi/2 with inexact
|
||||
return x * pio2 + 0x1.0p-120; // asin(+-1) = +-pi/2 with inexact
|
||||
} else {
|
||||
return math.nan(f32); // asin(|x| > 1) is nan
|
||||
return math.nan(f32); // asin(|x| > 1) is nan
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,16 +66,16 @@ fn asin32(x: f32) f32 {
|
||||
}
|
||||
|
||||
fn r64(z: f64) f64 {
|
||||
const pS0: f64 = 1.66666666666666657415e-01;
|
||||
const pS0: f64 = 1.66666666666666657415e-01;
|
||||
const pS1: f64 = -3.25565818622400915405e-01;
|
||||
const pS2: f64 = 2.01212532134862925881e-01;
|
||||
const pS2: f64 = 2.01212532134862925881e-01;
|
||||
const pS3: f64 = -4.00555345006794114027e-02;
|
||||
const pS4: f64 = 7.91534994289814532176e-04;
|
||||
const pS5: f64 = 3.47933107596021167570e-05;
|
||||
const pS4: f64 = 7.91534994289814532176e-04;
|
||||
const pS5: f64 = 3.47933107596021167570e-05;
|
||||
const qS1: f64 = -2.40339491173441421878e+00;
|
||||
const qS2: f64 = 2.02094576023350569471e+00;
|
||||
const qS2: f64 = 2.02094576023350569471e+00;
|
||||
const qS3: f64 = -6.88283971605453293030e-01;
|
||||
const qS4: f64 = 7.70381505559019352791e-02;
|
||||
const qS4: f64 = 7.70381505559019352791e-02;
|
||||
|
||||
const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
|
||||
const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
|
||||
|
@ -31,7 +31,7 @@ pub fn atan2(comptime T: type, x: T, y: T) T {
|
||||
}
|
||||
|
||||
fn atan2_32(y: f32, x: f32) f32 {
|
||||
const pi: f32 = 3.1415927410e+00;
|
||||
const pi: f32 = 3.1415927410e+00;
|
||||
const pi_lo: f32 = -8.7422776573e-08;
|
||||
|
||||
if (math.isNan(x) or math.isNan(y)) {
|
||||
@ -53,9 +53,10 @@ fn atan2_32(y: f32, x: f32) f32 {
|
||||
|
||||
if (iy == 0) {
|
||||
switch (m) {
|
||||
0, 1 => return y, // atan(+-0, +...)
|
||||
2 => return pi, // atan(+0, -...)
|
||||
3 => return -pi, // atan(-0, -...)
|
||||
0,
|
||||
1 => return y, // atan(+-0, +...)
|
||||
2 => return pi, // atan(+0, -...)
|
||||
3 => return -pi, // atan(-0, -...)
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@ -71,18 +72,18 @@ fn atan2_32(y: f32, x: f32) f32 {
|
||||
if (ix == 0x7F800000) {
|
||||
if (iy == 0x7F800000) {
|
||||
switch (m) {
|
||||
0 => return pi / 4, // atan(+inf, +inf)
|
||||
1 => return -pi / 4, // atan(-inf, +inf)
|
||||
2 => return 3*pi / 4, // atan(+inf, -inf)
|
||||
3 => return -3*pi / 4, // atan(-inf, -inf)
|
||||
0 => return pi / 4, // atan(+inf, +inf)
|
||||
1 => return -pi / 4, // atan(-inf, +inf)
|
||||
2 => return 3 * pi / 4, // atan(+inf, -inf)
|
||||
3 => return -3 * pi / 4, // atan(-inf, -inf)
|
||||
else => unreachable,
|
||||
}
|
||||
} else {
|
||||
switch (m) {
|
||||
0 => return 0.0, // atan(+..., +inf)
|
||||
1 => return -0.0, // atan(-..., +inf)
|
||||
2 => return pi, // atan(+..., -inf)
|
||||
3 => return -pi, // atan(-...f, -inf)
|
||||
0 => return 0.0, // atan(+..., +inf)
|
||||
1 => return -0.0, // atan(-..., +inf)
|
||||
2 => return pi, // atan(+..., -inf)
|
||||
3 => return -pi, // atan(-...f, -inf)
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@ -107,16 +108,16 @@ fn atan2_32(y: f32, x: f32) f32 {
|
||||
};
|
||||
|
||||
switch (m) {
|
||||
0 => return z, // atan(+, +)
|
||||
1 => return -z, // atan(-, +)
|
||||
2 => return pi - (z - pi_lo), // atan(+, -)
|
||||
3 => return (z - pi_lo) - pi, // atan(-, -)
|
||||
0 => return z, // atan(+, +)
|
||||
1 => return -z, // atan(-, +)
|
||||
2 => return pi - (z - pi_lo), // atan(+, -)
|
||||
3 => return (z - pi_lo) - pi, // atan(-, -)
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
fn atan2_64(y: f64, x: f64) f64 {
|
||||
const pi: f64 = 3.1415926535897931160E+00;
|
||||
const pi: f64 = 3.1415926535897931160E+00;
|
||||
const pi_lo: f64 = 1.2246467991473531772E-16;
|
||||
|
||||
if (math.isNan(x) or math.isNan(y)) {
|
||||
@ -143,9 +144,10 @@ fn atan2_64(y: f64, x: f64) f64 {
|
||||
|
||||
if (iy | ly == 0) {
|
||||
switch (m) {
|
||||
0, 1 => return y, // atan(+-0, +...)
|
||||
2 => return pi, // atan(+0, -...)
|
||||
3 => return -pi, // atan(-0, -...)
|
||||
0,
|
||||
1 => return y, // atan(+-0, +...)
|
||||
2 => return pi, // atan(+0, -...)
|
||||
3 => return -pi, // atan(-0, -...)
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@ -161,18 +163,18 @@ fn atan2_64(y: f64, x: f64) f64 {
|
||||
if (ix == 0x7FF00000) {
|
||||
if (iy == 0x7FF00000) {
|
||||
switch (m) {
|
||||
0 => return pi / 4, // atan(+inf, +inf)
|
||||
1 => return -pi / 4, // atan(-inf, +inf)
|
||||
2 => return 3*pi / 4, // atan(+inf, -inf)
|
||||
3 => return -3*pi / 4, // atan(-inf, -inf)
|
||||
0 => return pi / 4, // atan(+inf, +inf)
|
||||
1 => return -pi / 4, // atan(-inf, +inf)
|
||||
2 => return 3 * pi / 4, // atan(+inf, -inf)
|
||||
3 => return -3 * pi / 4, // atan(-inf, -inf)
|
||||
else => unreachable,
|
||||
}
|
||||
} else {
|
||||
switch (m) {
|
||||
0 => return 0.0, // atan(+..., +inf)
|
||||
1 => return -0.0, // atan(-..., +inf)
|
||||
2 => return pi, // atan(+..., -inf)
|
||||
3 => return -pi, // atan(-...f, -inf)
|
||||
0 => return 0.0, // atan(+..., +inf)
|
||||
1 => return -0.0, // atan(-..., +inf)
|
||||
2 => return pi, // atan(+..., -inf)
|
||||
3 => return -pi, // atan(-...f, -inf)
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@ -197,10 +199,10 @@ fn atan2_64(y: f64, x: f64) f64 {
|
||||
};
|
||||
|
||||
switch (m) {
|
||||
0 => return z, // atan(+, +)
|
||||
1 => return -z, // atan(-, +)
|
||||
2 => return pi - (z - pi_lo), // atan(+, -)
|
||||
3 => return (z - pi_lo) - pi, // atan(-, -)
|
||||
0 => return z, // atan(+, +)
|
||||
1 => return -z, // atan(-, +)
|
||||
2 => return pi - (z - pi_lo), // atan(+, -)
|
||||
3 => return (z - pi_lo) - pi, // atan(-, -)
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
@ -58,15 +58,15 @@ fn cbrt32(x: f32) f32 {
|
||||
}
|
||||
|
||||
fn cbrt64(x: f64) f64 {
|
||||
const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20
|
||||
const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20
|
||||
const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20
|
||||
const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20
|
||||
|
||||
// |1 / cbrt(x) - p(x)| < 2^(23.5)
|
||||
const P0: f64 = 1.87595182427177009643;
|
||||
const P0: f64 = 1.87595182427177009643;
|
||||
const P1: f64 = -1.88497979543377169875;
|
||||
const P2: f64 = 1.621429720105354466140;
|
||||
const P2: f64 = 1.621429720105354466140;
|
||||
const P3: f64 = -0.758397934778766047437;
|
||||
const P4: f64 = 0.145996192886612446982;
|
||||
const P4: f64 = 0.145996192886612446982;
|
||||
|
||||
var u = @bitCast(u64, x);
|
||||
var hx = u32(u >> 32) & 0x7FFFFFFF;
|
||||
|
@ -56,7 +56,7 @@ fn ceil64(x: f64) f64 {
|
||||
const e = (u >> 52) & 0x7FF;
|
||||
var y: f64 = undefined;
|
||||
|
||||
if (e >= 0x3FF+52 or x == 0) {
|
||||
if (e >= 0x3FF + 52 or x == 0) {
|
||||
return x;
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ fn ceil64(x: f64) f64 {
|
||||
y = x + math.f64_toint - math.f64_toint - x;
|
||||
}
|
||||
|
||||
if (e <= 0x3FF-1) {
|
||||
if (e <= 0x3FF - 1) {
|
||||
math.forceEval(y);
|
||||
if (u >> 63 != 0) {
|
||||
return -0.0;
|
||||
|
@ -18,20 +18,20 @@ pub fn cos(x: var) @typeOf(x) {
|
||||
}
|
||||
|
||||
// sin polynomial coefficients
|
||||
const S0 = 1.58962301576546568060E-10;
|
||||
const S0 = 1.58962301576546568060E-10;
|
||||
const S1 = -2.50507477628578072866E-8;
|
||||
const S2 = 2.75573136213857245213E-6;
|
||||
const S2 = 2.75573136213857245213E-6;
|
||||
const S3 = -1.98412698295895385996E-4;
|
||||
const S4 = 8.33333333332211858878E-3;
|
||||
const S4 = 8.33333333332211858878E-3;
|
||||
const S5 = -1.66666666666666307295E-1;
|
||||
|
||||
// cos polynomial coeffiecients
|
||||
const C0 = -1.13585365213876817300E-11;
|
||||
const C1 = 2.08757008419747316778E-9;
|
||||
const C1 = 2.08757008419747316778E-9;
|
||||
const C2 = -2.75573141792967388112E-7;
|
||||
const C3 = 2.48015872888517045348E-5;
|
||||
const C3 = 2.48015872888517045348E-5;
|
||||
const C4 = -1.38888888888730564116E-3;
|
||||
const C5 = 4.16666666666665929218E-2;
|
||||
const C5 = 4.16666666666665929218E-2;
|
||||
|
||||
// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
|
||||
//
|
||||
|
@ -57,7 +57,7 @@ fn floor64(x: f64) f64 {
|
||||
const e = (u >> 52) & 0x7FF;
|
||||
var y: f64 = undefined;
|
||||
|
||||
if (e >= 0x3FF+52 or x == 0) {
|
||||
if (e >= 0x3FF + 52 or x == 0) {
|
||||
return x;
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ fn floor64(x: f64) f64 {
|
||||
y = x + math.f64_toint - math.f64_toint - x;
|
||||
}
|
||||
|
||||
if (e <= 0x3FF-1) {
|
||||
if (e <= 0x3FF - 1) {
|
||||
math.forceEval(y);
|
||||
if (u >> 63 != 0) {
|
||||
return -1.0;
|
||||
|
@ -5,7 +5,7 @@ const assert = std.debug.assert;
|
||||
pub fn fma(comptime T: type, x: T, y: T, z: T) T {
|
||||
return switch (T) {
|
||||
f32 => fma32(x, y, z),
|
||||
f64 => fma64(x, y ,z),
|
||||
f64 => fma64(x, y, z),
|
||||
else => @compileError("fma not implemented for " ++ @typeName(T)),
|
||||
};
|
||||
}
|
||||
@ -71,7 +71,10 @@ fn fma64(x: f64, y: f64, z: f64) f64 {
|
||||
}
|
||||
}
|
||||
|
||||
const dd = struct { hi: f64, lo: f64, };
|
||||
const dd = struct {
|
||||
hi: f64,
|
||||
lo: f64,
|
||||
};
|
||||
|
||||
fn dd_add(a: f64, b: f64) dd {
|
||||
var ret: dd = undefined;
|
||||
|
@ -39,11 +39,11 @@ fn hypot32(x: f32, y: f32) f32 {
|
||||
}
|
||||
|
||||
var z: f32 = 1.0;
|
||||
if (ux >= (0x7F+60) << 23) {
|
||||
if (ux >= (0x7F + 60) << 23) {
|
||||
z = 0x1.0p90;
|
||||
xx *= 0x1.0p-90;
|
||||
yy *= 0x1.0p-90;
|
||||
} else if (uy < (0x7F-60) << 23) {
|
||||
} else if (uy < (0x7F - 60) << 23) {
|
||||
z = 0x1.0p-90;
|
||||
xx *= 0x1.0p-90;
|
||||
yy *= 0x1.0p-90;
|
||||
@ -57,8 +57,8 @@ fn sq(hi: &f64, lo: &f64, x: f64) void {
|
||||
const xc = x * split;
|
||||
const xh = x - xc + xc;
|
||||
const xl = x - xh;
|
||||
*hi = x * x;
|
||||
*lo = xh * xh - *hi + 2 * xh * xl + xl * xl;
|
||||
hi.* = x * x;
|
||||
lo.* = xh * xh - hi.* + 2 * xh * xl + xl * xl;
|
||||
}
|
||||
|
||||
fn hypot64(x: f64, y: f64) f64 {
|
||||
|
@ -120,11 +120,9 @@ pub fn ln_64(x_: f64) f64 {
|
||||
k -= 54;
|
||||
x *= 0x1.0p54;
|
||||
hx = u32(@bitCast(u64, ix) >> 32);
|
||||
}
|
||||
else if (hx >= 0x7FF00000) {
|
||||
} else if (hx >= 0x7FF00000) {
|
||||
return x;
|
||||
}
|
||||
else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
||||
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -35,10 +35,10 @@ pub fn log10(x: var) @typeOf(x) {
|
||||
}
|
||||
|
||||
pub fn log10_32(x_: f32) f32 {
|
||||
const ivln10hi: f32 = 4.3432617188e-01;
|
||||
const ivln10lo: f32 = -3.1689971365e-05;
|
||||
const log10_2hi: f32 = 3.0102920532e-01;
|
||||
const log10_2lo: f32 = 7.9034151668e-07;
|
||||
const ivln10hi: f32 = 4.3432617188e-01;
|
||||
const ivln10lo: f32 = -3.1689971365e-05;
|
||||
const log10_2hi: f32 = 3.0102920532e-01;
|
||||
const log10_2lo: f32 = 7.9034151668e-07;
|
||||
const Lg1: f32 = 0xaaaaaa.0p-24;
|
||||
const Lg2: f32 = 0xccce13.0p-25;
|
||||
const Lg3: f32 = 0x91e9ee.0p-25;
|
||||
@ -95,8 +95,8 @@ pub fn log10_32(x_: f32) f32 {
|
||||
}
|
||||
|
||||
pub fn log10_64(x_: f64) f64 {
|
||||
const ivln10hi: f64 = 4.34294481878168880939e-01;
|
||||
const ivln10lo: f64 = 2.50829467116452752298e-11;
|
||||
const ivln10hi: f64 = 4.34294481878168880939e-01;
|
||||
const ivln10lo: f64 = 2.50829467116452752298e-11;
|
||||
const log10_2hi: f64 = 3.01029995663611771306e-01;
|
||||
const log10_2lo: f64 = 3.69423907715893078616e-13;
|
||||
const Lg1: f64 = 6.666666666666735130e-01;
|
||||
@ -126,11 +126,9 @@ pub fn log10_64(x_: f64) f64 {
|
||||
k -= 54;
|
||||
x *= 0x1.0p54;
|
||||
hx = u32(@bitCast(u64, x) >> 32);
|
||||
}
|
||||
else if (hx >= 0x7FF00000) {
|
||||
} else if (hx >= 0x7FF00000) {
|
||||
return x;
|
||||
}
|
||||
else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
||||
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,10 @@ pub fn log2(x: var) @typeOf(x) {
|
||||
TypeId.IntLiteral => comptime {
|
||||
var result = 0;
|
||||
var x_shifted = x;
|
||||
while (b: {x_shifted >>= 1; break :b x_shifted != 0;}) : (result += 1) {}
|
||||
while (b: {
|
||||
x_shifted >>= 1;
|
||||
break :b x_shifted != 0;
|
||||
}) : (result += 1) {}
|
||||
return result;
|
||||
},
|
||||
TypeId.Int => {
|
||||
@ -38,7 +41,7 @@ pub fn log2(x: var) @typeOf(x) {
|
||||
}
|
||||
|
||||
pub fn log2_32(x_: f32) f32 {
|
||||
const ivln2hi: f32 = 1.4428710938e+00;
|
||||
const ivln2hi: f32 = 1.4428710938e+00;
|
||||
const ivln2lo: f32 = -1.7605285393e-04;
|
||||
const Lg1: f32 = 0xaaaaaa.0p-24;
|
||||
const Lg2: f32 = 0xccce13.0p-25;
|
||||
|
@ -24,13 +24,13 @@ fn round32(x_: f32) f32 {
|
||||
const e = (u >> 23) & 0xFF;
|
||||
var y: f32 = undefined;
|
||||
|
||||
if (e >= 0x7F+23) {
|
||||
if (e >= 0x7F + 23) {
|
||||
return x;
|
||||
}
|
||||
if (u >> 31 != 0) {
|
||||
x = -x;
|
||||
}
|
||||
if (e < 0x7F-1) {
|
||||
if (e < 0x7F - 1) {
|
||||
math.forceEval(x + math.f32_toint);
|
||||
return 0 * @bitCast(f32, u);
|
||||
}
|
||||
@ -61,13 +61,13 @@ fn round64(x_: f64) f64 {
|
||||
const e = (u >> 52) & 0x7FF;
|
||||
var y: f64 = undefined;
|
||||
|
||||
if (e >= 0x3FF+52) {
|
||||
if (e >= 0x3FF + 52) {
|
||||
return x;
|
||||
}
|
||||
if (u >> 63 != 0) {
|
||||
x = -x;
|
||||
}
|
||||
if (e < 0x3ff-1) {
|
||||
if (e < 0x3ff - 1) {
|
||||
math.forceEval(x + math.f64_toint);
|
||||
return 0 * @bitCast(f64, u);
|
||||
}
|
||||
|
@ -19,20 +19,20 @@ pub fn sin(x: var) @typeOf(x) {
|
||||
}
|
||||
|
||||
// sin polynomial coefficients
|
||||
const S0 = 1.58962301576546568060E-10;
|
||||
const S0 = 1.58962301576546568060E-10;
|
||||
const S1 = -2.50507477628578072866E-8;
|
||||
const S2 = 2.75573136213857245213E-6;
|
||||
const S2 = 2.75573136213857245213E-6;
|
||||
const S3 = -1.98412698295895385996E-4;
|
||||
const S4 = 8.33333333332211858878E-3;
|
||||
const S4 = 8.33333333332211858878E-3;
|
||||
const S5 = -1.66666666666666307295E-1;
|
||||
|
||||
// cos polynomial coeffiecients
|
||||
const C0 = -1.13585365213876817300E-11;
|
||||
const C1 = 2.08757008419747316778E-9;
|
||||
const C1 = 2.08757008419747316778E-9;
|
||||
const C2 = -2.75573141792967388112E-7;
|
||||
const C3 = 2.48015872888517045348E-5;
|
||||
const C3 = 2.48015872888517045348E-5;
|
||||
const C4 = -1.38888888888730564116E-3;
|
||||
const C5 = 4.16666666666665929218E-2;
|
||||
const C5 = 4.16666666666665929218E-2;
|
||||
|
||||
// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
|
||||
//
|
||||
|
@ -19,12 +19,12 @@ pub fn tan(x: var) @typeOf(x) {
|
||||
}
|
||||
|
||||
const Tp0 = -1.30936939181383777646E4;
|
||||
const Tp1 = 1.15351664838587416140E6;
|
||||
const Tp1 = 1.15351664838587416140E6;
|
||||
const Tp2 = -1.79565251976484877988E7;
|
||||
|
||||
const Tq1 = 1.36812963470692954678E4;
|
||||
const Tq1 = 1.36812963470692954678E4;
|
||||
const Tq2 = -1.32089234440210967447E6;
|
||||
const Tq3 = 2.50083801823357915839E7;
|
||||
const Tq3 = 2.50083801823357915839E7;
|
||||
const Tq4 = -5.38695755929454629881E7;
|
||||
|
||||
// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
|
||||
|
40
std/net.zig
40
std/net.zig
@ -19,37 +19,29 @@ pub const Address = struct {
|
||||
os_addr: OsAddress,
|
||||
|
||||
pub fn initIp4(ip4: u32, port: u16) Address {
|
||||
return Address {
|
||||
.os_addr = posix.sockaddr {
|
||||
.in = posix.sockaddr_in {
|
||||
.family = posix.AF_INET,
|
||||
.port = std.mem.endianSwapIfLe(u16, port),
|
||||
.addr = ip4,
|
||||
.zero = []u8{0} ** 8,
|
||||
},
|
||||
},
|
||||
};
|
||||
return Address{ .os_addr = posix.sockaddr{ .in = posix.sockaddr_in{
|
||||
.family = posix.AF_INET,
|
||||
.port = std.mem.endianSwapIfLe(u16, port),
|
||||
.addr = ip4,
|
||||
.zero = []u8{0} ** 8,
|
||||
} } };
|
||||
}
|
||||
|
||||
pub fn initIp6(ip6: &const Ip6Addr, port: u16) Address {
|
||||
return Address {
|
||||
return Address{
|
||||
.family = posix.AF_INET6,
|
||||
.os_addr = posix.sockaddr {
|
||||
.in6 = posix.sockaddr_in6 {
|
||||
.family = posix.AF_INET6,
|
||||
.port = std.mem.endianSwapIfLe(u16, port),
|
||||
.flowinfo = 0,
|
||||
.addr = ip6.addr,
|
||||
.scope_id = ip6.scope_id,
|
||||
},
|
||||
},
|
||||
.os_addr = posix.sockaddr{ .in6 = posix.sockaddr_in6{
|
||||
.family = posix.AF_INET6,
|
||||
.port = std.mem.endianSwapIfLe(u16, port),
|
||||
.flowinfo = 0,
|
||||
.addr = ip6.addr,
|
||||
.scope_id = ip6.scope_id,
|
||||
} },
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initPosix(addr: &const posix.sockaddr) Address {
|
||||
return Address {
|
||||
.os_addr = *addr,
|
||||
};
|
||||
return Address{ .os_addr = addr.* };
|
||||
}
|
||||
|
||||
pub fn format(self: &const Address, out_stream: var) !void {
|
||||
@ -98,7 +90,7 @@ pub fn parseIp4(buf: []const u8) !u32 {
|
||||
}
|
||||
} else {
|
||||
return error.InvalidCharacter;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (index == 3 and saw_any_digits) {
|
||||
out_ptr[index] = x;
|
||||
|
@ -49,7 +49,7 @@ pub const ChildProcess = struct {
|
||||
err_pipe: if (is_windows) void else [2]i32,
|
||||
llnode: if (is_windows) void else LinkedList(&ChildProcess).Node,
|
||||
|
||||
pub const SpawnError = error {
|
||||
pub const SpawnError = error{
|
||||
ProcessFdQuotaExceeded,
|
||||
Unexpected,
|
||||
NotDir,
|
||||
@ -88,7 +88,7 @@ pub const ChildProcess = struct {
|
||||
const child = try allocator.create(ChildProcess);
|
||||
errdefer allocator.destroy(child);
|
||||
|
||||
*child = ChildProcess {
|
||||
child.* = ChildProcess{
|
||||
.allocator = allocator,
|
||||
.argv = argv,
|
||||
.pid = undefined,
|
||||
@ -99,8 +99,10 @@ pub const ChildProcess = struct {
|
||||
.term = null,
|
||||
.env_map = null,
|
||||
.cwd = null,
|
||||
.uid = if (is_windows) {} else null,
|
||||
.gid = if (is_windows) {} else null,
|
||||
.uid = if (is_windows) {} else
|
||||
null,
|
||||
.gid = if (is_windows) {} else
|
||||
null,
|
||||
.stdin = null,
|
||||
.stdout = null,
|
||||
.stderr = null,
|
||||
@ -193,9 +195,7 @@ pub const ChildProcess = struct {
|
||||
|
||||
/// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
|
||||
/// If it succeeds, the caller owns result.stdout and result.stderr memory.
|
||||
pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8,
|
||||
env_map: ?&const BufMap, max_output_size: usize) !ExecResult
|
||||
{
|
||||
pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, env_map: ?&const BufMap, max_output_size: usize) !ExecResult {
|
||||
const child = try ChildProcess.init(argv, allocator);
|
||||
defer child.deinit();
|
||||
|
||||
@ -218,7 +218,7 @@ pub const ChildProcess = struct {
|
||||
try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
|
||||
try stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size);
|
||||
|
||||
return ExecResult {
|
||||
return ExecResult{
|
||||
.term = try child.wait(),
|
||||
.stdout = stdout.toOwnedSlice(),
|
||||
.stderr = stderr.toOwnedSlice(),
|
||||
@ -255,9 +255,9 @@ pub const ChildProcess = struct {
|
||||
self.term = (SpawnError!Term)(x: {
|
||||
var exit_code: windows.DWORD = undefined;
|
||||
if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) {
|
||||
break :x Term { .Unknown = 0 };
|
||||
break :x Term{ .Unknown = 0 };
|
||||
} else {
|
||||
break :x Term { .Exited = @bitCast(i32, exit_code)};
|
||||
break :x Term{ .Exited = @bitCast(i32, exit_code) };
|
||||
}
|
||||
});
|
||||
|
||||
@ -288,9 +288,18 @@ pub const ChildProcess = struct {
|
||||
}
|
||||
|
||||
fn cleanupStreams(self: &ChildProcess) void {
|
||||
if (self.stdin) |*stdin| { stdin.close(); self.stdin = null; }
|
||||
if (self.stdout) |*stdout| { stdout.close(); self.stdout = null; }
|
||||
if (self.stderr) |*stderr| { stderr.close(); self.stderr = null; }
|
||||
if (self.stdin) |*stdin| {
|
||||
stdin.close();
|
||||
self.stdin = null;
|
||||
}
|
||||
if (self.stdout) |*stdout| {
|
||||
stdout.close();
|
||||
self.stdout = null;
|
||||
}
|
||||
if (self.stderr) |*stderr| {
|
||||
stderr.close();
|
||||
self.stderr = null;
|
||||
}
|
||||
}
|
||||
|
||||
fn cleanupAfterWait(self: &ChildProcess, status: i32) !Term {
|
||||
@ -317,25 +326,30 @@ pub const ChildProcess = struct {
|
||||
|
||||
fn statusToTerm(status: i32) Term {
|
||||
return if (posix.WIFEXITED(status))
|
||||
Term { .Exited = posix.WEXITSTATUS(status) }
|
||||
Term{ .Exited = posix.WEXITSTATUS(status) }
|
||||
else if (posix.WIFSIGNALED(status))
|
||||
Term { .Signal = posix.WTERMSIG(status) }
|
||||
Term{ .Signal = posix.WTERMSIG(status) }
|
||||
else if (posix.WIFSTOPPED(status))
|
||||
Term { .Stopped = posix.WSTOPSIG(status) }
|
||||
Term{ .Stopped = posix.WSTOPSIG(status) }
|
||||
else
|
||||
Term { .Unknown = status }
|
||||
;
|
||||
Term{ .Unknown = status };
|
||||
}
|
||||
|
||||
fn spawnPosix(self: &ChildProcess) !void {
|
||||
const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined;
|
||||
errdefer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); };
|
||||
errdefer if (self.stdin_behavior == StdIo.Pipe) {
|
||||
destroyPipe(stdin_pipe);
|
||||
};
|
||||
|
||||
const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined;
|
||||
errdefer if (self.stdout_behavior == StdIo.Pipe) { destroyPipe(stdout_pipe); };
|
||||
errdefer if (self.stdout_behavior == StdIo.Pipe) {
|
||||
destroyPipe(stdout_pipe);
|
||||
};
|
||||
|
||||
const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined;
|
||||
errdefer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); };
|
||||
errdefer if (self.stderr_behavior == StdIo.Pipe) {
|
||||
destroyPipe(stderr_pipe);
|
||||
};
|
||||
|
||||
const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
|
||||
const dev_null_fd = if (any_ignore) blk: {
|
||||
@ -346,7 +360,9 @@ pub const ChildProcess = struct {
|
||||
} else blk: {
|
||||
break :blk undefined;
|
||||
};
|
||||
defer { if (any_ignore) os.close(dev_null_fd); }
|
||||
defer {
|
||||
if (any_ignore) os.close(dev_null_fd);
|
||||
}
|
||||
|
||||
var env_map_owned: BufMap = undefined;
|
||||
var we_own_env_map: bool = undefined;
|
||||
@ -358,7 +374,9 @@ pub const ChildProcess = struct {
|
||||
env_map_owned = try os.getEnvMap(self.allocator);
|
||||
break :x &env_map_owned;
|
||||
};
|
||||
defer { if (we_own_env_map) env_map_owned.deinit(); }
|
||||
defer {
|
||||
if (we_own_env_map) env_map_owned.deinit();
|
||||
}
|
||||
|
||||
// This pipe is used to communicate errors between the time of fork
|
||||
// and execve from the child process to the parent process.
|
||||
@ -369,23 +387,21 @@ pub const ChildProcess = struct {
|
||||
const pid_err = posix.getErrno(pid_result);
|
||||
if (pid_err > 0) {
|
||||
return switch (pid_err) {
|
||||
posix.EAGAIN, posix.ENOMEM, posix.ENOSYS => error.SystemResources,
|
||||
posix.EAGAIN,
|
||||
posix.ENOMEM,
|
||||
posix.ENOSYS => error.SystemResources,
|
||||
else => os.unexpectedErrorPosix(pid_err),
|
||||
};
|
||||
}
|
||||
if (pid_result == 0) {
|
||||
// we are the child
|
||||
|
||||
setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch
|
||||
|err| forkChildErrReport(err_pipe[1], err);
|
||||
setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch
|
||||
|err| forkChildErrReport(err_pipe[1], err);
|
||||
setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch
|
||||
|err| forkChildErrReport(err_pipe[1], err);
|
||||
setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
|
||||
setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
|
||||
setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
|
||||
|
||||
if (self.cwd) |cwd| {
|
||||
os.changeCurDir(self.allocator, cwd) catch
|
||||
|err| forkChildErrReport(err_pipe[1], err);
|
||||
os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err);
|
||||
}
|
||||
|
||||
if (self.gid) |gid| {
|
||||
@ -396,8 +412,7 @@ pub const ChildProcess = struct {
|
||||
os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err);
|
||||
}
|
||||
|
||||
os.posixExecve(self.argv, env_map, self.allocator) catch
|
||||
|err| forkChildErrReport(err_pipe[1], err);
|
||||
os.posixExecve(self.argv, env_map, self.allocator) catch |err| forkChildErrReport(err_pipe[1], err);
|
||||
}
|
||||
|
||||
// we are the parent
|
||||
@ -423,37 +438,41 @@ pub const ChildProcess = struct {
|
||||
self.llnode = LinkedList(&ChildProcess).Node.init(self);
|
||||
self.term = null;
|
||||
|
||||
if (self.stdin_behavior == StdIo.Pipe) { os.close(stdin_pipe[0]); }
|
||||
if (self.stdout_behavior == StdIo.Pipe) { os.close(stdout_pipe[1]); }
|
||||
if (self.stderr_behavior == StdIo.Pipe) { os.close(stderr_pipe[1]); }
|
||||
if (self.stdin_behavior == StdIo.Pipe) {
|
||||
os.close(stdin_pipe[0]);
|
||||
}
|
||||
if (self.stdout_behavior == StdIo.Pipe) {
|
||||
os.close(stdout_pipe[1]);
|
||||
}
|
||||
if (self.stderr_behavior == StdIo.Pipe) {
|
||||
os.close(stderr_pipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
fn spawnWindows(self: &ChildProcess) !void {
|
||||
const saAttr = windows.SECURITY_ATTRIBUTES {
|
||||
const saAttr = windows.SECURITY_ATTRIBUTES{
|
||||
.nLength = @sizeOf(windows.SECURITY_ATTRIBUTES),
|
||||
.bInheritHandle = windows.TRUE,
|
||||
.lpSecurityDescriptor = null,
|
||||
};
|
||||
|
||||
const any_ignore = (self.stdin_behavior == StdIo.Ignore or
|
||||
self.stdout_behavior == StdIo.Ignore or
|
||||
self.stderr_behavior == StdIo.Ignore);
|
||||
const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
|
||||
|
||||
const nul_handle = if (any_ignore) blk: {
|
||||
const nul_file_path = "NUL";
|
||||
var fixed_buffer_mem: [nul_file_path.len + 1]u8 = undefined;
|
||||
var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
|
||||
break :blk try os.windowsOpen(&fixed_allocator.allocator, "NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ,
|
||||
windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL);
|
||||
break :blk try os.windowsOpen(&fixed_allocator.allocator, "NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ, windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL);
|
||||
} else blk: {
|
||||
break :blk undefined;
|
||||
};
|
||||
defer { if (any_ignore) os.close(nul_handle); }
|
||||
defer {
|
||||
if (any_ignore) os.close(nul_handle);
|
||||
}
|
||||
if (any_ignore) {
|
||||
try windowsSetHandleInfo(nul_handle, windows.HANDLE_FLAG_INHERIT, 0);
|
||||
}
|
||||
|
||||
|
||||
var g_hChildStd_IN_Rd: ?windows.HANDLE = null;
|
||||
var g_hChildStd_IN_Wr: ?windows.HANDLE = null;
|
||||
switch (self.stdin_behavior) {
|
||||
@ -470,7 +489,9 @@ pub const ChildProcess = struct {
|
||||
g_hChildStd_IN_Rd = null;
|
||||
},
|
||||
}
|
||||
errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); };
|
||||
errdefer if (self.stdin_behavior == StdIo.Pipe) {
|
||||
windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr);
|
||||
};
|
||||
|
||||
var g_hChildStd_OUT_Rd: ?windows.HANDLE = null;
|
||||
var g_hChildStd_OUT_Wr: ?windows.HANDLE = null;
|
||||
@ -488,7 +509,9 @@ pub const ChildProcess = struct {
|
||||
g_hChildStd_OUT_Wr = null;
|
||||
},
|
||||
}
|
||||
errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); };
|
||||
errdefer if (self.stdin_behavior == StdIo.Pipe) {
|
||||
windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr);
|
||||
};
|
||||
|
||||
var g_hChildStd_ERR_Rd: ?windows.HANDLE = null;
|
||||
var g_hChildStd_ERR_Wr: ?windows.HANDLE = null;
|
||||
@ -506,12 +529,14 @@ pub const ChildProcess = struct {
|
||||
g_hChildStd_ERR_Wr = null;
|
||||
},
|
||||
}
|
||||
errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); };
|
||||
errdefer if (self.stdin_behavior == StdIo.Pipe) {
|
||||
windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr);
|
||||
};
|
||||
|
||||
const cmd_line = try windowsCreateCommandLine(self.allocator, self.argv);
|
||||
defer self.allocator.free(cmd_line);
|
||||
|
||||
var siStartInfo = windows.STARTUPINFOA {
|
||||
var siStartInfo = windows.STARTUPINFOA{
|
||||
.cb = @sizeOf(windows.STARTUPINFOA),
|
||||
.hStdError = g_hChildStd_ERR_Wr,
|
||||
.hStdOutput = g_hChildStd_OUT_Wr,
|
||||
@ -534,19 +559,11 @@ pub const ChildProcess = struct {
|
||||
};
|
||||
var piProcInfo: windows.PROCESS_INFORMATION = undefined;
|
||||
|
||||
const cwd_slice = if (self.cwd) |cwd|
|
||||
try cstr.addNullByte(self.allocator, cwd)
|
||||
else
|
||||
null
|
||||
;
|
||||
const cwd_slice = if (self.cwd) |cwd| try cstr.addNullByte(self.allocator, cwd) else null;
|
||||
defer if (cwd_slice) |cwd| self.allocator.free(cwd);
|
||||
const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null;
|
||||
|
||||
const maybe_envp_buf = if (self.env_map) |env_map|
|
||||
try os.createWindowsEnvBlock(self.allocator, env_map)
|
||||
else
|
||||
null
|
||||
;
|
||||
const maybe_envp_buf = if (self.env_map) |env_map| try os.createWindowsEnvBlock(self.allocator, env_map) else null;
|
||||
defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf);
|
||||
const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null;
|
||||
|
||||
@ -563,11 +580,8 @@ pub const ChildProcess = struct {
|
||||
};
|
||||
defer self.allocator.free(app_name);
|
||||
|
||||
windowsCreateProcess(app_name.ptr, cmd_line.ptr, envp_ptr, cwd_ptr,
|
||||
&siStartInfo, &piProcInfo) catch |no_path_err|
|
||||
{
|
||||
if (no_path_err != error.FileNotFound)
|
||||
return no_path_err;
|
||||
windowsCreateProcess(app_name.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, &siStartInfo, &piProcInfo) catch |no_path_err| {
|
||||
if (no_path_err != error.FileNotFound) return no_path_err;
|
||||
|
||||
const PATH = try os.getEnvVarOwned(self.allocator, "PATH");
|
||||
defer self.allocator.free(PATH);
|
||||
@ -577,9 +591,7 @@ pub const ChildProcess = struct {
|
||||
const joined_path = try os.path.join(self.allocator, search_path, app_name);
|
||||
defer self.allocator.free(joined_path);
|
||||
|
||||
if (windowsCreateProcess(joined_path.ptr, cmd_line.ptr, envp_ptr, cwd_ptr,
|
||||
&siStartInfo, &piProcInfo)) |_|
|
||||
{
|
||||
if (windowsCreateProcess(joined_path.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, &siStartInfo, &piProcInfo)) |_| {
|
||||
break;
|
||||
} else |err| if (err == error.FileNotFound) {
|
||||
continue;
|
||||
@ -609,9 +621,15 @@ pub const ChildProcess = struct {
|
||||
self.thread_handle = piProcInfo.hThread;
|
||||
self.term = null;
|
||||
|
||||
if (self.stdin_behavior == StdIo.Pipe) { os.close(??g_hChildStd_IN_Rd); }
|
||||
if (self.stderr_behavior == StdIo.Pipe) { os.close(??g_hChildStd_ERR_Wr); }
|
||||
if (self.stdout_behavior == StdIo.Pipe) { os.close(??g_hChildStd_OUT_Wr); }
|
||||
if (self.stdin_behavior == StdIo.Pipe) {
|
||||
os.close(??g_hChildStd_IN_Rd);
|
||||
}
|
||||
if (self.stderr_behavior == StdIo.Pipe) {
|
||||
os.close(??g_hChildStd_ERR_Wr);
|
||||
}
|
||||
if (self.stdout_behavior == StdIo.Pipe) {
|
||||
os.close(??g_hChildStd_OUT_Wr);
|
||||
}
|
||||
}
|
||||
|
||||
fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) !void {
|
||||
@ -622,18 +640,14 @@ pub const ChildProcess = struct {
|
||||
StdIo.Ignore => try os.posixDup2(dev_null_fd, std_fileno),
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8,
|
||||
lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void
|
||||
{
|
||||
if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0,
|
||||
@ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0)
|
||||
{
|
||||
fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void {
|
||||
if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) {
|
||||
const err = windows.GetLastError();
|
||||
return switch (err) {
|
||||
windows.ERROR.FILE_NOT_FOUND, windows.ERROR.PATH_NOT_FOUND => error.FileNotFound,
|
||||
windows.ERROR.FILE_NOT_FOUND,
|
||||
windows.ERROR.PATH_NOT_FOUND => error.FileNotFound,
|
||||
windows.ERROR.INVALID_PARAMETER => unreachable,
|
||||
windows.ERROR.INVALID_NAME => error.InvalidName,
|
||||
else => os.unexpectedErrorWindows(err),
|
||||
@ -641,9 +655,6 @@ fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Caller must dealloc.
|
||||
/// Guarantees a null byte at result[result.len].
|
||||
fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) ![]u8 {
|
||||
@ -651,8 +662,7 @@ fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8)
|
||||
defer buf.deinit();
|
||||
|
||||
for (argv) |arg, arg_i| {
|
||||
if (arg_i != 0)
|
||||
try buf.appendByte(' ');
|
||||
if (arg_i != 0) try buf.appendByte(' ');
|
||||
if (mem.indexOfAny(u8, arg, " \t\n\"") == null) {
|
||||
try buf.append(arg);
|
||||
continue;
|
||||
@ -686,7 +696,6 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void {
|
||||
if (wr) |h| os.close(h);
|
||||
}
|
||||
|
||||
|
||||
// TODO: workaround for bug where the `const` from `&const` is dropped when the type is
|
||||
// a namespace field lookup
|
||||
const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES;
|
||||
@ -715,8 +724,8 @@ fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const S
|
||||
try windowsMakePipe(&rd_h, &wr_h, sattr);
|
||||
errdefer windowsDestroyPipe(rd_h, wr_h);
|
||||
try windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0);
|
||||
*rd = rd_h;
|
||||
*wr = wr_h;
|
||||
rd.* = rd_h;
|
||||
wr.* = wr_h;
|
||||
}
|
||||
|
||||
fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) !void {
|
||||
@ -725,8 +734,8 @@ fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const
|
||||
try windowsMakePipe(&rd_h, &wr_h, sattr);
|
||||
errdefer windowsDestroyPipe(rd_h, wr_h);
|
||||
try windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0);
|
||||
*rd = rd_h;
|
||||
*wr = wr_h;
|
||||
rd.* = rd_h;
|
||||
wr.* = wr_h;
|
||||
}
|
||||
|
||||
fn makePipe() ![2]i32 {
|
||||
@ -734,7 +743,8 @@ fn makePipe() ![2]i32 {
|
||||
const err = posix.getErrno(posix.pipe(&fds));
|
||||
if (err > 0) {
|
||||
return switch (err) {
|
||||
posix.EMFILE, posix.ENFILE => error.SystemResources,
|
||||
posix.EMFILE,
|
||||
posix.ENFILE => error.SystemResources,
|
||||
else => os.unexpectedErrorPosix(err),
|
||||
};
|
||||
}
|
||||
@ -742,8 +752,8 @@ fn makePipe() ![2]i32 {
|
||||
}
|
||||
|
||||
fn destroyPipe(pipe: &const [2]i32) void {
|
||||
os.close((*pipe)[0]);
|
||||
os.close((*pipe)[1]);
|
||||
os.close((pipe.*)[0]);
|
||||
os.close((pipe.*)[1]);
|
||||
}
|
||||
|
||||
// Child of fork calls this to report an error to the fork parent.
|
||||
|
@ -93,7 +93,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
|
||||
/// Deinitialize with `deinit`
|
||||
pub fn init(allocator: &Allocator) Self {
|
||||
return Self {
|
||||
return Self{
|
||||
.allocator = allocator,
|
||||
.len = 0,
|
||||
.prealloc_segment = undefined,
|
||||
@ -104,7 +104,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
pub fn deinit(self: &Self) void {
|
||||
self.freeShelves(ShelfIndex(self.dynamic_segments.len), 0);
|
||||
self.allocator.free(self.dynamic_segments);
|
||||
*self = undefined;
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn at(self: &Self, i: usize) &T {
|
||||
@ -118,7 +118,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
|
||||
pub fn push(self: &Self, item: &const T) !void {
|
||||
const new_item_ptr = try self.addOne();
|
||||
*new_item_ptr = *item;
|
||||
new_item_ptr.* = item.*;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
pub fn pop(self: &Self) ?T {
|
||||
if (self.len == 0)
|
||||
return null;
|
||||
if (self.len == 0) return null;
|
||||
|
||||
const index = self.len - 1;
|
||||
const result = *self.uncheckedAt(index);
|
||||
const result = self.uncheckedAt(index).*;
|
||||
self.len = index;
|
||||
return result;
|
||||
}
|
||||
@ -245,8 +244,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
shelf_size: usize,
|
||||
|
||||
pub fn next(it: &Iterator) ?&T {
|
||||
if (it.index >= it.list.len)
|
||||
return null;
|
||||
if (it.index >= it.list.len) return null;
|
||||
if (it.index < prealloc_item_count) {
|
||||
const ptr = &it.list.prealloc_segment[it.index];
|
||||
it.index += 1;
|
||||
@ -270,12 +268,10 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
}
|
||||
|
||||
pub fn prev(it: &Iterator) ?&T {
|
||||
if (it.index == 0)
|
||||
return null;
|
||||
if (it.index == 0) return null;
|
||||
|
||||
it.index -= 1;
|
||||
if (it.index < prealloc_item_count)
|
||||
return &it.list.prealloc_segment[it.index];
|
||||
if (it.index < prealloc_item_count) return &it.list.prealloc_segment[it.index];
|
||||
|
||||
if (it.box_index == 0) {
|
||||
it.shelf_index -= 1;
|
||||
@ -290,7 +286,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
};
|
||||
|
||||
pub fn iterator(self: &Self, start_index: usize) Iterator {
|
||||
var it = Iterator {
|
||||
var it = Iterator{
|
||||
.list = self,
|
||||
.index = start_index,
|
||||
.shelf_index = undefined,
|
||||
@ -324,25 +320,31 @@ fn testSegmentedList(comptime prealloc: usize, allocator: &Allocator) !void {
|
||||
var list = SegmentedList(i32, prealloc).init(allocator);
|
||||
defer list.deinit();
|
||||
|
||||
{var i: usize = 0; while (i < 100) : (i += 1) {
|
||||
try list.push(i32(i + 1));
|
||||
assert(list.len == i + 1);
|
||||
}}
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < 100) : (i += 1) {
|
||||
try list.push(i32(i + 1));
|
||||
assert(list.len == i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
{var i: usize = 0; while (i < 100) : (i += 1) {
|
||||
assert(*list.at(i) == i32(i + 1));
|
||||
}}
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < 100) : (i += 1) {
|
||||
assert(list.at(i).* == i32(i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var it = list.iterator(0);
|
||||
var x: i32 = 0;
|
||||
while (it.next()) |item| {
|
||||
x += 1;
|
||||
assert(*item == x);
|
||||
assert(item.* == x);
|
||||
}
|
||||
assert(x == 100);
|
||||
while (it.prev()) |item| : (x -= 1) {
|
||||
assert(*item == x);
|
||||
assert(item.* == x);
|
||||
}
|
||||
assert(x == 0);
|
||||
}
|
||||
@ -350,14 +352,18 @@ fn testSegmentedList(comptime prealloc: usize, allocator: &Allocator) !void {
|
||||
assert(??list.pop() == 100);
|
||||
assert(list.len == 99);
|
||||
|
||||
try list.pushMany([]i32 { 1, 2, 3 });
|
||||
try list.pushMany([]i32{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
});
|
||||
assert(list.len == 102);
|
||||
assert(??list.pop() == 3);
|
||||
assert(??list.pop() == 2);
|
||||
assert(??list.pop() == 1);
|
||||
assert(list.len == 99);
|
||||
|
||||
try list.pushMany([]const i32 {});
|
||||
try list.pushMany([]const i32{});
|
||||
assert(list.len == 99);
|
||||
|
||||
var i: i32 = 99;
|
||||
|
564
std/sort.zig
564
std/sort.zig
@ -5,15 +5,18 @@ const math = std.math;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
/// Stable in-place sort. O(n) best case, O(pow(n, 2)) worst case. O(1) memory (no allocator required).
|
||||
pub fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void {
|
||||
{var i: usize = 1; while (i < items.len) : (i += 1) {
|
||||
const x = items[i];
|
||||
var j: usize = i;
|
||||
while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) {
|
||||
items[j] = items[j - 1];
|
||||
pub fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) void {
|
||||
{
|
||||
var i: usize = 1;
|
||||
while (i < items.len) : (i += 1) {
|
||||
const x = items[i];
|
||||
var j: usize = i;
|
||||
while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) {
|
||||
items[j] = items[j - 1];
|
||||
}
|
||||
items[j] = x;
|
||||
}
|
||||
items[j] = x;
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
const Range = struct {
|
||||
@ -21,7 +24,10 @@ const Range = struct {
|
||||
end: usize,
|
||||
|
||||
fn init(start: usize, end: usize) Range {
|
||||
return Range { .start = start, .end = end };
|
||||
return Range{
|
||||
.start = start,
|
||||
.end = end,
|
||||
};
|
||||
}
|
||||
|
||||
fn length(self: &const Range) usize {
|
||||
@ -29,7 +35,6 @@ const Range = struct {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const Iterator = struct {
|
||||
size: usize,
|
||||
power_of_two: usize,
|
||||
@ -42,7 +47,7 @@ const Iterator = struct {
|
||||
fn init(size2: usize, min_level: usize) Iterator {
|
||||
const power_of_two = math.floorPowerOfTwo(usize, size2);
|
||||
const denominator = power_of_two / min_level;
|
||||
return Iterator {
|
||||
return Iterator{
|
||||
.numerator = 0,
|
||||
.decimal = 0,
|
||||
.size = size2,
|
||||
@ -68,7 +73,10 @@ const Iterator = struct {
|
||||
self.decimal += 1;
|
||||
}
|
||||
|
||||
return Range {.start = start, .end = self.decimal};
|
||||
return Range{
|
||||
.start = start,
|
||||
.end = self.decimal,
|
||||
};
|
||||
}
|
||||
|
||||
fn finished(self: &Iterator) bool {
|
||||
@ -100,7 +108,7 @@ const Pull = struct {
|
||||
|
||||
/// Stable in-place sort. O(n) best case, O(n*log(n)) worst case and average case. O(1) memory (no allocator required).
|
||||
/// Currently implemented as block sort.
|
||||
pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void {
|
||||
pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) void {
|
||||
// Implementation ported from https://github.com/BonzaiThePenguin/WikiSort/blob/master/WikiSort.c
|
||||
var cache: [512]T = undefined;
|
||||
|
||||
@ -123,7 +131,16 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
|
||||
// http://pages.ripco.net/~jgamble/nw.html
|
||||
var iterator = Iterator.init(items.len, 4);
|
||||
while (!iterator.finished()) {
|
||||
var order = []u8{0, 1, 2, 3, 4, 5, 6, 7};
|
||||
var order = []u8{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
};
|
||||
const range = iterator.nextRange();
|
||||
|
||||
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
|
||||
swap(T, sliced_items, lessThan, &order, 3, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 4);
|
||||
},
|
||||
7 => {
|
||||
swap(T, sliced_items, lessThan, &order, 1, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 5, 6);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 4, 6);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 1);
|
||||
swap(T, sliced_items, lessThan, &order, 4, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 6);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 3);
|
||||
},
|
||||
6 => {
|
||||
swap(T, sliced_items, lessThan, &order, 1, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 4, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 1);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 3);
|
||||
},
|
||||
5 => {
|
||||
swap(T, sliced_items, lessThan, &order, 0, 1);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 2);
|
||||
},
|
||||
4 => {
|
||||
swap(T, sliced_items, lessThan, &order, 0, 1);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 2);
|
||||
},
|
||||
7 => {
|
||||
swap(T, sliced_items, lessThan, &order, 1, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 5, 6);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 4, 6);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 1);
|
||||
swap(T, sliced_items, lessThan, &order, 4, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 6);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 3);
|
||||
},
|
||||
6 => {
|
||||
swap(T, sliced_items, lessThan, &order, 1, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 4, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 1);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 5);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 3);
|
||||
},
|
||||
5 => {
|
||||
swap(T, sliced_items, lessThan, &order, 0, 1);
|
||||
swap(T, sliced_items, lessThan, &order, 3, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 4);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 2);
|
||||
},
|
||||
4 => {
|
||||
swap(T, sliced_items, lessThan, &order, 0, 1);
|
||||
swap(T, sliced_items, lessThan, &order, 2, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 0, 2);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 3);
|
||||
swap(T, sliced_items, lessThan, &order, 1, 2);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
@ -273,7 +290,6 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
|
||||
// we merged two levels at the same time, so we're done with this level already
|
||||
// (iterator.nextLevel() is called again at the bottom of this outer merge loop)
|
||||
_ = iterator.nextLevel();
|
||||
|
||||
} else {
|
||||
iterator.begin();
|
||||
while (!iterator.finished()) {
|
||||
@ -303,7 +319,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
|
||||
// 8. redistribute the two internal buffers back into the items
|
||||
|
||||
var block_size: usize = math.sqrt(iterator.length());
|
||||
var buffer_size = iterator.length()/block_size + 1;
|
||||
var buffer_size = iterator.length() / block_size + 1;
|
||||
|
||||
// as an optimization, we really only need to pull out the internal buffers once for each level of merges
|
||||
// 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
|
||||
var start: usize = 0;
|
||||
var pull_index: usize = 0;
|
||||
var pull = []Pull{
|
||||
Pull {.from = 0, .to = 0, .count = 0, .range = Range.init(0, 0),},
|
||||
Pull {.from = 0, .to = 0, .count = 0, .range = Range.init(0, 0),},
|
||||
Pull{
|
||||
.from = 0,
|
||||
.to = 0,
|
||||
.count = 0,
|
||||
.range = Range.init(0, 0),
|
||||
},
|
||||
Pull{
|
||||
.from = 0,
|
||||
.to = 0,
|
||||
.count = 0,
|
||||
.range = Range.init(0, 0),
|
||||
},
|
||||
};
|
||||
|
||||
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
|
||||
// these values will be pulled out to the start of A
|
||||
last = A.start;
|
||||
count = 1;
|
||||
while (count < find) : ({last = index; count += 1;}) {
|
||||
while (count < find) : ({
|
||||
last = index;
|
||||
count += 1;
|
||||
}) {
|
||||
index = findLastForward(T, items, items[last], Range.init(last + 1, A.end), lessThan, find - count);
|
||||
if (index == A.end) break;
|
||||
}
|
||||
@ -363,7 +392,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
|
||||
|
||||
if (count >= buffer_size) {
|
||||
// keep track of the range within the items where we'll need to "pull out" these values to create the internal buffer
|
||||
pull[pull_index] = Pull {
|
||||
pull[pull_index] = Pull{
|
||||
.range = Range.init(A.start, B.end),
|
||||
.count = count,
|
||||
.from = index,
|
||||
@ -398,7 +427,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
|
||||
} else if (pull_index == 0 and count > buffer1.length()) {
|
||||
// keep track of the largest buffer we were able to find
|
||||
buffer1 = Range.init(A.start, A.start + count);
|
||||
pull[pull_index] = Pull {
|
||||
pull[pull_index] = Pull{
|
||||
.range = Range.init(A.start, B.end),
|
||||
.count = count,
|
||||
.from = index,
|
||||
@ -410,7 +439,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
|
||||
// these values will be pulled out to the end of B
|
||||
last = B.end - 1;
|
||||
count = 1;
|
||||
while (count < find) : ({last = index - 1; count += 1;}) {
|
||||
while (count < find) : ({
|
||||
last = index - 1;
|
||||
count += 1;
|
||||
}) {
|
||||
index = findFirstBackward(T, items, items[last], Range.init(B.start, last), lessThan, find - count);
|
||||
if (index == B.start) break;
|
||||
}
|
||||
@ -418,7 +450,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
|
||||
|
||||
if (count >= buffer_size) {
|
||||
// keep track of the range within the items where we'll need to "pull out" these values to create the internal buffe
|
||||
pull[pull_index] = Pull {
|
||||
pull[pull_index] = Pull{
|
||||
.range = Range.init(A.start, B.end),
|
||||
.count = count,
|
||||
.from = index,
|
||||
@ -457,7 +489,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
|
||||
} else if (pull_index == 0 and count > buffer1.length()) {
|
||||
// keep track of the largest buffer we were able to find
|
||||
buffer1 = Range.init(B.end - count, B.end);
|
||||
pull[pull_index] = Pull {
|
||||
pull[pull_index] = Pull{
|
||||
.range = Range.init(A.start, B.end),
|
||||
.count = count,
|
||||
.from = index,
|
||||
@ -496,7 +528,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
|
||||
|
||||
// adjust block_size and buffer_size based on the values we were able to pull out
|
||||
buffer_size = buffer1.length();
|
||||
block_size = iterator.length()/buffer_size + 1;
|
||||
block_size = iterator.length() / buffer_size + 1;
|
||||
|
||||
// the first buffer NEEDS to be large enough to tag each of the evenly sized A blocks,
|
||||
// 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
|
||||
// swap the first value of each A block with the value in buffer1
|
||||
var indexA = buffer1.start;
|
||||
index = firstA.end;
|
||||
while (index < blockA.end) : ({indexA += 1; index += block_size;}) {
|
||||
while (index < blockA.end) : ({
|
||||
indexA += 1;
|
||||
index += block_size;
|
||||
}) {
|
||||
mem.swap(T, &items[indexA], &items[index]);
|
||||
}
|
||||
|
||||
@ -626,9 +661,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
|
||||
|
||||
// if there are no more A blocks remaining, this step is finished!
|
||||
blockA.start += block_size;
|
||||
if (blockA.length() == 0)
|
||||
break;
|
||||
|
||||
if (blockA.length() == 0) break;
|
||||
} else if (blockB.length() < block_size) {
|
||||
// move the last B block, which is unevenly sized, to before the remaining A blocks, by using a rotation
|
||||
// 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
|
||||
}
|
||||
|
||||
// merge operation without a buffer
|
||||
fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T,&const T)bool) void {
|
||||
fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T, &const T) bool) void {
|
||||
if (A_arg.length() == 0 or B_arg.length() == 0) return;
|
||||
|
||||
// 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
|
||||
// again, this is NOT a general-purpose solution – it only works well in this case!
|
||||
// kind of like how the O(n^2) insertion sort is used in some places
|
||||
|
||||
var A = *A_arg;
|
||||
var B = *B_arg;
|
||||
var A = A_arg.*;
|
||||
var B = B_arg.*;
|
||||
|
||||
while (true) {
|
||||
// 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
|
||||
}
|
||||
|
||||
// merge operation using an internal buffer
|
||||
fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, buffer: &const Range) void {
|
||||
fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, buffer: &const Range) void {
|
||||
// whenever we find a value to add to the final array, swap it with the value that's already in that spot
|
||||
// when this algorithm is finished, 'buffer' will contain its original contents, but in a different order
|
||||
var A_count: usize = 0;
|
||||
@ -787,9 +820,9 @@ fn blockSwap(comptime T: type, items: []T, start1: usize, start2: usize, block_s
|
||||
|
||||
// combine a linear search with a binary search to reduce the number of comparisons in situations
|
||||
// where have some idea as to how many unique values there are and where the next value might be
|
||||
fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize {
|
||||
fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize {
|
||||
if (range.length() == 0) return range.start;
|
||||
const skip = math.max(range.length()/unique, usize(1));
|
||||
const skip = math.max(range.length() / unique, usize(1));
|
||||
|
||||
var index = range.start + skip;
|
||||
while (lessThan(items[index - 1], value)) : (index += skip) {
|
||||
@ -801,9 +834,9 @@ fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const
|
||||
return binaryFirst(T, items, value, Range.init(index - skip, index), lessThan);
|
||||
}
|
||||
|
||||
fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize {
|
||||
fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize {
|
||||
if (range.length() == 0) return range.start;
|
||||
const skip = math.max(range.length()/unique, usize(1));
|
||||
const skip = math.max(range.length() / unique, usize(1));
|
||||
|
||||
var index = range.end - skip;
|
||||
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
|
||||
return binaryFirst(T, items, value, Range.init(index, index + skip), lessThan);
|
||||
}
|
||||
|
||||
fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize {
|
||||
fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize {
|
||||
if (range.length() == 0) return range.start;
|
||||
const skip = math.max(range.length()/unique, usize(1));
|
||||
const skip = math.max(range.length() / unique, usize(1));
|
||||
|
||||
var index = range.start + skip;
|
||||
while (!lessThan(value, items[index - 1])) : (index += skip) {
|
||||
@ -829,9 +862,9 @@ fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const
|
||||
return binaryLast(T, items, value, Range.init(index - skip, index), lessThan);
|
||||
}
|
||||
|
||||
fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize {
|
||||
fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize {
|
||||
if (range.length() == 0) return range.start;
|
||||
const skip = math.max(range.length()/unique, usize(1));
|
||||
const skip = math.max(range.length() / unique, usize(1));
|
||||
|
||||
var index = range.end - skip;
|
||||
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
|
||||
return binaryLast(T, items, value, Range.init(index, index + skip), lessThan);
|
||||
}
|
||||
|
||||
fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize {
|
||||
fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool) usize {
|
||||
var start = range.start;
|
||||
var end = range.end - 1;
|
||||
if (range.start >= range.end) return range.end;
|
||||
while (start < end) {
|
||||
const mid = start + (end - start)/2;
|
||||
const mid = start + (end - start) / 2;
|
||||
if (lessThan(items[mid], value)) {
|
||||
start = mid + 1;
|
||||
} else {
|
||||
@ -861,12 +894,12 @@ fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Rang
|
||||
return start;
|
||||
}
|
||||
|
||||
fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize {
|
||||
fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool) usize {
|
||||
var start = range.start;
|
||||
var end = range.end - 1;
|
||||
if (range.start >= range.end) return range.end;
|
||||
while (start < end) {
|
||||
const mid = start + (end - start)/2;
|
||||
const mid = start + (end - start) / 2;
|
||||
if (!lessThan(value, items[mid])) {
|
||||
start = mid + 1;
|
||||
} else {
|
||||
@ -879,7 +912,7 @@ fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range
|
||||
return start;
|
||||
}
|
||||
|
||||
fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, into: []T) void {
|
||||
fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, into: []T) void {
|
||||
var A_index: usize = A.start;
|
||||
var B_index: usize = B.start;
|
||||
const A_last = A.end;
|
||||
@ -909,7 +942,7 @@ fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, less
|
||||
}
|
||||
}
|
||||
|
||||
fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, cache: []T) void {
|
||||
fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, cache: []T) void {
|
||||
// A fits into the cache, so use that instead of the internal buffer
|
||||
var A_index: usize = 0;
|
||||
var B_index: usize = B.start;
|
||||
@ -937,29 +970,27 @@ fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range,
|
||||
mem.copy(T, items[insert_index..], cache[A_index..A_last]);
|
||||
}
|
||||
|
||||
fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool, order: &[8]u8, x: usize, y: usize) void {
|
||||
if (lessThan(items[y], items[x]) or
|
||||
((*order)[x] > (*order)[y] and !lessThan(items[x], items[y])))
|
||||
{
|
||||
fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool, order: &[8]u8, x: usize, y: usize) void {
|
||||
if (lessThan(items[y], items[x]) or ((order.*)[x] > (order.*)[y] and !lessThan(items[x], items[y]))) {
|
||||
mem.swap(T, &items[x], &items[y]);
|
||||
mem.swap(u8, &(*order)[x], &(*order)[y]);
|
||||
mem.swap(u8, &(order.*)[x], &(order.*)[y]);
|
||||
}
|
||||
}
|
||||
|
||||
fn i32asc(lhs: &const i32, rhs: &const i32) bool {
|
||||
return *lhs < *rhs;
|
||||
return lhs.* < rhs.*;
|
||||
}
|
||||
|
||||
fn i32desc(lhs: &const i32, rhs: &const i32) bool {
|
||||
return *rhs < *lhs;
|
||||
return rhs.* < lhs.*;
|
||||
}
|
||||
|
||||
fn u8asc(lhs: &const u8, rhs: &const u8) bool {
|
||||
return *lhs < *rhs;
|
||||
return lhs.* < rhs.*;
|
||||
}
|
||||
|
||||
fn u8desc(lhs: &const u8, rhs: &const u8) bool {
|
||||
return *rhs < *lhs;
|
||||
return rhs.* < lhs.*;
|
||||
}
|
||||
|
||||
test "stable sort" {
|
||||
@ -967,44 +998,125 @@ test "stable sort" {
|
||||
comptime testStableSort();
|
||||
}
|
||||
fn testStableSort() void {
|
||||
var expected = []IdAndValue {
|
||||
IdAndValue{.id = 0, .value = 0},
|
||||
IdAndValue{.id = 1, .value = 0},
|
||||
IdAndValue{.id = 2, .value = 0},
|
||||
IdAndValue{.id = 0, .value = 1},
|
||||
IdAndValue{.id = 1, .value = 1},
|
||||
IdAndValue{.id = 2, .value = 1},
|
||||
IdAndValue{.id = 0, .value = 2},
|
||||
IdAndValue{.id = 1, .value = 2},
|
||||
IdAndValue{.id = 2, .value = 2},
|
||||
};
|
||||
var cases = [][9]IdAndValue {
|
||||
[]IdAndValue {
|
||||
IdAndValue{.id = 0, .value = 0},
|
||||
IdAndValue{.id = 0, .value = 1},
|
||||
IdAndValue{.id = 0, .value = 2},
|
||||
IdAndValue{.id = 1, .value = 0},
|
||||
IdAndValue{.id = 1, .value = 1},
|
||||
IdAndValue{.id = 1, .value = 2},
|
||||
IdAndValue{.id = 2, .value = 0},
|
||||
IdAndValue{.id = 2, .value = 1},
|
||||
IdAndValue{.id = 2, .value = 2},
|
||||
var expected = []IdAndValue{
|
||||
IdAndValue{
|
||||
.id = 0,
|
||||
.value = 0,
|
||||
},
|
||||
[]IdAndValue {
|
||||
IdAndValue{.id = 0, .value = 2},
|
||||
IdAndValue{.id = 0, .value = 1},
|
||||
IdAndValue{.id = 0, .value = 0},
|
||||
IdAndValue{.id = 1, .value = 2},
|
||||
IdAndValue{.id = 1, .value = 1},
|
||||
IdAndValue{.id = 1, .value = 0},
|
||||
IdAndValue{.id = 2, .value = 2},
|
||||
IdAndValue{.id = 2, .value = 1},
|
||||
IdAndValue{.id = 2, .value = 0},
|
||||
IdAndValue{
|
||||
.id = 1,
|
||||
.value = 0,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 2,
|
||||
.value = 0,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 0,
|
||||
.value = 1,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 1,
|
||||
.value = 1,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 2,
|
||||
.value = 1,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 0,
|
||||
.value = 2,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 1,
|
||||
.value = 2,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 2,
|
||||
.value = 2,
|
||||
},
|
||||
};
|
||||
var cases = [][9]IdAndValue{
|
||||
[]IdAndValue{
|
||||
IdAndValue{
|
||||
.id = 0,
|
||||
.value = 0,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 0,
|
||||
.value = 1,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 0,
|
||||
.value = 2,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 1,
|
||||
.value = 0,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 1,
|
||||
.value = 1,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 1,
|
||||
.value = 2,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 2,
|
||||
.value = 0,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 2,
|
||||
.value = 1,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 2,
|
||||
.value = 2,
|
||||
},
|
||||
},
|
||||
[]IdAndValue{
|
||||
IdAndValue{
|
||||
.id = 0,
|
||||
.value = 2,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 0,
|
||||
.value = 1,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 0,
|
||||
.value = 0,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 1,
|
||||
.value = 2,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 1,
|
||||
.value = 1,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 1,
|
||||
.value = 0,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 2,
|
||||
.value = 2,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 2,
|
||||
.value = 1,
|
||||
},
|
||||
IdAndValue{
|
||||
.id = 2,
|
||||
.value = 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
for (cases) |*case| {
|
||||
insertionSort(IdAndValue, (*case)[0..], cmpByValue);
|
||||
for (*case) |item, i| {
|
||||
insertionSort(IdAndValue, (case.*)[0..], cmpByValue);
|
||||
for (case.*) |item, i| {
|
||||
assert(item.id == expected[i].id);
|
||||
assert(item.value == expected[i].value);
|
||||
}
|
||||
@ -1019,13 +1131,31 @@ fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) bool {
|
||||
}
|
||||
|
||||
test "std.sort" {
|
||||
const u8cases = [][]const []const u8 {
|
||||
[][]const u8{"", ""},
|
||||
[][]const u8{"a", "a"},
|
||||
[][]const u8{"az", "az"},
|
||||
[][]const u8{"za", "az"},
|
||||
[][]const u8{"asdf", "adfs"},
|
||||
[][]const u8{"one", "eno"},
|
||||
const u8cases = [][]const []const u8{
|
||||
[][]const u8{
|
||||
"",
|
||||
"",
|
||||
},
|
||||
[][]const u8{
|
||||
"a",
|
||||
"a",
|
||||
},
|
||||
[][]const u8{
|
||||
"az",
|
||||
"az",
|
||||
},
|
||||
[][]const u8{
|
||||
"za",
|
||||
"az",
|
||||
},
|
||||
[][]const u8{
|
||||
"asdf",
|
||||
"adfs",
|
||||
},
|
||||
[][]const u8{
|
||||
"one",
|
||||
"eno",
|
||||
},
|
||||
};
|
||||
|
||||
for (u8cases) |case| {
|
||||
@ -1036,13 +1166,59 @@ test "std.sort" {
|
||||
assert(mem.eql(u8, slice, case[1]));
|
||||
}
|
||||
|
||||
const i32cases = [][]const []const i32 {
|
||||
[][]const i32{[]i32{}, []i32{}},
|
||||
[][]const i32{[]i32{1}, []i32{1}},
|
||||
[][]const i32{[]i32{0, 1}, []i32{0, 1}},
|
||||
[][]const i32{[]i32{1, 0}, []i32{0, 1}},
|
||||
[][]const i32{[]i32{1, -1, 0}, []i32{-1, 0, 1}},
|
||||
[][]const i32{[]i32{2, 1, 3}, []i32{1, 2, 3}},
|
||||
const i32cases = [][]const []const i32{
|
||||
[][]const i32{
|
||||
[]i32{},
|
||||
[]i32{},
|
||||
},
|
||||
[][]const i32{
|
||||
[]i32{1},
|
||||
[]i32{1},
|
||||
},
|
||||
[][]const i32{
|
||||
[]i32{
|
||||
0,
|
||||
1,
|
||||
},
|
||||
[]i32{
|
||||
0,
|
||||
1,
|
||||
},
|
||||
},
|
||||
[][]const i32{
|
||||
[]i32{
|
||||
1,
|
||||
0,
|
||||
},
|
||||
[]i32{
|
||||
0,
|
||||
1,
|
||||
},
|
||||
},
|
||||
[][]const i32{
|
||||
[]i32{
|
||||
1,
|
||||
-1,
|
||||
0,
|
||||
},
|
||||
[]i32{
|
||||
-1,
|
||||
0,
|
||||
1,
|
||||
},
|
||||
},
|
||||
[][]const i32{
|
||||
[]i32{
|
||||
2,
|
||||
1,
|
||||
3,
|
||||
},
|
||||
[]i32{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
for (i32cases) |case| {
|
||||
@ -1055,13 +1231,59 @@ test "std.sort" {
|
||||
}
|
||||
|
||||
test "std.sort descending" {
|
||||
const rev_cases = [][]const []const i32 {
|
||||
[][]const i32{[]i32{}, []i32{}},
|
||||
[][]const i32{[]i32{1}, []i32{1}},
|
||||
[][]const i32{[]i32{0, 1}, []i32{1, 0}},
|
||||
[][]const i32{[]i32{1, 0}, []i32{1, 0}},
|
||||
[][]const i32{[]i32{1, -1, 0}, []i32{1, 0, -1}},
|
||||
[][]const i32{[]i32{2, 1, 3}, []i32{3, 2, 1}},
|
||||
const rev_cases = [][]const []const i32{
|
||||
[][]const i32{
|
||||
[]i32{},
|
||||
[]i32{},
|
||||
},
|
||||
[][]const i32{
|
||||
[]i32{1},
|
||||
[]i32{1},
|
||||
},
|
||||
[][]const i32{
|
||||
[]i32{
|
||||
0,
|
||||
1,
|
||||
},
|
||||
[]i32{
|
||||
1,
|
||||
0,
|
||||
},
|
||||
},
|
||||
[][]const i32{
|
||||
[]i32{
|
||||
1,
|
||||
0,
|
||||
},
|
||||
[]i32{
|
||||
1,
|
||||
0,
|
||||
},
|
||||
},
|
||||
[][]const i32{
|
||||
[]i32{
|
||||
1,
|
||||
-1,
|
||||
0,
|
||||
},
|
||||
[]i32{
|
||||
1,
|
||||
0,
|
||||
-1,
|
||||
},
|
||||
},
|
||||
[][]const i32{
|
||||
[]i32{
|
||||
2,
|
||||
1,
|
||||
3,
|
||||
},
|
||||
[]i32{
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
for (rev_cases) |case| {
|
||||
@ -1074,10 +1296,22 @@ test "std.sort descending" {
|
||||
}
|
||||
|
||||
test "another sort case" {
|
||||
var arr = []i32{ 5, 3, 1, 2, 4 };
|
||||
var arr = []i32{
|
||||
5,
|
||||
3,
|
||||
1,
|
||||
2,
|
||||
4,
|
||||
};
|
||||
sort(i32, arr[0..], i32asc);
|
||||
|
||||
assert(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 }));
|
||||
assert(mem.eql(i32, arr, []i32{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
}));
|
||||
}
|
||||
|
||||
test "sort fuzz testing" {
|
||||
@ -1112,7 +1346,7 @@ fn fuzzTest(rng: &std.rand.Random) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T {
|
||||
pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) T {
|
||||
var i: usize = 0;
|
||||
var smallest = items[0];
|
||||
for (items[1..]) |item| {
|
||||
@ -1123,7 +1357,7 @@ pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const
|
||||
return smallest;
|
||||
}
|
||||
|
||||
pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T {
|
||||
pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) T {
|
||||
var i: usize = 0;
|
||||
var biggest = items[0];
|
||||
for (items[1..]) |item| {
|
||||
|
Loading…
Reference in New Issue
Block a user