aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-12-23 17:04:26 -0500
committerAndrew Kelley <superjoe30@gmail.com>2018-12-23 17:04:26 -0500
commitc00216701c64269a2395e84f3ccff99d6fb89ffc (patch)
tree9fa071b9e96f9eadc5069b71634b11fc13b00839 /std
parentc21884e1d64e4193e03be4f3064917a26b34b142 (diff)
parent45081c1e9cc28757cb563c77553631f7a92b29d8 (diff)
downloadzig-c00216701c64269a2395e84f3ccff99d6fb89ffc.tar.gz
zig-c00216701c64269a2395e84f3ccff99d6fb89ffc.zip
Merge remote-tracking branch 'origin/master' into llvm8
Diffstat (limited to 'std')
-rw-r--r--std/array_list.zig11
-rw-r--r--std/atomic/int.zig4
-rw-r--r--std/buf_map.zig36
-rw-r--r--std/build.zig46
-rw-r--r--std/c/freebsd.zig33
-rw-r--r--std/c/index.zig1
-rw-r--r--std/coff.zig44
-rw-r--r--std/crypto/blake2.zig11
-rw-r--r--std/crypto/chacha20.zig53
-rw-r--r--std/crypto/md5.zig3
-rw-r--r--std/crypto/poly1305.zig27
-rw-r--r--std/crypto/sha1.zig3
-rw-r--r--std/crypto/sha2.zig6
-rw-r--r--std/crypto/sha3.zig5
-rw-r--r--std/crypto/x25519.zig41
-rw-r--r--std/debug/index.zig499
-rw-r--r--std/dynamic_library.zig4
-rw-r--r--std/elf.zig115
-rw-r--r--std/event/fs.zig31
-rw-r--r--std/event/io.zig14
-rw-r--r--std/event/loop.zig27
-rw-r--r--std/fmt/index.zig80
-rw-r--r--std/hash/siphash.zig14
-rw-r--r--std/hash_map.zig14
-rw-r--r--std/heap.zig8
-rw-r--r--std/index.zig3
-rw-r--r--std/io.zig141
-rw-r--r--std/io/seekable_stream.zig32
-rw-r--r--std/json.zig27
-rw-r--r--std/json_test.zig638
-rw-r--r--std/linked_list.zig96
-rw-r--r--std/math/index.zig70
-rw-r--r--std/mem.zig425
-rw-r--r--std/meta/index.zig48
-rw-r--r--std/net.zig12
-rw-r--r--std/os/child_process.zig17
-rw-r--r--std/os/file.zig70
-rw-r--r--std/os/freebsd/errno.zig121
-rw-r--r--std/os/freebsd/index.zig801
-rw-r--r--std/os/freebsd/syscall.zig493
-rw-r--r--std/os/freebsd/x86_64.zig136
-rw-r--r--std/os/get_app_data_dir.zig2
-rw-r--r--std/os/get_user_id.zig2
-rw-r--r--std/os/index.zig95
-rw-r--r--std/os/linux/index.zig103
-rw-r--r--std/os/path.zig14
-rw-r--r--std/os/windows/kernel32.zig6
-rw-r--r--std/os/zen.zig22
-rw-r--r--std/pdb.zig7
-rw-r--r--std/rand/index.zig201
-rw-r--r--std/rand/ziggurat.zig2
-rw-r--r--std/segmented_list.zig5
-rw-r--r--std/special/bootstrap.zig18
-rw-r--r--std/special/build_runner.zig1
-rw-r--r--std/special/compiler_rt/fixdfdi.zig11
-rw-r--r--std/special/compiler_rt/fixdfdi_test.zig66
-rw-r--r--std/special/compiler_rt/fixdfsi.zig11
-rw-r--r--std/special/compiler_rt/fixdfsi_test.zig74
-rw-r--r--std/special/compiler_rt/fixdfti.zig11
-rw-r--r--std/special/compiler_rt/fixdfti_test.zig66
-rw-r--r--std/special/compiler_rt/fixint.zig74
-rw-r--r--std/special/compiler_rt/fixint_test.zig152
-rw-r--r--std/special/compiler_rt/fixsfdi.zig11
-rw-r--r--std/special/compiler_rt/fixsfdi_test.zig68
-rw-r--r--std/special/compiler_rt/fixsfsi.zig11
-rw-r--r--std/special/compiler_rt/fixsfsi_test.zig76
-rw-r--r--std/special/compiler_rt/fixsfti.zig11
-rw-r--r--std/special/compiler_rt/fixsfti_test.zig84
-rw-r--r--std/special/compiler_rt/fixtfdi.zig11
-rw-r--r--std/special/compiler_rt/fixtfdi_test.zig76
-rw-r--r--std/special/compiler_rt/fixtfsi.zig11
-rw-r--r--std/special/compiler_rt/fixtfsi_test.zig76
-rw-r--r--std/special/compiler_rt/fixtfti.zig11
-rw-r--r--std/special/compiler_rt/fixtfti_test.zig66
-rw-r--r--std/special/compiler_rt/index.zig153
-rw-r--r--std/unicode.zig32
76 files changed, 4695 insertions, 1205 deletions
diff --git a/std/array_list.zig b/std/array_list.zig
index 3ee425fe14..ddad9c989c 100644
--- a/std/array_list.zig
+++ b/std/array_list.zig
@@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" {
assert(list.len == 6);
assert(list.items[0] == 1);
}
+
+const Item = struct {
+ integer: i32,
+ sub_items: ArrayList(Item),
+};
+
+test "std.ArrayList: ArrayList(T) of struct T" {
+ var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(debug.global_allocator) };
+ try root.sub_items.append( Item{ .integer = 42, .sub_items = ArrayList(Item).init(debug.global_allocator) } );
+ assert(root.sub_items.items[0].integer == 42);
+}
diff --git a/std/atomic/int.zig b/std/atomic/int.zig
index 38b85873c0..94985b914f 100644
--- a/std/atomic/int.zig
+++ b/std/atomic/int.zig
@@ -26,6 +26,10 @@ pub fn Int(comptime T: type) type {
return @atomicLoad(T, &self.unprotected_value, AtomicOrder.SeqCst);
}
+ pub fn set(self: *Self, new_value: T) void {
+ _ = self.xchg(new_value);
+ }
+
pub fn xchg(self: *Self, new_value: T) T {
return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst);
}
diff --git a/std/buf_map.zig b/std/buf_map.zig
index a82d1b731a..6de0d20cdb 100644
--- a/std/buf_map.zig
+++ b/std/buf_map.zig
@@ -16,7 +16,7 @@ pub const BufMap = struct {
return self;
}
- pub fn deinit(self: *const BufMap) void {
+ pub fn deinit(self: *BufMap) void {
var it = self.hash_map.iterator();
while (true) {
const entry = it.next() orelse break;
@@ -27,16 +27,34 @@ pub const BufMap = struct {
self.hash_map.deinit();
}
+ /// Same as `set` but the key and value become owned by the BufMap rather
+ /// than being copied.
+ /// If `setMove` fails, the ownership of key and value does not transfer.
+ pub fn setMove(self: *BufMap, key: []u8, value: []u8) !void {
+ const get_or_put = try self.hash_map.getOrPut(key);
+ if (get_or_put.found_existing) {
+ self.free(get_or_put.kv.key);
+ get_or_put.kv.key = key;
+ }
+ get_or_put.kv.value = value;
+ }
+
+ /// `key` and `value` are copied into the BufMap.
pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {
- self.delete(key);
- const key_copy = try self.copy(key);
- errdefer self.free(key_copy);
const value_copy = try self.copy(value);
errdefer self.free(value_copy);
- _ = try self.hash_map.put(key_copy, value_copy);
+ // Avoid copying key if it already exists
+ const get_or_put = try self.hash_map.getOrPut(key);
+ if (!get_or_put.found_existing) {
+ get_or_put.kv.key = self.copy(key) catch |err| {
+ _ = self.hash_map.remove(key);
+ return err;
+ };
+ }
+ get_or_put.kv.value = value_copy;
}
- pub fn get(self: *const BufMap, key: []const u8) ?[]const u8 {
+ pub fn get(self: BufMap, key: []const u8) ?[]const u8 {
const entry = self.hash_map.get(key) orelse return null;
return entry.value;
}
@@ -47,7 +65,7 @@ pub const BufMap = struct {
self.free(entry.value);
}
- pub fn count(self: *const BufMap) usize {
+ pub fn count(self: BufMap) usize {
return self.hash_map.count();
}
@@ -55,11 +73,11 @@ pub const BufMap = struct {
return self.hash_map.iterator();
}
- fn free(self: *const BufMap, value: []const u8) void {
+ fn free(self: BufMap, value: []const u8) void {
self.hash_map.allocator.free(value);
}
- fn copy(self: *const BufMap, value: []const u8) ![]const u8 {
+ fn copy(self: BufMap, value: []const u8) ![]u8 {
return mem.dupe(self.hash_map.allocator, u8, value);
}
};
diff --git a/std/build.zig b/std/build.zig
index fe84455cbe..90f5bec656 100644
--- a/std/build.zig
+++ b/std/build.zig
@@ -150,7 +150,11 @@ pub const Builder = struct {
}
pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
- return LibExeObjStep.createExecutable(self, name, root_src);
+ return LibExeObjStep.createExecutable(self, name, root_src, false);
+ }
+
+ pub fn addStaticExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
+ return LibExeObjStep.createExecutable(self, name, root_src, true);
}
pub fn addObject(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {
@@ -795,11 +799,23 @@ pub const Target = union(enum) {
};
}
+ pub fn isFreeBSD(self: *const Target) bool {
+ return switch (self.getOs()) {
+ builtin.Os.freebsd => true,
+ else => false,
+ };
+ }
+
pub fn wantSharedLibSymLinks(self: *const Target) bool {
return !self.isWindows();
}
};
+const Pkg = struct {
+ name: []const u8,
+ path: []const u8,
+};
+
pub const LibExeObjStep = struct {
step: Step,
builder: *Builder,
@@ -842,11 +858,6 @@ pub const LibExeObjStep = struct {
source_files: ArrayList([]const u8),
object_src: []const u8,
- const Pkg = struct {
- name: []const u8,
- path: []const u8,
- };
-
const Kind = enum {
Exe,
Lib,
@@ -884,8 +895,8 @@ pub const LibExeObjStep = struct {
return self;
}
- pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
- const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0))) catch unreachable;
+ pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep {
+ const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0))) catch unreachable;
return self;
}
@@ -1263,6 +1274,9 @@ pub const LibExeObjStep = struct {
zig_args.append("--ver-patch") catch unreachable;
zig_args.append(builder.fmt("{}", self.version.patch)) catch unreachable;
}
+ if (self.kind == Kind.Exe and self.static) {
+ zig_args.append("--static") catch unreachable;
+ }
switch (self.target) {
Target.Native => {},
@@ -1653,6 +1667,7 @@ pub const TestStep = struct {
exec_cmd_args: ?[]const ?[]const u8,
include_dirs: ArrayList([]const u8),
lib_paths: ArrayList([]const u8),
+ packages: ArrayList(Pkg),
object_files: ArrayList([]const u8),
no_rosegment: bool,
output_path: ?[]const u8,
@@ -1673,6 +1688,7 @@ pub const TestStep = struct {
.exec_cmd_args = null,
.include_dirs = ArrayList([]const u8).init(builder.allocator),
.lib_paths = ArrayList([]const u8).init(builder.allocator),
+ .packages = ArrayList(Pkg).init(builder.allocator),
.object_files = ArrayList([]const u8).init(builder.allocator),
.no_rosegment = false,
.output_path = null,
@@ -1688,6 +1704,13 @@ pub const TestStep = struct {
self.lib_paths.append(path) catch unreachable;
}
+ pub fn addPackagePath(self: *TestStep, name: []const u8, pkg_index_path: []const u8) void {
+ self.packages.append(Pkg{
+ .name = name,
+ .path = pkg_index_path,
+ }) catch unreachable;
+ }
+
pub fn setVerbose(self: *TestStep, value: bool) void {
self.verbose = value;
}
@@ -1864,6 +1887,13 @@ pub const TestStep = struct {
try zig_args.append(lib_path);
}
+ for (self.packages.toSliceConst()) |pkg| {
+ zig_args.append("--pkg-begin") catch unreachable;
+ zig_args.append(pkg.name) catch unreachable;
+ zig_args.append(builder.pathFromRoot(pkg.path)) catch unreachable;
+ zig_args.append("--pkg-end") catch unreachable;
+ }
+
if (self.no_rosegment) {
try zig_args.append("--no-rosegment");
}
diff --git a/std/c/freebsd.zig b/std/c/freebsd.zig
new file mode 100644
index 0000000000..421e964827
--- /dev/null
+++ b/std/c/freebsd.zig
@@ -0,0 +1,33 @@
+const timespec = @import("../os/freebsd/index.zig").timespec;
+
+extern "c" fn __error() *c_int;
+pub const _errno = __error;
+
+pub extern "c" fn kqueue() c_int;
+pub extern "c" fn kevent(
+ kq: c_int,
+ changelist: [*]const Kevent,
+ nchanges: c_int,
+ eventlist: [*]Kevent,
+ nevents: c_int,
+ timeout: ?*const timespec,
+) c_int;
+pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
+pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
+pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;
+
+/// Renamed from `kevent` to `Kevent` to avoid conflict with function name.
+pub const Kevent = extern struct {
+ ident: usize,
+ filter: i16,
+ flags: u16,
+ fflags: u32,
+ data: i64,
+ udata: usize,
+ // TODO ext
+};
+
+pub const pthread_attr_t = extern struct {
+ __size: [56]u8,
+ __align: c_long,
+};
diff --git a/std/c/index.zig b/std/c/index.zig
index 6b20d718ef..4aab39d931 100644
--- a/std/c/index.zig
+++ b/std/c/index.zig
@@ -5,6 +5,7 @@ pub use switch (builtin.os) {
Os.linux => @import("linux.zig"),
Os.windows => @import("windows.zig"),
Os.macosx, Os.ios => @import("darwin.zig"),
+ Os.freebsd => @import("freebsd.zig"),
else => empty_import,
};
const empty_import = @import("../empty.zig");
diff --git a/std/coff.zig b/std/coff.zig
index 6a1aa34b46..53bd2a4b7a 100644
--- a/std/coff.zig
+++ b/std/coff.zig
@@ -51,7 +51,7 @@ pub const Coff = struct {
// Seek to PE File Header (coff header)
try self.in_file.seekTo(pe_pointer_offset);
- const pe_magic_offset = try in.readIntLe(u32);
+ const pe_magic_offset = try in.readIntLittle(u32);
try self.in_file.seekTo(pe_magic_offset);
var pe_header_magic: [4]u8 = undefined;
@@ -60,13 +60,13 @@ pub const Coff = struct {
return error.InvalidPEHeader;
self.coff_header = CoffHeader{
- .machine = try in.readIntLe(u16),
- .number_of_sections = try in.readIntLe(u16),
- .timedate_stamp = try in.readIntLe(u32),
- .pointer_to_symbol_table = try in.readIntLe(u32),
- .number_of_symbols = try in.readIntLe(u32),
- .size_of_optional_header = try in.readIntLe(u16),
- .characteristics = try in.readIntLe(u16),
+ .machine = try in.readIntLittle(u16),
+ .number_of_sections = try in.readIntLittle(u16),
+ .timedate_stamp = try in.readIntLittle(u32),
+ .pointer_to_symbol_table = try in.readIntLittle(u32),
+ .number_of_symbols = try in.readIntLittle(u32),
+ .size_of_optional_header = try in.readIntLittle(u16),
+ .characteristics = try in.readIntLittle(u16),
};
switch (self.coff_header.machine) {
@@ -79,7 +79,7 @@ pub const Coff = struct {
fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
const in = &file_stream.stream;
- self.pe_header.magic = try in.readIntLe(u16);
+ self.pe_header.magic = try in.readIntLittle(u16);
// For now we're only interested in finding the reference to the .pdb,
// so we'll skip most of this header, which size is different in 32
// 64 bits by the way.
@@ -93,14 +93,14 @@ pub const Coff = struct {
try self.in_file.seekForward(skip_size);
- const number_of_rva_and_sizes = try in.readIntLe(u32);
+ const number_of_rva_and_sizes = try in.readIntLittle(u32);
if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
return error.InvalidPEHeader;
for (self.pe_header.data_directory) |*data_dir| {
data_dir.* = OptionalHeader.DataDirectory{
- .virtual_address = try in.readIntLe(u32),
- .size = try in.readIntLe(u32),
+ .virtual_address = try in.readIntLittle(u32),
+ .size = try in.readIntLittle(u32),
};
}
}
@@ -124,7 +124,7 @@ pub const Coff = struct {
if (!mem.eql(u8, cv_signature, "RSDS"))
return error.InvalidPEMagic;
try in.readNoEof(self.guid[0..]);
- self.age = try in.readIntLe(u32);
+ self.age = try in.readIntLittle(u32);
// Finally read the null-terminated string.
var byte = try in.readByte();
@@ -157,15 +157,15 @@ pub const Coff = struct {
try self.sections.append(Section{
.header = SectionHeader{
.name = name,
- .misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) },
- .virtual_address = try in.readIntLe(u32),
- .size_of_raw_data = try in.readIntLe(u32),
- .pointer_to_raw_data = try in.readIntLe(u32),
- .pointer_to_relocations = try in.readIntLe(u32),
- .pointer_to_line_numbers = try in.readIntLe(u32),
- .number_of_relocations = try in.readIntLe(u16),
- .number_of_line_numbers = try in.readIntLe(u16),
- .characteristics = try in.readIntLe(u32),
+ .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) },
+ .virtual_address = try in.readIntLittle(u32),
+ .size_of_raw_data = try in.readIntLittle(u32),
+ .pointer_to_raw_data = try in.readIntLittle(u32),
+ .pointer_to_relocations = try in.readIntLittle(u32),
+ .pointer_to_line_numbers = try in.readIntLittle(u32),
+ .number_of_relocations = try in.readIntLittle(u16),
+ .number_of_line_numbers = try in.readIntLittle(u16),
+ .characteristics = try in.readIntLittle(u32),
},
});
}
diff --git a/std/crypto/blake2.zig b/std/crypto/blake2.zig
index dc68d806d2..e3de65916a 100644
--- a/std/crypto/blake2.zig
+++ b/std/crypto/blake2.zig
@@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type {
const rr = d.h[0 .. out_len / 32];
for (rr) |s, j| {
- mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
}
}
@@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type {
var v: [16]u32 = undefined;
for (m) |*r, i| {
- r.* = mem.readIntLE(u32, b[4 * i .. 4 * i + 4]);
+ // TODO https://github.com/ziglang/zig/issues/863
+ r.* = mem.readIntSliceLittle(u32, b[4 * i .. 4 * i + 4]);
}
var k: usize = 0;
@@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type {
const rr = d.h[0 .. out_len / 64];
for (rr) |s, j| {
- mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceLittle(u64, out[8 * j .. 8 * j + 8], s);
}
}
@@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type {
var v: [16]u64 = undefined;
for (m) |*r, i| {
- r.* = mem.readIntLE(u64, b[8 * i .. 8 * i + 8]);
+ r.* = mem.readIntSliceLittle(u64, b[8 * i .. 8 * i + 8]);
}
var k: usize = 0;
diff --git a/std/crypto/chacha20.zig b/std/crypto/chacha20.zig
index 059bc82088..5ec1e79756 100644
--- a/std/crypto/chacha20.zig
+++ b/std/crypto/chacha20.zig
@@ -59,7 +59,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
}
for (x) |_, i| {
- mem.writeInt(out[4 * i .. 4 * i + 4], x[i] +% input[i], builtin.Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]);
}
}
@@ -70,10 +71,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
const c = "expand 32-byte k";
const constant_le = []u32{
- mem.readIntLE(u32, c[0..4]),
- mem.readIntLE(u32, c[4..8]),
- mem.readIntLE(u32, c[8..12]),
- mem.readIntLE(u32, c[12..16]),
+ mem.readIntSliceLittle(u32, c[0..4]),
+ mem.readIntSliceLittle(u32, c[4..8]),
+ mem.readIntSliceLittle(u32, c[8..12]),
+ mem.readIntSliceLittle(u32, c[12..16]),
};
mem.copy(u32, ctx[0..], constant_le[0..4]);
@@ -117,19 +118,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce:
var k: [8]u32 = undefined;
var c: [4]u32 = undefined;
- k[0] = mem.readIntLE(u32, key[0..4]);
- k[1] = mem.readIntLE(u32, key[4..8]);
- k[2] = mem.readIntLE(u32, key[8..12]);
- k[3] = mem.readIntLE(u32, key[12..16]);
- k[4] = mem.readIntLE(u32, key[16..20]);
- k[5] = mem.readIntLE(u32, key[20..24]);
- k[6] = mem.readIntLE(u32, key[24..28]);
- k[7] = mem.readIntLE(u32, key[28..32]);
+ k[0] = mem.readIntSliceLittle(u32, key[0..4]);
+ k[1] = mem.readIntSliceLittle(u32, key[4..8]);
+ k[2] = mem.readIntSliceLittle(u32, key[8..12]);
+ k[3] = mem.readIntSliceLittle(u32, key[12..16]);
+ k[4] = mem.readIntSliceLittle(u32, key[16..20]);
+ k[5] = mem.readIntSliceLittle(u32, key[20..24]);
+ k[6] = mem.readIntSliceLittle(u32, key[24..28]);
+ k[7] = mem.readIntSliceLittle(u32, key[28..32]);
c[0] = counter;
- c[1] = mem.readIntLE(u32, nonce[0..4]);
- c[2] = mem.readIntLE(u32, nonce[4..8]);
- c[3] = mem.readIntLE(u32, nonce[8..12]);
+ c[1] = mem.readIntSliceLittle(u32, nonce[0..4]);
+ c[2] = mem.readIntSliceLittle(u32, nonce[4..8]);
+ c[3] = mem.readIntSliceLittle(u32, nonce[8..12]);
chaCha20_internal(out, in, k, c);
}
@@ -144,19 +145,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
var k: [8]u32 = undefined;
var c: [4]u32 = undefined;
- k[0] = mem.readIntLE(u32, key[0..4]);
- k[1] = mem.readIntLE(u32, key[4..8]);
- k[2] = mem.readIntLE(u32, key[8..12]);
- k[3] = mem.readIntLE(u32, key[12..16]);
- k[4] = mem.readIntLE(u32, key[16..20]);
- k[5] = mem.readIntLE(u32, key[20..24]);
- k[6] = mem.readIntLE(u32, key[24..28]);
- k[7] = mem.readIntLE(u32, key[28..32]);
+ k[0] = mem.readIntSliceLittle(u32, key[0..4]);
+ k[1] = mem.readIntSliceLittle(u32, key[4..8]);
+ k[2] = mem.readIntSliceLittle(u32, key[8..12]);
+ k[3] = mem.readIntSliceLittle(u32, key[12..16]);
+ k[4] = mem.readIntSliceLittle(u32, key[16..20]);
+ k[5] = mem.readIntSliceLittle(u32, key[20..24]);
+ k[6] = mem.readIntSliceLittle(u32, key[24..28]);
+ k[7] = mem.readIntSliceLittle(u32, key[28..32]);
c[0] = @truncate(u32, counter);
c[1] = @truncate(u32, counter >> 32);
- c[2] = mem.readIntLE(u32, nonce[0..4]);
- c[3] = mem.readIntLE(u32, nonce[4..8]);
+ c[2] = mem.readIntSliceLittle(u32, nonce[0..4]);
+ c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);
const block_size = (1 << 6);
const big_block = (block_size << 32);
diff --git a/std/crypto/md5.zig b/std/crypto/md5.zig
index 8663fa751f..994a7fa25c 100644
--- a/std/crypto/md5.zig
+++ b/std/crypto/md5.zig
@@ -112,7 +112,8 @@ pub const Md5 = struct {
d.round(d.buf[0..]);
for (d.s) |s, j| {
- mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
}
}
diff --git a/std/crypto/poly1305.zig b/std/crypto/poly1305.zig
index a5d9fcdf57..0d7a4d672d 100644
--- a/std/crypto/poly1305.zig
+++ b/std/crypto/poly1305.zig
@@ -6,8 +6,8 @@ const std = @import("../index.zig");
const builtin = @import("builtin");
const Endian = builtin.Endian;
-const readInt = std.mem.readInt;
-const writeInt = std.mem.writeInt;
+const readIntSliceLittle = std.mem.readIntSliceLittle;
+const writeIntSliceLittle = std.mem.writeIntSliceLittle;
pub const Poly1305 = struct {
const Self = @This();
@@ -59,19 +59,19 @@ pub const Poly1305 = struct {
{
var i: usize = 0;
while (i < 1) : (i += 1) {
- ctx.r[0] = readInt(key[0..4], u32, Endian.Little) & 0x0fffffff;
+ ctx.r[0] = readIntSliceLittle(u32, key[0..4]) & 0x0fffffff;
}
}
{
var i: usize = 1;
while (i < 4) : (i += 1) {
- ctx.r[i] = readInt(key[i * 4 .. i * 4 + 4], u32, Endian.Little) & 0x0ffffffc;
+ ctx.r[i] = readIntSliceLittle(u32, key[i * 4 .. i * 4 + 4]) & 0x0ffffffc;
}
}
{
var i: usize = 0;
while (i < 4) : (i += 1) {
- ctx.pad[i] = readInt(key[i * 4 + 16 .. i * 4 + 16 + 4], u32, Endian.Little);
+ ctx.pad[i] = readIntSliceLittle(u32, key[i * 4 + 16 .. i * 4 + 16 + 4]);
}
}
@@ -168,10 +168,10 @@ pub const Poly1305 = struct {
const nb_blocks = nmsg.len >> 4;
var i: usize = 0;
while (i < nb_blocks) : (i += 1) {
- ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little);
- ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little);
- ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little);
- ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little);
+ ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]);
+ ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]);
+ ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]);
+ ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]);
polyBlock(ctx);
nmsg = nmsg[16..];
}
@@ -210,10 +210,11 @@ pub const Poly1305 = struct {
const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
- writeInt(out[0..], @truncate(u32, uu0), Endian.Little);
- writeInt(out[4..], @truncate(u32, uu1), Endian.Little);
- writeInt(out[8..], @truncate(u32, uu2), Endian.Little);
- writeInt(out[12..], @truncate(u32, uu3), Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0));
+ writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1));
+ writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2));
+ writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3));
ctx.secureZero();
}
diff --git a/std/crypto/sha1.zig b/std/crypto/sha1.zig
index 1cb0b17434..d5aab8f33f 100644
--- a/std/crypto/sha1.zig
+++ b/std/crypto/sha1.zig
@@ -109,7 +109,8 @@ pub const Sha1 = struct {
d.round(d.buf[0..]);
for (d.s) |s, j| {
- mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
}
}
diff --git a/std/crypto/sha2.zig b/std/crypto/sha2.zig
index 7e9749364b..0476a3a25e 100644
--- a/std/crypto/sha2.zig
+++ b/std/crypto/sha2.zig
@@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type {
const rr = d.s[0 .. params.out_len / 32];
for (rr) |s, j| {
- mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
}
}
@@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type {
const rr = d.s[0 .. params.out_len / 64];
for (rr) |s, j| {
- mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Big);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceBig(u64, out[8 * j .. 8 * j + 8], s);
}
}
diff --git a/std/crypto/sha3.zig b/std/crypto/sha3.zig
index 881370e686..e686e1337c 100644
--- a/std/crypto/sha3.zig
+++ b/std/crypto/sha3.zig
@@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
var c = []const u64{0} ** 5;
for (s) |*r, i| {
- r.* = mem.readIntLE(u64, d[8 * i .. 8 * i + 8]);
+ r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]);
}
comptime var x: usize = 0;
@@ -167,7 +167,8 @@ 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);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceLittle(u64, d[8 * i .. 8 * i + 8], r);
}
}
diff --git a/std/crypto/x25519.zig b/std/crypto/x25519.zig
index 281813b457..daccb56808 100644
--- a/std/crypto/x25519.zig
+++ b/std/crypto/x25519.zig
@@ -7,8 +7,8 @@ const builtin = @import("builtin");
const fmt = std.fmt;
const Endian = builtin.Endian;
-const readInt = std.mem.readInt;
-const writeInt = std.mem.writeInt;
+const readIntSliceLittle = std.mem.readIntSliceLittle;
+const writeIntSliceLittle = std.mem.writeIntSliceLittle;
// Based on Supercop's ref10 implementation.
pub const X25519 = struct {
@@ -255,16 +255,16 @@ const Fe = struct {
var t: [10]i64 = undefined;
- t[0] = readInt(s[0..4], u32, Endian.Little);
- t[1] = readInt(s[4..7], u32, Endian.Little) << 6;
- t[2] = readInt(s[7..10], u32, Endian.Little) << 5;
- t[3] = readInt(s[10..13], u32, Endian.Little) << 3;
- t[4] = readInt(s[13..16], u32, Endian.Little) << 2;
- t[5] = readInt(s[16..20], u32, Endian.Little);
- t[6] = readInt(s[20..23], u32, Endian.Little) << 7;
- t[7] = readInt(s[23..26], u32, Endian.Little) << 5;
- t[8] = readInt(s[26..29], u32, Endian.Little) << 4;
- t[9] = (readInt(s[29..32], u32, Endian.Little) & 0x7fffff) << 2;
+ t[0] = readIntSliceLittle(u32, s[0..4]);
+ t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6;
+ t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5;
+ t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3;
+ t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2;
+ t[5] = readIntSliceLittle(u32, s[16..20]);
+ t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7;
+ t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5;
+ t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4;
+ t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2;
carry1(h, t[0..]);
}
@@ -544,14 +544,15 @@ const Fe = struct {
ut[i] = @bitCast(u32, @intCast(i32, t[i]));
}
- writeInt(s[0..], (ut[0] >> 0) | (ut[1] << 26), Endian.Little);
- writeInt(s[4..], (ut[1] >> 6) | (ut[2] << 19), Endian.Little);
- writeInt(s[8..], (ut[2] >> 13) | (ut[3] << 13), Endian.Little);
- writeInt(s[12..], (ut[3] >> 19) | (ut[4] << 6), Endian.Little);
- writeInt(s[16..], (ut[5] >> 0) | (ut[6] << 25), Endian.Little);
- writeInt(s[20..], (ut[6] >> 7) | (ut[7] << 19), Endian.Little);
- writeInt(s[24..], (ut[7] >> 13) | (ut[8] << 12), Endian.Little);
- writeInt(s[28..], (ut[8] >> 20) | (ut[9] << 6), Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));
+ writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));
+ writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));
+ writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));
+ writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));
+ writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));
+ writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));
+ writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6));
std.mem.secureZero(i64, t[0..]);
}
diff --git a/std/debug/index.zig b/std/debug/index.zig
index b077bdb3b0..73c6ea7b56 100644
--- a/std/debug/index.zig
+++ b/std/debug/index.zig
@@ -198,49 +198,44 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var,
}
}
-pub inline fn getReturnAddress(frame_count: usize) usize {
- var fp = @ptrToInt(@frameAddress());
- var i: usize = 0;
- while (fp != 0 and i < frame_count) {
- fp = @intToPtr(*const usize, fp).*;
- i += 1;
+pub const StackIterator = struct {
+ first_addr: ?usize,
+ fp: usize,
+
+ pub fn init(first_addr: ?usize) StackIterator {
+ return StackIterator{
+ .first_addr = first_addr,
+ .fp = @ptrToInt(@frameAddress()),
+ };
}
- return @intToPtr(*const usize, fp + @sizeOf(usize)).*;
-}
+
+ fn next(self: *StackIterator) ?usize {
+ if (self.fp == 0) return null;
+ self.fp = @intToPtr(*const usize, self.fp).*;
+ if (self.fp == 0) return null;
+
+ if (self.first_addr) |addr| {
+ while (self.fp != 0) : (self.fp = @intToPtr(*const usize, self.fp).*) {
+ const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*;
+ if (addr == return_address) {
+ self.first_addr = null;
+ return return_address;
+ }
+ }
+ }
+
+ const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*;
+ return return_address;
+ }
+};
pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void {
switch (builtin.os) {
builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr),
else => {},
}
- const AddressState = union(enum) {
- NotLookingForStartAddress,
- LookingForStartAddress: usize,
- };
- // TODO: I want to express like this:
- //var addr_state = if (start_addr) |addr| AddressState { .LookingForStartAddress = addr }
- // else AddressState.NotLookingForStartAddress;
- var addr_state: AddressState = undefined;
- if (start_addr) |addr| {
- addr_state = AddressState{ .LookingForStartAddress = addr };
- } else {
- addr_state = AddressState.NotLookingForStartAddress;
- }
-
- var fp = @ptrToInt(@frameAddress());
- while (fp != 0) : (fp = @intToPtr(*const usize, fp).*) {
- const return_address = @intToPtr(*const usize, fp + @sizeOf(usize)).*;
-
- switch (addr_state) {
- AddressState.NotLookingForStartAddress => {},
- AddressState.LookingForStartAddress => |addr| {
- if (return_address == addr) {
- addr_state = AddressState.NotLookingForStartAddress;
- } else {
- continue;
- }
- },
- }
+ var it = StackIterator.init(start_addr);
+ while (it.next()) |return_address| {
try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);
}
}
@@ -282,8 +277,9 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
var coff_section: *coff.Section = undefined;
const mod_index = for (di.sect_contribs) |sect_contrib| {
- if (sect_contrib.Section >= di.coff.sections.len) continue;
- coff_section = &di.coff.sections.toSlice()[sect_contrib.Section];
+ if (sect_contrib.Section > di.coff.sections.len) continue;
+ // Remember that SectionContribEntry.Section is 1-based.
+ coff_section = &di.coff.sections.toSlice()[sect_contrib.Section - 1];
const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset;
const vaddr_end = vaddr_start + sect_contrib.Size;
@@ -413,7 +409,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
if (opt_line_info) |line_info| {
try out_stream.print("\n");
- if (printLineFromFile(out_stream, line_info)) {
+ if (printLineFromFileAnyOs(out_stream, line_info)) {
if (line_info.column == 0) {
try out_stream.write("\n");
} else {
@@ -527,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {
const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;
- const signature = try modi.stream.readIntLe(u32);
+ const signature = try modi.stream.readIntLittle(u32);
if (signature != 4)
return error.InvalidDebugInfo;
@@ -597,7 +593,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
} else "???";
if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
defer line_info.deinit();
- try printLineInfo(di, out_stream, line_info, address, symbol_name, compile_unit_name, tty_color);
+ try printLineInfo(
+ out_stream,
+ line_info,
+ address,
+ symbol_name,
+ compile_unit_name,
+ tty_color,
+ printLineFromFileAnyOs,
+ );
} else |err| switch (err) {
error.MissingDebugInfo, error.InvalidDebugInfo => {
if (tty_color) {
@@ -610,7 +614,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
}
}
-pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
+/// This function works in freestanding mode.
+/// fn printLineFromFile(out_stream: var, line_info: LineInfo) !void
+pub fn printSourceAtAddressDwarf(
+ debug_info: *DwarfInfo,
+ out_stream: var,
+ address: usize,
+ tty_color: bool,
+ comptime printLineFromFile: var,
+) !void {
const compile_unit = findCompileUnit(debug_info, address) catch {
if (tty_color) {
try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", address);
@@ -620,10 +632,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres
return;
};
const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);
- if (getLineNumberInfoLinux(debug_info, compile_unit, address - 1)) |line_info| {
+ if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address - 1)) |line_info| {
defer line_info.deinit();
const symbol_name = "???";
- try printLineInfo(debug_info, out_stream, line_info, address, symbol_name, compile_unit_name, tty_color);
+ try printLineInfo(
+ out_stream,
+ line_info,
+ address,
+ symbol_name,
+ compile_unit_name,
+ tty_color,
+ printLineFromFile,
+ );
} else |err| switch (err) {
error.MissingDebugInfo, error.InvalidDebugInfo => {
if (tty_color) {
@@ -636,14 +656,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres
}
}
+pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
+ return printSourceAtAddressDwarf(debug_info, out_stream, address, tty_color, printLineFromFileAnyOs);
+}
+
fn printLineInfo(
- debug_info: *DebugInfo,
out_stream: var,
line_info: LineInfo,
address: usize,
symbol_name: []const u8,
compile_unit_name: []const u8,
tty_color: bool,
+ comptime printLineFromFile: var,
) !void {
if (tty_color) {
try out_stream.print(
@@ -733,9 +757,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
try di.pdb.openFile(di.coff, path);
var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;
- const version = try pdb_stream.stream.readIntLe(u32);
- const signature = try pdb_stream.stream.readIntLe(u32);
- const age = try pdb_stream.stream.readIntLe(u32);
+ const version = try pdb_stream.stream.readIntLittle(u32);
+ const signature = try pdb_stream.stream.readIntLittle(u32);
+ const age = try pdb_stream.stream.readIntLittle(u32);
var guid: [16]u8 = undefined;
try pdb_stream.stream.readNoEof(guid[0..]);
if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
@@ -743,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
// We validated the executable and pdb match.
const string_table_index = str_tab_index: {
- const name_bytes_len = try pdb_stream.stream.readIntLe(u32);
+ const name_bytes_len = try pdb_stream.stream.readIntLittle(u32);
const name_bytes = try allocator.alloc(u8, name_bytes_len);
try pdb_stream.stream.readNoEof(name_bytes);
@@ -773,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
};
const bucket_list = try allocator.alloc(Bucket, present.len);
for (present) |_| {
- const name_offset = try pdb_stream.stream.readIntLe(u32);
- const name_index = try pdb_stream.stream.readIntLe(u32);
+ const name_offset = try pdb_stream.stream.readIntLittle(u32);
+ const name_index = try pdb_stream.stream.readIntLittle(u32);
const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
if (mem.eql(u8, name, "/names")) {
break :str_tab_index name_index;
@@ -835,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);
var sect_cont_offset: usize = 0;
if (section_contrib_size != 0) {
- const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLe(u32));
+ const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLittle(u32));
if (ver != pdb.SectionContrSubstreamVersion.Ver60)
return error.InvalidDebugInfo;
sect_cont_offset += @sizeOf(u32);
@@ -855,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
}
fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
- const num_words = try stream.readIntLe(u32);
+ const num_words = try stream.readIntLittle(u32);
var word_i: usize = 0;
var list = ArrayList(usize).init(allocator);
while (word_i != num_words) : (word_i += 1) {
- const word = try stream.readIntLe(u32);
+ const word = try stream.readIntLittle(u32);
var bit_i: u5 = 0;
while (true) : (bit_i += 1) {
if (word & (u32(1) << bit_i) != 0) {
@@ -871,55 +895,68 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
return list.toOwnedSlice();
}
-fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {
- var di = DebugInfo{
- .self_exe_file = undefined,
- .elf = undefined,
- .debug_info = undefined,
- .debug_abbrev = undefined,
- .debug_str = undefined,
- .debug_line = undefined,
- .debug_ranges = null,
- .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator),
- .compile_unit_list = ArrayList(CompileUnit).init(allocator),
+fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section {
+ const elf_header = (try elf_file.findSection(name)) orelse return null;
+ return DwarfInfo.Section{
+ .offset = elf_header.offset,
+ .size = elf_header.size,
};
- di.self_exe_file = try os.openSelfExe();
- errdefer di.self_exe_file.close();
-
- try di.elf.openFile(allocator, di.self_exe_file);
- errdefer di.elf.close();
-
- di.debug_info = (try di.elf.findSection(".debug_info")) orelse return error.MissingDebugInfo;
- di.debug_abbrev = (try di.elf.findSection(".debug_abbrev")) orelse return error.MissingDebugInfo;
- di.debug_str = (try di.elf.findSection(".debug_str")) orelse return error.MissingDebugInfo;
- di.debug_line = (try di.elf.findSection(".debug_line")) orelse return error.MissingDebugInfo;
- di.debug_ranges = (try di.elf.findSection(".debug_ranges"));
- try scanAllCompileUnits(&di);
- return di;
}
-pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr {
- var file_stream = elf.in_file.inStream();
- const in = &file_stream.stream;
-
- section_loop: for (elf.section_headers) |*elf_section| {
- if (elf_section.sh_type == SHT_NULL) continue;
-
- const name_offset = elf.string_section.offset + elf_section.name;
- try elf.in_file.seekTo(name_offset);
-
- for (name) |expected_c| {
- const target_c = try in.readByte();
- if (target_c == 0 or expected_c != target_c) continue :section_loop;
- }
+/// Initialize DWARF info. The caller has the responsibility to initialize most
+/// the DwarfInfo fields before calling. These fields can be left undefined:
+/// * abbrev_table_list
+/// * compile_unit_list
+pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void {
+ di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator);
+ di.compile_unit_list = ArrayList(CompileUnit).init(allocator);
+ try scanAllCompileUnits(di);
+}
- {
- const null_byte = try in.readByte();
- if (null_byte == 0) return elf_section;
- }
- }
+pub fn openElfDebugInfo(
+ allocator: *mem.Allocator,
+ elf_seekable_stream: *DwarfSeekableStream,
+ elf_in_stream: *DwarfInStream,
+) !DwarfInfo {
+ var efile: elf.Elf = undefined;
+ try efile.openStream(allocator, elf_seekable_stream, elf_in_stream);
+ errdefer efile.close();
+
+ var di = DwarfInfo{
+ .dwarf_seekable_stream = elf_seekable_stream,
+ .dwarf_in_stream = elf_in_stream,
+ .endian = efile.endian,
+ .debug_info = (try findDwarfSectionFromElf(&efile, ".debug_info")) orelse return error.MissingDebugInfo,
+ .debug_abbrev = (try findDwarfSectionFromElf(&efile, ".debug_abbrev")) orelse return error.MissingDebugInfo,
+ .debug_str = (try findDwarfSectionFromElf(&efile, ".debug_str")) orelse return error.MissingDebugInfo,
+ .debug_line = (try findDwarfSectionFromElf(&efile, ".debug_line")) orelse return error.MissingDebugInfo,
+ .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")),
+ .abbrev_table_list = undefined,
+ .compile_unit_list = undefined,
+ };
+ try openDwarfDebugInfo(&di, allocator);
+ return di;
+}
- return null;
+fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
+ const S = struct {
+ var self_exe_file: os.File = undefined;
+ var self_exe_seekable_stream: os.File.SeekableStream = undefined;
+ var self_exe_in_stream: os.File.InStream = undefined;
+ };
+ S.self_exe_file = try os.openSelfExe();
+ errdefer S.self_exe_file.close();
+
+ S.self_exe_seekable_stream = S.self_exe_file.seekableStream();
+ S.self_exe_in_stream = S.self_exe_file.inStream();
+
+ return openElfDebugInfo(
+ allocator,
+ // TODO https://github.com/ziglang/zig/issues/764
+ @ptrCast(*DwarfSeekableStream, &S.self_exe_seekable_stream.stream),
+ // TODO https://github.com/ziglang/zig/issues/764
+ @ptrCast(*DwarfInStream, &S.self_exe_in_stream.stream),
+ );
}
fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
@@ -999,7 +1036,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
};
}
-fn printLineFromFile(out_stream: var, line_info: LineInfo) !void {
+fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
var f = try os.File.openRead(line_info.file_name);
defer f.close();
// TODO fstat and make sure that the file has the correct size
@@ -1052,6 +1089,35 @@ const MachOFile = struct {
sect_debug_line: ?*const macho.section_64,
};
+pub const DwarfSeekableStream = io.SeekableStream(anyerror, anyerror);
+pub const DwarfInStream = io.InStream(anyerror);
+
+pub const DwarfInfo = struct {
+ dwarf_seekable_stream: *DwarfSeekableStream,
+ dwarf_in_stream: *DwarfInStream,
+ endian: builtin.Endian,
+ debug_info: Section,
+ debug_abbrev: Section,
+ debug_str: Section,
+ debug_line: Section,
+ debug_ranges: ?Section,
+ abbrev_table_list: ArrayList(AbbrevTableHeader),
+ compile_unit_list: ArrayList(CompileUnit),
+
+ pub const Section = struct {
+ offset: usize,
+ size: usize,
+ };
+
+ pub fn allocator(self: DwarfInfo) *mem.Allocator {
+ return self.abbrev_table_list.allocator;
+ }
+
+ pub fn readString(self: *DwarfInfo) ![]u8 {
+ return readStringRaw(self.allocator(), self.dwarf_in_stream);
+ }
+};
+
pub const DebugInfo = switch (builtin.os) {
builtin.Os.macosx => struct {
symbols: []const MachoSymbol,
@@ -1075,32 +1141,8 @@ pub const DebugInfo = switch (builtin.os) {
sect_contribs: []pdb.SectionContribEntry,
modules: []Module,
},
- builtin.Os.linux => struct {
- self_exe_file: os.File,
- elf: elf.Elf,
- debug_info: *elf.SectionHeader,
- debug_abbrev: *elf.SectionHeader,
- debug_str: *elf.SectionHeader,
- debug_line: *elf.SectionHeader,
- debug_ranges: ?*elf.SectionHeader,
- abbrev_table_list: ArrayList(AbbrevTableHeader),
- compile_unit_list: ArrayList(CompileUnit),
-
- pub fn allocator(self: DebugInfo) *mem.Allocator {
- return self.abbrev_table_list.allocator;
- }
-
- pub fn readString(self: *DebugInfo) ![]u8 {
- var in_file_stream = self.self_exe_file.inStream();
- const in_stream = &in_file_stream.stream;
- return readStringRaw(self.allocator(), in_stream);
- }
-
- pub fn close(self: *DebugInfo) void {
- self.self_exe_file.close();
- self.elf.close();
- }
- },
+ builtin.Os.linux => DwarfInfo,
+ builtin.Os.freebsd => struct {},
else => @compileError("Unsupported OS"),
};
@@ -1158,7 +1200,7 @@ const Constant = struct {
fn asUnsignedLe(self: *const Constant) !u64 {
if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
if (self.signed) return error.InvalidDebugInfo;
- return mem.readInt(self.payload, u64, builtin.Endian.Little);
+ return mem.readVarInt(u64, self.payload, builtin.Endian.Little);
}
};
@@ -1204,11 +1246,11 @@ const Die = struct {
};
}
- fn getAttrString(self: *const Die, st: *DebugInfo, id: u64) ![]u8 {
+ fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 {
const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
return switch (form_value.*) {
FormValue.String => |value| value,
- FormValue.StrPtr => |offset| getString(st, offset),
+ FormValue.StrPtr => |offset| getString(di, offset),
else => error.InvalidDebugInfo,
};
}
@@ -1221,14 +1263,15 @@ const FileEntry = struct {
len_bytes: usize,
};
-const LineInfo = struct {
+pub const LineInfo = struct {
line: usize,
column: usize,
- file_name: []u8,
- allocator: *mem.Allocator,
+ file_name: []const u8,
+ allocator: ?*mem.Allocator,
- fn deinit(self: *const LineInfo) void {
- self.allocator.free(self.file_name);
+ fn deinit(self: LineInfo) void {
+ const allocator = self.allocator orelse return;
+ allocator.free(self.file_name);
}
};
@@ -1319,10 +1362,10 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 {
return buf.toSlice();
}
-fn getString(st: *DebugInfo, offset: u64) ![]u8 {
- const pos = st.debug_str.offset + offset;
- try st.self_exe_file.seekTo(pos);
- return st.readString();
+fn getString(di: *DwarfInfo, offset: u64) ![]u8 {
+ const pos = di.debug_str.offset + offset;
+ try di.dwarf_seekable_stream.seekTo(pos);
+ return di.readString();
}
fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 {
@@ -1338,7 +1381,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize
}
fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
- const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size);
+ const block_len = try in_stream.readVarInt(usize, builtin.Endian.Little, size);
return parseFormValueBlockLen(allocator, in_stream, block_len);
}
@@ -1352,11 +1395,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
}
fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
- return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32));
+ return if (is_64) try in_stream.readIntLittle(u64) else u64(try in_stream.readIntLittle(u32));
}
fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
- return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable;
+ return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable;
}
fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
@@ -1365,18 +1408,11 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize)
}
fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {
- const block_len = try in_stream.readIntLe(T);
+ const block_len = try in_stream.readIntLittle(T);
return parseFormValueRefLen(allocator, in_stream, block_len);
}
-const ParseFormValueError = error{
- EndOfStream,
- InvalidDebugInfo,
- EndOfFile,
- OutOfMemory,
-} || std.os.File.ReadError;
-
-fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue {
+fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {
return switch (form_id) {
DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },
DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
@@ -1414,7 +1450,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
},
DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
- DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) },
+ DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) },
DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
@@ -1426,25 +1462,22 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
};
}
-fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable {
- const in_file = st.self_exe_file;
- var in_file_stream = in_file.inStream();
- const in_stream = &in_file_stream.stream;
- var result = AbbrevTable.init(st.allocator());
+fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable {
+ var result = AbbrevTable.init(di.allocator());
while (true) {
- const abbrev_code = try readULeb128(in_stream);
+ const abbrev_code = try readULeb128(di.dwarf_in_stream);
if (abbrev_code == 0) return result;
try result.append(AbbrevTableEntry{
.abbrev_code = abbrev_code,
- .tag_id = try readULeb128(in_stream),
- .has_children = (try in_stream.readByte()) == DW.CHILDREN_yes,
- .attrs = ArrayList(AbbrevAttr).init(st.allocator()),
+ .tag_id = try readULeb128(di.dwarf_in_stream),
+ .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes,
+ .attrs = ArrayList(AbbrevAttr).init(di.allocator()),
});
const attrs = &result.items[result.len - 1].attrs;
while (true) {
- const attr_id = try readULeb128(in_stream);
- const form_id = try readULeb128(in_stream);
+ const attr_id = try readULeb128(di.dwarf_in_stream);
+ const form_id = try readULeb128(di.dwarf_in_stream);
if (attr_id == 0 and form_id == 0) break;
try attrs.append(AbbrevAttr{
.attr_id = attr_id,
@@ -1456,18 +1489,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable {
/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,
/// seeks in the stream and parses it.
-fn getAbbrevTable(st: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable {
- for (st.abbrev_table_list.toSlice()) |*header| {
+fn getAbbrevTable(di: *DwarfInfo, abbrev_offset: u64) !*const AbbrevTable {
+ for (di.abbrev_table_list.toSlice()) |*header| {
if (header.offset == abbrev_offset) {
return &header.table;
}
}
- try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset);
- try st.abbrev_table_list.append(AbbrevTableHeader{
+ try di.dwarf_seekable_stream.seekTo(di.debug_abbrev.offset + abbrev_offset);
+ try di.abbrev_table_list.append(AbbrevTableHeader{
.offset = abbrev_offset,
- .table = try parseAbbrevTable(st),
+ .table = try parseAbbrevTable(di),
});
- return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table;
+ return &di.abbrev_table_list.items[di.abbrev_table_list.len - 1].table;
}
fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry {
@@ -1477,23 +1510,20 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
return null;
}
-fn parseDie(st: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
- const in_file = st.self_exe_file;
- var in_file_stream = in_file.inStream();
- const in_stream = &in_file_stream.stream;
- const abbrev_code = try readULeb128(in_stream);
+fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
+ const abbrev_code = try readULeb128(di.dwarf_in_stream);
const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
var result = Die{
.tag_id = table_entry.tag_id,
.has_children = table_entry.has_children,
- .attrs = ArrayList(Die.Attr).init(st.allocator()),
+ .attrs = ArrayList(Die.Attr).init(di.allocator()),
};
try result.attrs.resize(table_entry.attrs.len);
for (table_entry.attrs.toSliceConst()) |attr, i| {
result.attrs.items[i] = Die.Attr{
.id = attr.attr_id,
- .value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64),
+ .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64),
};
}
return result;
@@ -1697,22 +1727,18 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
return error.MissingDebugInfo;
}
-fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, target_address: usize) !LineInfo {
+fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {
const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);
- const in_file = di.self_exe_file;
const debug_line_end = di.debug_line.offset + di.debug_line.size;
var this_offset = di.debug_line.offset;
var this_index: usize = 0;
- var in_file_stream = in_file.inStream();
- const in_stream = &in_file_stream.stream;
-
while (this_offset < debug_line_end) : (this_index += 1) {
- try in_file.seekTo(this_offset);
+ try di.dwarf_seekable_stream.seekTo(this_offset);
var is_64: bool = undefined;
- const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);
+ const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
if (unit_length == 0) return error.MissingDebugInfo;
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
@@ -1721,35 +1747,35 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
continue;
}
- const version = try in_stream.readInt(di.elf.endian, u16);
+ const version = try di.dwarf_in_stream.readInt(u16, di.endian);
// TODO support 3 and 5
if (version != 2 and version != 4) return error.InvalidDebugInfo;
- const prologue_length = if (is_64) try in_stream.readInt(di.elf.endian, u64) else try in_stream.readInt(di.elf.endian, u32);
- const prog_start_offset = (try in_file.getPos()) + prologue_length;
+ const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
+ const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
- const minimum_instruction_length = try in_stream.readByte();
+ const minimum_instruction_length = try di.dwarf_in_stream.readByte();
if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
if (version >= 4) {
// maximum_operations_per_instruction
- _ = try in_stream.readByte();
+ _ = try di.dwarf_in_stream.readByte();
}
- const default_is_stmt = (try in_stream.readByte()) != 0;
- const line_base = try in_stream.readByteSigned();
+ const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0;
+ const line_base = try di.dwarf_in_stream.readByteSigned();
- const line_range = try in_stream.readByte();
+ const line_range = try di.dwarf_in_stream.readByte();
if (line_range == 0) return error.InvalidDebugInfo;
- const opcode_base = try in_stream.readByte();
+ const opcode_base = try di.dwarf_in_stream.readByte();
const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);
{
var i: usize = 0;
while (i < opcode_base - 1) : (i += 1) {
- standard_opcode_lengths[i] = try in_stream.readByte();
+ standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte();
}
}
@@ -1767,9 +1793,9 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
while (true) {
const file_name = try di.readString();
if (file_name.len == 0) break;
- const dir_index = try readULeb128(in_stream);
- const mtime = try readULeb128(in_stream);
- const len_bytes = try readULeb128(in_stream);
+ const dir_index = try readULeb128(di.dwarf_in_stream);
+ const mtime = try readULeb128(di.dwarf_in_stream);
+ const len_bytes = try readULeb128(di.dwarf_in_stream);
try file_entries.append(FileEntry{
.file_name = file_name,
.dir_index = dir_index,
@@ -1778,15 +1804,15 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
});
}
- try in_file.seekTo(prog_start_offset);
+ try di.dwarf_seekable_stream.seekTo(prog_start_offset);
while (true) {
- const opcode = try in_stream.readByte();
+ const opcode = try di.dwarf_in_stream.readByte();
if (opcode == DW.LNS_extended_op) {
- const op_size = try readULeb128(in_stream);
+ const op_size = try readULeb128(di.dwarf_in_stream);
if (op_size < 1) return error.InvalidDebugInfo;
- var sub_op = try in_stream.readByte();
+ var sub_op = try di.dwarf_in_stream.readByte();
switch (sub_op) {
DW.LNE_end_sequence => {
prog.end_sequence = true;
@@ -1794,14 +1820,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
return error.MissingDebugInfo;
},
DW.LNE_set_address => {
- const addr = try in_stream.readInt(di.elf.endian, usize);
+ const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
prog.address = addr;
},
DW.LNE_define_file => {
const file_name = try di.readString();
- const dir_index = try readULeb128(in_stream);
- const mtime = try readULeb128(in_stream);
- const len_bytes = try readULeb128(in_stream);
+ const dir_index = try readULeb128(di.dwarf_in_stream);
+ const mtime = try readULeb128(di.dwarf_in_stream);
+ const len_bytes = try readULeb128(di.dwarf_in_stream);
try file_entries.append(FileEntry{
.file_name = file_name,
.dir_index = dir_index,
@@ -1811,7 +1837,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
},
else => {
const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;
- try in_file.seekForward(fwd_amt);
+ try di.dwarf_seekable_stream.seekForward(fwd_amt);
},
}
} else if (opcode >= opcode_base) {
@@ -1830,19 +1856,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
prog.basic_block = false;
},
DW.LNS_advance_pc => {
- const arg = try readULeb128(in_stream);
+ const arg = try readULeb128(di.dwarf_in_stream);
prog.address += arg * minimum_instruction_length;
},
DW.LNS_advance_line => {
- const arg = try readILeb128(in_stream);
+ const arg = try readILeb128(di.dwarf_in_stream);
prog.line += arg;
},
DW.LNS_set_file => {
- const arg = try readULeb128(in_stream);
+ const arg = try readULeb128(di.dwarf_in_stream);
prog.file = arg;
},
DW.LNS_set_column => {
- const arg = try readULeb128(in_stream);
+ const arg = try readULeb128(di.dwarf_in_stream);
prog.column = arg;
},
DW.LNS_negate_stmt => {
@@ -1856,14 +1882,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
prog.address += inc_addr;
},
DW.LNS_fixed_advance_pc => {
- const arg = try in_stream.readInt(di.elf.endian, u16);
+ const arg = try di.dwarf_in_stream.readInt(u16, di.endian);
prog.address += arg;
},
DW.LNS_set_prologue_end => {},
else => {
if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
const len_bytes = standard_opcode_lengths[opcode - 1];
- try in_file.seekForward(len_bytes);
+ try di.dwarf_seekable_stream.seekForward(len_bytes);
},
}
}
@@ -1875,36 +1901,33 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
return error.MissingDebugInfo;
}
-fn scanAllCompileUnits(st: *DebugInfo) !void {
- const debug_info_end = st.debug_info.offset + st.debug_info.size;
- var this_unit_offset = st.debug_info.offset;
+fn scanAllCompileUnits(di: *DwarfInfo) !void {
+ const debug_info_end = di.debug_info.offset + di.debug_info.size;
+ var this_unit_offset = di.debug_info.offset;
var cu_index: usize = 0;
- var in_file_stream = st.self_exe_file.inStream();
- const in_stream = &in_file_stream.stream;
-
while (this_unit_offset < debug_info_end) {
- try st.self_exe_file.seekTo(this_unit_offset);
+ try di.dwarf_seekable_stream.seekTo(this_unit_offset);
var is_64: bool = undefined;
- const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);
+ const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
if (unit_length == 0) return;
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
- const version = try in_stream.readInt(st.elf.endian, u16);
+ const version = try di.dwarf_in_stream.readInt(u16, di.endian);
if (version < 2 or version > 5) return error.InvalidDebugInfo;
- const debug_abbrev_offset = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32);
+ const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
- const address_size = try in_stream.readByte();
+ const address_size = try di.dwarf_in_stream.readByte();
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
- const compile_unit_pos = try st.self_exe_file.getPos();
- const abbrev_table = try getAbbrevTable(st, debug_abbrev_offset);
+ const compile_unit_pos = try di.dwarf_seekable_stream.getPos();
+ const abbrev_table = try getAbbrevTable(di, debug_abbrev_offset);
- try st.self_exe_file.seekTo(compile_unit_pos);
+ try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
- const compile_unit_die = try st.allocator().create(try parseDie(st, abbrev_table, is_64));
+ const compile_unit_die = try di.allocator().create(try parseDie(di, abbrev_table, is_64));
if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
@@ -1932,7 +1955,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
}
};
- try st.compile_unit_list.append(CompileUnit{
+ try di.compile_unit_list.append(CompileUnit{
.version = version,
.is_64 = is_64,
.pc_range = pc_range,
@@ -1945,20 +1968,18 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
}
}
-fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit {
- var in_file_stream = st.self_exe_file.inStream();
- const in_stream = &in_file_stream.stream;
- for (st.compile_unit_list.toSlice()) |*compile_unit| {
+fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
+ for (di.compile_unit_list.toSlice()) |*compile_unit| {
if (compile_unit.pc_range) |range| {
if (target_address >= range.start and target_address < range.end) return compile_unit;
}
if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
var base_address: usize = 0;
- if (st.debug_ranges) |debug_ranges| {
- try st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset);
+ if (di.debug_ranges) |debug_ranges| {
+ try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
while (true) {
- const begin_addr = try in_stream.readIntLe(usize);
- const end_addr = try in_stream.readIntLe(usize);
+ const begin_addr = try di.dwarf_in_stream.readIntLittle(usize);
+ const end_addr = try di.dwarf_in_stream.readIntLittle(usize);
if (begin_addr == 0 and end_addr == 0) {
break;
}
@@ -1980,7 +2001,8 @@ fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit {
}
fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {
- const result = mem.readInt(ptr.*[0..@sizeOf(T)], T, endian);
+ // TODO https://github.com/ziglang/zig/issues/863
+ const result = mem.readIntSlice(T, ptr.*[0..@sizeOf(T)], endian);
ptr.* += @sizeOf(T);
return result;
}
@@ -1996,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 {
}
fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
- const first_32_bits = mem.readIntLE(u32, ptr.*[0..4]);
+ // TODO this code can be improved with https://github.com/ziglang/zig/issues/863
+ const first_32_bits = mem.readIntSliceLittle(u32, ptr.*[0..4]);
is_64.* = (first_32_bits == 0xffffffff);
if (is_64.*) {
ptr.* += 4;
- const result = mem.readIntLE(u64, ptr.*[0..8]);
+ const result = mem.readIntSliceLittle(u64, ptr.*[0..8]);
ptr.* += 8;
return result;
} else {
@@ -2063,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 {
}
fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
- const first_32_bits = try in_stream.readIntLe(u32);
+ const first_32_bits = try in_stream.readIntLittle(u32);
is_64.* = (first_32_bits == 0xffffffff);
if (is_64.*) {
- return in_stream.readIntLe(u64);
+ return in_stream.readIntLittle(u64);
} else {
if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
return u64(first_32_bits);
diff --git a/std/dynamic_library.zig b/std/dynamic_library.zig
index 49f217bc8e..4d19951318 100644
--- a/std/dynamic_library.zig
+++ b/std/dynamic_library.zig
@@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) {
};
pub const LinuxDynLib = struct {
- allocator: *mem.Allocator,
elf_lib: ElfLib,
fd: i32,
map_addr: usize,
@@ -27,7 +26,7 @@ pub const LinuxDynLib = struct {
/// Trusts the file
pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
- const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
+ const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
errdefer std.os.close(fd);
const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
@@ -45,7 +44,6 @@ pub const LinuxDynLib = struct {
const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];
return DynLib{
- .allocator = allocator,
.elf_lib = try ElfLib.init(bytes),
.fd = fd,
.map_addr = addr,
diff --git a/std/elf.zig b/std/elf.zig
index e95222744d..6a564c3283 100644
--- a/std/elf.zig
+++ b/std/elf.zig
@@ -353,7 +353,8 @@ pub const SectionHeader = struct {
};
pub const Elf = struct {
- in_file: os.File,
+ seekable_stream: *io.SeekableStream(anyerror, anyerror),
+ in_stream: *io.InStream(anyerror),
auto_close_stream: bool,
is_64: bool,
endian: builtin.Endian,
@@ -370,19 +371,24 @@ pub const Elf = struct {
/// Call close when done.
pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void {
- try elf.prealloc_file.open(path);
- try elf.openFile(allocator, *elf.prealloc_file);
- elf.auto_close_stream = true;
+ @compileError("TODO implement");
}
/// Call close when done.
pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void {
- elf.allocator = allocator;
- elf.in_file = file;
- elf.auto_close_stream = false;
+ @compileError("TODO implement");
+ }
- var file_stream = elf.in_file.inStream();
- const in = &file_stream.stream;
+ pub fn openStream(
+ elf: *Elf,
+ allocator: *mem.Allocator,
+ seekable_stream: *io.SeekableStream(anyerror, anyerror),
+ in: *io.InStream(anyerror),
+ ) !void {
+ elf.auto_close_stream = false;
+ elf.allocator = allocator;
+ elf.seekable_stream = seekable_stream;
+ elf.in_stream = in;
var magic: [4]u8 = undefined;
try in.readNoEof(magic[0..]);
@@ -404,9 +410,9 @@ pub const Elf = struct {
if (version_byte != 1) return error.InvalidFormat;
// skip over padding
- try elf.in_file.seekForward(9);
+ try seekable_stream.seekForward(9);
- elf.file_type = switch (try in.readInt(elf.endian, u16)) {
+ elf.file_type = switch (try in.readInt(u16, elf.endian)) {
1 => FileType.Relocatable,
2 => FileType.Executable,
3 => FileType.Shared,
@@ -414,7 +420,7 @@ pub const Elf = struct {
else => return error.InvalidFormat,
};
- elf.arch = switch (try in.readInt(elf.endian, u16)) {
+ elf.arch = switch (try in.readInt(u16, elf.endian)) {
0x02 => Arch.Sparc,
0x03 => Arch.x86,
0x08 => Arch.Mips,
@@ -427,32 +433,32 @@ pub const Elf = struct {
else => return error.InvalidFormat,
};
- const elf_version = try in.readInt(elf.endian, u32);
+ const elf_version = try in.readInt(u32, elf.endian);
if (elf_version != 1) return error.InvalidFormat;
if (elf.is_64) {
- elf.entry_addr = try in.readInt(elf.endian, u64);
- elf.program_header_offset = try in.readInt(elf.endian, u64);
- elf.section_header_offset = try in.readInt(elf.endian, u64);
+ elf.entry_addr = try in.readInt(u64, elf.endian);
+ elf.program_header_offset = try in.readInt(u64, elf.endian);
+ elf.section_header_offset = try in.readInt(u64, elf.endian);
} else {
- elf.entry_addr = u64(try in.readInt(elf.endian, u32));
- elf.program_header_offset = u64(try in.readInt(elf.endian, u32));
- elf.section_header_offset = u64(try in.readInt(elf.endian, u32));
+ elf.entry_addr = u64(try in.readInt(u32, elf.endian));
+ elf.program_header_offset = u64(try in.readInt(u32, elf.endian));
+ elf.section_header_offset = u64(try in.readInt(u32, elf.endian));
}
// skip over flags
- try elf.in_file.seekForward(4);
+ try seekable_stream.seekForward(4);
- const header_size = try in.readInt(elf.endian, u16);
+ const header_size = try in.readInt(u16, elf.endian);
if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
return error.InvalidFormat;
}
- const ph_entry_size = try in.readInt(elf.endian, u16);
- const ph_entry_count = try in.readInt(elf.endian, u16);
- const sh_entry_size = try in.readInt(elf.endian, u16);
- const sh_entry_count = try in.readInt(elf.endian, u16);
- elf.string_section_index = u64(try in.readInt(elf.endian, u16));
+ const ph_entry_size = try in.readInt(u16, elf.endian);
+ const ph_entry_count = try in.readInt(u16, elf.endian);
+ const sh_entry_size = try in.readInt(u16, elf.endian);
+ const sh_entry_count = try in.readInt(u16, elf.endian);
+ elf.string_section_index = u64(try in.readInt(u16, elf.endian));
if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
@@ -461,12 +467,12 @@ pub const Elf = struct {
const ph_byte_count = u64(ph_entry_size) * u64(ph_entry_count);
const end_ph = try math.add(u64, elf.program_header_offset, ph_byte_count);
- const stream_end = try elf.in_file.getEndPos();
+ const stream_end = try seekable_stream.getEndPos();
if (stream_end < end_sh or stream_end < end_ph) {
return error.InvalidFormat;
}
- try elf.in_file.seekTo(elf.section_header_offset);
+ try seekable_stream.seekTo(elf.section_header_offset);
elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count);
errdefer elf.allocator.free(elf.section_headers);
@@ -475,32 +481,32 @@ pub const Elf = struct {
if (sh_entry_size != 64) return error.InvalidFormat;
for (elf.section_headers) |*elf_section| {
- elf_section.name = try in.readInt(elf.endian, u32);
- elf_section.sh_type = try in.readInt(elf.endian, u32);
- elf_section.flags = try in.readInt(elf.endian, u64);
- elf_section.addr = try in.readInt(elf.endian, u64);
- elf_section.offset = try in.readInt(elf.endian, u64);
- elf_section.size = try in.readInt(elf.endian, u64);
- elf_section.link = try in.readInt(elf.endian, u32);
- elf_section.info = try in.readInt(elf.endian, u32);
- elf_section.addr_align = try in.readInt(elf.endian, u64);
- elf_section.ent_size = try in.readInt(elf.endian, u64);
+ elf_section.name = try in.readInt(u32, elf.endian);
+ elf_section.sh_type = try in.readInt(u32, elf.endian);
+ elf_section.flags = try in.readInt(u64, elf.endian);
+ elf_section.addr = try in.readInt(u64, elf.endian);
+ elf_section.offset = try in.readInt(u64, elf.endian);
+ elf_section.size = try in.readInt(u64, elf.endian);
+ elf_section.link = try in.readInt(u32, elf.endian);
+ elf_section.info = try in.readInt(u32, elf.endian);
+ elf_section.addr_align = try in.readInt(u64, elf.endian);
+ elf_section.ent_size = try in.readInt(u64, elf.endian);
}
} else {
if (sh_entry_size != 40) return error.InvalidFormat;
for (elf.section_headers) |*elf_section| {
// TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?
- elf_section.name = try in.readInt(elf.endian, u32);
- elf_section.sh_type = try in.readInt(elf.endian, u32);
- elf_section.flags = u64(try in.readInt(elf.endian, u32));
- elf_section.addr = u64(try in.readInt(elf.endian, u32));
- elf_section.offset = u64(try in.readInt(elf.endian, u32));
- elf_section.size = u64(try in.readInt(elf.endian, u32));
- elf_section.link = try in.readInt(elf.endian, u32);
- elf_section.info = try in.readInt(elf.endian, u32);
- elf_section.addr_align = u64(try in.readInt(elf.endian, u32));
- elf_section.ent_size = u64(try in.readInt(elf.endian, u32));
+ elf_section.name = try in.readInt(u32, elf.endian);
+ elf_section.sh_type = try in.readInt(u32, elf.endian);
+ elf_section.flags = u64(try in.readInt(u32, elf.endian));
+ elf_section.addr = u64(try in.readInt(u32, elf.endian));
+ elf_section.offset = u64(try in.readInt(u32, elf.endian));
+ elf_section.size = u64(try in.readInt(u32, elf.endian));
+ elf_section.link = try in.readInt(u32, elf.endian);
+ elf_section.info = try in.readInt(u32, elf.endian);
+ elf_section.addr_align = u64(try in.readInt(u32, elf.endian));
+ elf_section.ent_size = u64(try in.readInt(u32, elf.endian));
}
}
@@ -521,26 +527,23 @@ pub const Elf = struct {
pub fn close(elf: *Elf) void {
elf.allocator.free(elf.section_headers);
- if (elf.auto_close_stream) elf.in_file.close();
+ if (elf.auto_close_stream) elf.prealloc_file.close();
}
pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader {
- var file_stream = elf.in_file.inStream();
- const in = &file_stream.stream;
-
section_loop: for (elf.section_headers) |*elf_section| {
if (elf_section.sh_type == SHT_NULL) continue;
const name_offset = elf.string_section.offset + elf_section.name;
- try elf.in_file.seekTo(name_offset);
+ try elf.seekable_stream.seekTo(name_offset);
for (name) |expected_c| {
- const target_c = try in.readByte();
+ const target_c = try elf.in_stream.readByte();
if (target_c == 0 or expected_c != target_c) continue :section_loop;
}
{
- const null_byte = try in.readByte();
+ const null_byte = try elf.in_stream.readByte();
if (null_byte == 0) return elf_section;
}
}
@@ -549,7 +552,7 @@ pub const Elf = struct {
}
pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void {
- try elf.in_file.seekTo(elf_section.offset);
+ try elf.seekable_stream.seekTo(elf_section.offset);
}
};
diff --git a/std/event/fs.zig b/std/event/fs.zig
index 2ce3014178..1b8e1aa5dc 100644
--- a/std/event/fs.zig
+++ b/std/event/fs.zig
@@ -83,6 +83,7 @@ pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, o
switch (builtin.os) {
builtin.Os.macosx,
builtin.Os.linux,
+ builtin.Os.freebsd,
=> {
const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
defer loop.allocator.free(iovecs);
@@ -219,6 +220,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset:
switch (builtin.os) {
builtin.Os.macosx,
builtin.Os.linux,
+ builtin.Os.freebsd,
=> {
const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
defer loop.allocator.free(iovecs);
@@ -399,7 +401,7 @@ pub async fn openPosix(
pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle {
switch (builtin.os) {
- builtin.Os.macosx, builtin.Os.linux => {
+ builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => {
const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;
return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
},
@@ -427,6 +429,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
switch (builtin.os) {
builtin.Os.macosx,
builtin.Os.linux,
+ builtin.Os.freebsd,
=> {
const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;
return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
@@ -449,7 +452,7 @@ pub async fn openReadWrite(
mode: os.File.Mode,
) os.File.OpenError!os.FileHandle {
switch (builtin.os) {
- builtin.Os.macosx, builtin.Os.linux => {
+ builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => {
const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
return await (async openPosix(loop, path, flags, mode) catch unreachable);
},
@@ -477,7 +480,7 @@ pub const CloseOperation = struct {
os_data: OsData,
const OsData = switch (builtin.os) {
- builtin.Os.linux, builtin.Os.macosx => OsDataPosix,
+ builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => OsDataPosix,
builtin.Os.windows => struct {
handle: ?os.FileHandle,
@@ -496,7 +499,7 @@ pub const CloseOperation = struct {
self.* = CloseOperation{
.loop = loop,
.os_data = switch (builtin.os) {
- builtin.Os.linux, builtin.Os.macosx => initOsDataPosix(self),
+ builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => initOsDataPosix(self),
builtin.Os.windows => OsData{ .handle = null },
else => @compileError("Unsupported OS"),
},
@@ -525,6 +528,7 @@ pub const CloseOperation = struct {
switch (builtin.os) {
builtin.Os.linux,
builtin.Os.macosx,
+ builtin.Os.freebsd,
=> {
if (self.os_data.have_fd) {
self.loop.posixFsRequest(&self.os_data.close_req_node);
@@ -546,6 +550,7 @@ pub const CloseOperation = struct {
switch (builtin.os) {
builtin.Os.linux,
builtin.Os.macosx,
+ builtin.Os.freebsd,
=> {
self.os_data.close_req_node.data.msg.Close.fd = handle;
self.os_data.have_fd = true;
@@ -562,6 +567,7 @@ pub const CloseOperation = struct {
switch (builtin.os) {
builtin.Os.linux,
builtin.Os.macosx,
+ builtin.Os.freebsd,
=> {
self.os_data.have_fd = false;
},
@@ -576,6 +582,7 @@ pub const CloseOperation = struct {
switch (builtin.os) {
builtin.Os.linux,
builtin.Os.macosx,
+ builtin.Os.freebsd,
=> {
assert(self.os_data.have_fd);
return self.os_data.close_req_node.data.msg.Close.fd;
@@ -599,6 +606,7 @@ pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8,
switch (builtin.os) {
builtin.Os.linux,
builtin.Os.macosx,
+ builtin.Os.freebsd,
=> return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable),
builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable),
else => @compileError("Unsupported OS"),
@@ -704,7 +712,7 @@ pub fn Watch(comptime V: type) type {
os_data: OsData,
const OsData = switch (builtin.os) {
- builtin.Os.macosx => struct {
+ builtin.Os.macosx, builtin.Os.freebsd => struct {
file_table: FileTable,
table_lock: event.Lock,
@@ -793,7 +801,7 @@ pub fn Watch(comptime V: type) type {
return self;
},
- builtin.Os.macosx => {
+ builtin.Os.macosx, builtin.Os.freebsd => {
const self = try loop.allocator.createOne(Self);
errdefer loop.allocator.destroy(self);
@@ -813,7 +821,7 @@ pub fn Watch(comptime V: type) type {
/// All addFile calls and removeFile calls must have completed.
pub fn destroy(self: *Self) void {
switch (builtin.os) {
- builtin.Os.macosx => {
+ builtin.Os.macosx, builtin.Os.freebsd => {
// TODO we need to cancel the coroutines before destroying the lock
self.os_data.table_lock.deinit();
var it = self.os_data.file_table.iterator();
@@ -855,14 +863,14 @@ pub fn Watch(comptime V: type) type {
pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V {
switch (builtin.os) {
- builtin.Os.macosx => return await (async addFileMacosx(self, file_path, value) catch unreachable),
+ builtin.Os.macosx, builtin.Os.freebsd => return await (async addFileKEvent(self, file_path, value) catch unreachable),
builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable),
builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable),
else => @compileError("Unsupported OS"),
}
}
- async fn addFileMacosx(self: *Self, file_path: []const u8, value: V) !?V {
+ async fn addFileKEvent(self: *Self, file_path: []const u8, value: V) !?V {
const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path);
var resolved_path_consumed = false;
defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path);
@@ -871,7 +879,10 @@ pub fn Watch(comptime V: type) type {
var close_op_consumed = false;
defer if (!close_op_consumed) close_op.finish();
- const flags = posix.O_SYMLINK | posix.O_EVTONLY;
+ const flags = switch (builtin.os) {
+ builtin.Os.macosx => posix.O_SYMLINK | posix.O_EVTONLY,
+ else => 0,
+ };
const mode = 0;
const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable);
close_op.setHandle(fd);
diff --git a/std/event/io.zig b/std/event/io.zig
index bb377a3b68..b11550f7aa 100644
--- a/std/event/io.zig
+++ b/std/event/io.zig
@@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type {
if (amt_read < buf.len) return error.EndOfStream;
}
- pub async fn readIntLe(self: *Self, comptime T: type) !T {
- return await (async self.readInt(builtin.Endian.Little, T) catch unreachable);
+ pub async fn readIntLittle(self: *Self, comptime T: type) !T {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ try await (async self.readNoEof(bytes[0..]) catch unreachable);
+ return mem.readIntLittle(T, &bytes);
}
pub async fn readIntBe(self: *Self, comptime T: type) !T {
- return await (async self.readInt(builtin.Endian.Big, T) catch unreachable);
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ try await (async self.readNoEof(bytes[0..]) catch unreachable);
+ return mem.readIntBig(T, &bytes);
}
- pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
+ pub async fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try await (async self.readNoEof(bytes[0..]) catch unreachable);
- return mem.readInt(bytes, T, endian);
+ return mem.readInt(T, &bytes, endian);
}
pub async fn readStruct(self: *Self, comptime T: type) !T {
diff --git a/std/event/loop.zig b/std/event/loop.zig
index fb47a9f253..43965e8293 100644
--- a/std/event/loop.zig
+++ b/std/event/loop.zig
@@ -49,7 +49,7 @@ pub const Loop = struct {
};
pub const EventFd = switch (builtin.os) {
- builtin.Os.macosx => MacOsEventFd,
+ builtin.Os.macosx, builtin.Os.freebsd => KEventFd,
builtin.Os.linux => struct {
base: ResumeNode,
epoll_op: u32,
@@ -62,13 +62,13 @@ pub const Loop = struct {
else => @compileError("unsupported OS"),
};
- const MacOsEventFd = struct {
+ const KEventFd = struct {
base: ResumeNode,
kevent: posix.Kevent,
};
pub const Basic = switch (builtin.os) {
- builtin.Os.macosx => MacOsBasic,
+ builtin.Os.macosx, builtin.Os.freebsd => KEventBasic,
builtin.Os.linux => struct {
base: ResumeNode,
},
@@ -78,7 +78,7 @@ pub const Loop = struct {
else => @compileError("unsupported OS"),
};
- const MacOsBasic = struct {
+ const KEventBasic = struct {
base: ResumeNode,
kev: posix.Kevent,
};
@@ -214,7 +214,7 @@ pub const Loop = struct {
self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);
}
},
- builtin.Os.macosx => {
+ builtin.Os.macosx, builtin.Os.freebsd => {
self.os_data.kqfd = try os.bsdKQueue();
errdefer os.close(self.os_data.kqfd);
@@ -369,7 +369,7 @@ pub const Loop = struct {
os.close(self.os_data.epollfd);
self.allocator.free(self.eventfd_resume_nodes);
},
- builtin.Os.macosx => {
+ builtin.Os.macosx, builtin.Os.freebsd => {
os.close(self.os_data.kqfd);
os.close(self.os_data.fs_kqfd);
},
@@ -484,7 +484,7 @@ pub const Loop = struct {
const eventfd_node = &resume_stack_node.data;
eventfd_node.base.handle = next_tick_node.data;
switch (builtin.os) {
- builtin.Os.macosx => {
+ builtin.Os.macosx, builtin.Os.freebsd => {
const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent);
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
_ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {
@@ -546,6 +546,7 @@ pub const Loop = struct {
switch (builtin.os) {
builtin.Os.linux,
builtin.Os.macosx,
+ builtin.Os.freebsd,
=> self.os_data.fs_thread.wait(),
else => {},
}
@@ -610,7 +611,7 @@ pub const Loop = struct {
os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
return;
},
- builtin.Os.macosx => {
+ builtin.Os.macosx, builtin.Os.freebsd => {
self.posixFsRequest(&self.os_data.fs_end_request);
const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent);
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
@@ -668,7 +669,7 @@ pub const Loop = struct {
}
}
},
- builtin.Os.macosx => {
+ builtin.Os.macosx, builtin.Os.freebsd => {
var eventlist: [1]posix.Kevent = undefined;
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;
@@ -731,7 +732,7 @@ pub const Loop = struct {
self.beginOneEvent(); // finished in posixFsRun after processing the msg
self.os_data.fs_queue.put(request_node);
switch (builtin.os) {
- builtin.Os.macosx => {
+ builtin.Os.macosx, builtin.Os.freebsd => {
const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake);
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
_ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
@@ -801,7 +802,7 @@ pub const Loop = struct {
else => unreachable,
}
},
- builtin.Os.macosx => {
+ builtin.Os.macosx, builtin.Os.freebsd => {
const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait);
var out_kevs: [1]posix.Kevent = undefined;
_ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;
@@ -813,7 +814,7 @@ pub const Loop = struct {
const OsData = switch (builtin.os) {
builtin.Os.linux => LinuxOsData,
- builtin.Os.macosx => MacOsData,
+ builtin.Os.macosx, builtin.Os.freebsd => KEventData,
builtin.Os.windows => struct {
io_port: windows.HANDLE,
extra_thread_count: usize,
@@ -821,7 +822,7 @@ pub const Loop = struct {
else => struct {},
};
- const MacOsData = struct {
+ const KEventData = struct {
kqfd: i32,
final_kevent: posix.Kevent,
fs_kevent_wake: posix.Kevent,
diff --git a/std/fmt/index.zig b/std/fmt/index.zig
index b4b2fdb010..b010072273 100644
--- a/std/fmt/index.zig
+++ b/std/fmt/index.zig
@@ -2,6 +2,7 @@ const std = @import("../index.zig");
const math = std.math;
const debug = std.debug;
const assert = debug.assert;
+const assertError = debug.assertError;
const mem = std.mem;
const builtin = @import("builtin");
const errol = @import("errol/index.zig");
@@ -116,7 +117,7 @@ pub fn formatType(
return output(context, @errorName(value));
}
switch (@typeInfo(T)) {
- builtin.TypeId.Int, builtin.TypeId.Float => {
+ builtin.TypeId.ComptimeInt, builtin.TypeId.Int, builtin.TypeId.Float => {
return formatValue(value, fmt, context, Errors, output);
},
builtin.TypeId.Void => {
@@ -242,6 +243,9 @@ pub fn formatType(
}
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
},
+ builtin.TypeId.Fn => {
+ return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value));
+ },
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
}
}
@@ -267,11 +271,15 @@ fn formatValue(
}
}
- comptime var T = @typeOf(value);
+ const T = @typeOf(value);
switch (@typeId(T)) {
builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),
- else => unreachable,
+ builtin.TypeId.ComptimeInt => {
+ const Int = math.IntFittingRange(value, value);
+ return formatIntValue(Int(value), fmt, context, Errors, output);
+ },
+ else => comptime unreachable,
}
}
@@ -288,9 +296,10 @@ pub fn formatIntValue(
if (fmt.len > 0) {
switch (fmt[0]) {
'c' => {
- if (@typeOf(value) == u8) {
- if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]});
- return formatAsciiChar(value, context, Errors, output);
+ if (@typeOf(value).bit_count <= 8) {
+ if (fmt.len > 1)
+ @compileError("Unknown format character: " ++ []u8{fmt[1]});
+ return formatAsciiChar(u8(value), context, Errors, output);
}
},
'b' => {
@@ -811,13 +820,41 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
for (buf) |c| {
const digit = try charToDigit(c, radix);
- x = try math.mul(T, x, radix);
- x = try math.add(T, x, digit);
+
+ if (x != 0) x = try math.mul(T, x, try math.cast(T, radix));
+ x = try math.add(T, x, try math.cast(T, digit));
}
return x;
}
+test "parseUnsigned" {
+ assert((try parseUnsigned(u16, "050124", 10)) == 50124);
+ assert((try parseUnsigned(u16, "65535", 10)) == 65535);
+ assertError(parseUnsigned(u16, "65536", 10), error.Overflow);
+
+ assert((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
+ assertError(parseUnsigned(u64, "10000000000000000", 16), error.Overflow);
+
+ assert((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
+
+ assert((try parseUnsigned(u7, "1", 10)) == 1);
+ assert((try parseUnsigned(u7, "1000", 2)) == 8);
+
+ assertError(parseUnsigned(u32, "f", 10), error.InvalidCharacter);
+ assertError(parseUnsigned(u8, "109", 8), error.InvalidCharacter);
+
+ assert((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
+
+ // these numbers should fit even though the radix itself doesn't fit in the destination type
+ assert((try parseUnsigned(u1, "0", 10)) == 0);
+ assert((try parseUnsigned(u1, "1", 10)) == 1);
+ assertError(parseUnsigned(u1, "2", 10), error.Overflow);
+ assert((try parseUnsigned(u1, "001", 16)) == 1);
+ assert((try parseUnsigned(u2, "3", 16)) == 3);
+ assertError(parseUnsigned(u2, "4", 16), error.Overflow);
+}
+
pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
const value = switch (c) {
'0'...'9' => c - '0',
@@ -936,6 +973,25 @@ test "fmt.format" {
try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value);
}
{
+ var buf1: [32]u8 = undefined;
+ var context = BufPrintContext{ .remaining = buf1[0..] };
+ try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite);
+ var res = buf1[0 .. buf1.len - context.remaining.len];
+ assert(mem.eql(u8, res, "1234"));
+
+ context = BufPrintContext{ .remaining = buf1[0..] };
+ try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);
+ res = buf1[0 .. buf1.len - context.remaining.len];
+ debug.warn("{}\n", res);
+ assert(mem.eql(u8, res, "a"));
+
+ context = BufPrintContext{ .remaining = buf1[0..] };
+ try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);
+ res = buf1[0 .. buf1.len - context.remaining.len];
+ debug.warn("{}\n", res);
+ assert(mem.eql(u8, res, "1100"));
+ }
+ {
const value: [3]u8 = "abc";
try testFmt("array: abc\n", "array: {}\n", value);
try testFmt("array: abc\n", "array: {}\n", &value);
@@ -956,6 +1012,14 @@ test "fmt.format" {
try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);
try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value);
}
+ {
+ const value = @intToPtr(fn () void, 0xdeadbeef);
+ try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
+ }
+ {
+ const value = @intToPtr(fn () void, 0xdeadbeef);
+ try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
+ }
try testFmt("buf: Test \n", "buf: {s5}\n", "Test");
try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
diff --git a/std/hash/siphash.zig b/std/hash/siphash.zig
index 0fe958c38b..ee26950272 100644
--- a/std/hash/siphash.zig
+++ b/std/hash/siphash.zig
@@ -42,8 +42,8 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
pub fn init(key: []const u8) Self {
debug.assert(key.len >= 16);
- const k0 = mem.readInt(key[0..8], u64, Endian.Little);
- const k1 = mem.readInt(key[8..16], u64, Endian.Little);
+ const k0 = mem.readIntSliceLittle(u64, key[0..8]);
+ const k1 = mem.readIntSliceLittle(u64, key[8..16]);
var d = Self{
.v0 = k0 ^ 0x736f6d6570736575,
@@ -121,7 +121,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
fn round(d: *Self, b: []const u8) void {
debug.assert(b.len == 8);
- const m = mem.readInt(b[0..], u64, Endian.Little);
+ const m = mem.readIntSliceLittle(u64, b[0..]);
d.v3 ^= m;
comptime var i: usize = 0;
@@ -162,7 +162,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
test "siphash64-2-4 sanity" {
- const vectors = [][]const u8{
+ const vectors = [][8]u8{
"\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
"\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
"\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
@@ -235,13 +235,13 @@ test "siphash64-2-4 sanity" {
for (vectors) |vector, i| {
buffer[i] = @intCast(u8, i);
- const expected = mem.readInt(vector, u64, Endian.Little);
+ const expected = mem.readIntLittle(u64, &vector);
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
}
}
test "siphash128-2-4 sanity" {
- const vectors = [][]const u8{
+ const vectors = [][16]u8{
"\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
"\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
"\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
@@ -314,7 +314,7 @@ test "siphash128-2-4 sanity" {
for (vectors) |vector, i| {
buffer[i] = @intCast(u8, i);
- const expected = mem.readInt(vector, u128, Endian.Little);
+ const expected = mem.readIntLittle(u128, &vector);
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
}
}
diff --git a/std/hash_map.zig b/std/hash_map.zig
index 1b299eff78..99237047e0 100644
--- a/std/hash_map.zig
+++ b/std/hash_map.zig
@@ -126,6 +126,14 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
};
}
+ pub fn getOrPutValue(self: *Self, key: K, value: V) !*KV {
+ const res = try self.getOrPut(key);
+ if (!res.found_existing)
+ res.kv.value = value;
+
+ return res.kv;
+ }
+
fn ensureCapacity(self: *Self) !void {
if (self.entries.len == 0) {
return self.initCapacity(16);
@@ -354,6 +362,12 @@ test "basic hash map usage" {
gop2.kv.value = 42;
assert(map.get(99).?.value == 42);
+ const gop3 = try map.getOrPutValue(5, 5);
+ assert(gop3.value == 77);
+
+ const gop4 = try map.getOrPutValue(100, 41);
+ assert(gop4.value == 41);
+
assert(map.contains(2));
assert(map.get(2).?.value == 22);
_ = map.remove(2);
diff --git a/std/heap.zig b/std/heap.zig
index 9dbae4b8e0..46b247fa7e 100644
--- a/std/heap.zig
+++ b/std/heap.zig
@@ -66,11 +66,11 @@ pub const DirectAllocator = struct {
}
}
- fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
+ fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
const p = os.posix;
const alloc_size = if (alignment <= os.page_size) n else n + alignment;
const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0);
@@ -121,7 +121,7 @@ pub const DirectAllocator = struct {
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
if (new_size <= old_mem.len) {
const base_addr = @ptrToInt(old_mem.ptr);
const old_addr_end = base_addr + old_mem.len;
@@ -166,7 +166,7 @@ pub const DirectAllocator = struct {
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
_ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len);
},
Os.windows => {
diff --git a/std/index.zig b/std/index.zig
index 55ad016bb1..33eec14b0e 100644
--- a/std/index.zig
+++ b/std/index.zig
@@ -57,7 +57,8 @@ test "std" {
_ = @import("mutex.zig");
_ = @import("segmented_list.zig");
_ = @import("spinlock.zig");
-
+
+ _ = @import("dynamic_library.zig");
_ = @import("base64.zig");
_ = @import("build.zig");
_ = @import("c/index.zig");
diff --git a/std/io.zig b/std/io.zig
index 6473d993c4..428d95725d 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -32,6 +32,8 @@ pub fn getStdIn() GetStdIoErrs!File {
return File.openHandle(handle);
}
+pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
+
pub fn InStream(comptime ReadError: type) type {
return struct {
const Self = @This();
@@ -150,35 +152,43 @@ pub fn InStream(comptime ReadError: type) type {
}
/// Reads a native-endian integer
- pub fn readIntNe(self: *Self, comptime T: type) !T {
- return self.readInt(builtin.endian, T);
+ pub fn readIntNative(self: *Self, comptime T: type) !T {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ try self.readNoEof(bytes[0..]);
+ return mem.readIntNative(T, &bytes);
+ }
+
+ /// Reads a foreign-endian integer
+ pub fn readIntForeign(self: *Self, comptime T: type) !T {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ try self.readNoEof(bytes[0..]);
+ return mem.readIntForeign(T, &bytes);
}
- pub fn readIntLe(self: *Self, comptime T: type) !T {
+ pub fn readIntLittle(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try self.readNoEof(bytes[0..]);
- return mem.readIntLE(T, bytes);
+ return mem.readIntLittle(T, &bytes);
}
- pub fn readIntBe(self: *Self, comptime T: type) !T {
+ pub fn readIntBig(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try self.readNoEof(bytes[0..]);
- return mem.readIntBE(T, bytes);
+ return mem.readIntBig(T, &bytes);
}
- pub fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
+ pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try self.readNoEof(bytes[0..]);
- return mem.readInt(bytes, T, endian);
+ return mem.readInt(T, &bytes, endian);
}
- pub fn readVarInt(self: *Self, endian: builtin.Endian, comptime T: type, size: usize) !T {
- assert(size <= @sizeOf(T));
- assert(size <= 8);
- var input_buf: [8]u8 = undefined;
- const input_slice = input_buf[0..size];
- try self.readNoEof(input_slice);
- return mem.readInt(input_slice, T, endian);
+ pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType {
+ assert(size <= @sizeOf(ReturnType));
+ var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined;
+ const bytes = bytes_buf[0..size];
+ try self.readNoEof(bytes);
+ return mem.readVarInt(ReturnType, bytes, endian);
}
pub fn skipBytes(self: *Self, num_bytes: usize) !void {
@@ -227,25 +237,34 @@ pub fn OutStream(comptime WriteError: type) type {
}
/// Write a native-endian integer.
- pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void {
- return self.writeInt(builtin.endian, T, value);
+ pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ mem.writeIntNative(T, &bytes, value);
+ return self.writeFn(self, bytes);
+ }
+
+ /// Write a foreign-endian integer.
+ pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ mem.writeIntForeign(T, &bytes, value);
+ return self.writeFn(self, bytes);
}
- pub fn writeIntLe(self: *Self, comptime T: type, value: T) Error!void {
+ pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [@sizeOf(T)]u8 = undefined;
- mem.writeIntLE(T, &bytes, value);
+ mem.writeIntLittle(T, &bytes, value);
return self.writeFn(self, bytes);
}
- pub fn writeIntBe(self: *Self, comptime T: type, value: T) Error!void {
+ pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [@sizeOf(T)]u8 = undefined;
- mem.writeIntBE(T, &bytes, value);
+ mem.writeIntBig(T, &bytes, value);
return self.writeFn(self, bytes);
}
- pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) Error!void {
+ pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
var bytes: [@sizeOf(T)]u8 = undefined;
- mem.writeInt(bytes[0..], value, endian);
+ mem.writeInt(T, &bytes, value, endian);
return self.writeFn(self, bytes);
}
};
@@ -683,25 +702,73 @@ test "import io tests" {
}
}
-pub fn readLine(buf: []u8) !usize {
- var stdin = getStdIn() catch return error.StdInUnavailable;
- var adapter = stdin.inStream();
- var stream = &adapter.stream;
- var index: usize = 0;
+pub fn readLine(buf: *std.Buffer) ![]u8 {
+ var stdin = try getStdIn();
+ var stdin_stream = stdin.inStream();
+ return readLineFrom(&stdin_stream.stream, buf);
+}
+
+/// Reads all characters until the next newline into buf, and returns
+/// a slice of the characters read (excluding the newline character(s)).
+pub fn readLineFrom(stream: var, buf: *std.Buffer) ![]u8 {
+ const start = buf.len();
while (true) {
- const byte = stream.readByte() catch return error.EndOfFile;
+ const byte = try stream.readByte();
switch (byte) {
'\r' => {
// trash the following \n
- _ = stream.readByte() catch return error.EndOfFile;
- return index;
- },
- '\n' => return index,
- else => {
- if (index == buf.len) return error.InputTooLong;
- buf[index] = byte;
- index += 1;
+ _ = try stream.readByte();
+ return buf.toSlice()[start..];
},
+ '\n' => return buf.toSlice()[start..],
+ else => try buf.appendByte(byte),
}
}
}
+
+test "io.readLineFrom" {
+ var bytes: [128]u8 = undefined;
+ const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
+
+ var buf = try std.Buffer.initSize(allocator, 0);
+ var mem_stream = SliceInStream.init(
+ \\Line 1
+ \\Line 22
+ \\Line 333
+ );
+ const stream = &mem_stream.stream;
+
+ debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));
+ debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));
+ debug.assertError(readLineFrom(stream, &buf), error.EndOfStream);
+ debug.assert(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333"));
+}
+
+pub fn readLineSlice(slice: []u8) ![]u8 {
+ var stdin = try getStdIn();
+ var stdin_stream = stdin.inStream();
+ return readLineSliceFrom(&stdin_stream.stream, slice);
+}
+
+/// Reads all characters until the next newline into slice, and returns
+/// a slice of the characters read (excluding the newline character(s)).
+pub fn readLineSliceFrom(stream: var, slice: []u8) ![]u8 {
+ // We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte
+ // after taking ownership, which would always require an allocation.
+ var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(debug.failing_allocator, slice) };
+ try buf.resize(0);
+ return try readLineFrom(stream, &buf);
+}
+
+test "io.readLineSliceFrom" {
+ var buf: [7]u8 = undefined;
+ var mem_stream = SliceInStream.init(
+ \\Line 1
+ \\Line 22
+ \\Line 333
+ );
+ const stream = &mem_stream.stream;
+
+ debug.assert(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])));
+ debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory);
+}
diff --git a/std/io/seekable_stream.zig b/std/io/seekable_stream.zig
new file mode 100644
index 0000000000..a766f4fb89
--- /dev/null
+++ b/std/io/seekable_stream.zig
@@ -0,0 +1,32 @@
+const std = @import("../index.zig");
+const InStream = std.io.InStream;
+
+pub fn SeekableStream(comptime SeekErrorType: type, comptime GetSeekPosErrorType: type) type {
+ return struct {
+ const Self = @This();
+ pub const SeekError = SeekErrorType;
+ pub const GetSeekPosError = GetSeekPosErrorType;
+
+ seekToFn: fn (self: *Self, pos: usize) SeekError!void,
+ seekForwardFn: fn (self: *Self, pos: isize) SeekError!void,
+
+ getPosFn: fn (self: *Self) GetSeekPosError!usize,
+ getEndPosFn: fn (self: *Self) GetSeekPosError!usize,
+
+ pub fn seekTo(self: *Self, pos: usize) SeekError!void {
+ return self.seekToFn(self, pos);
+ }
+
+ pub fn seekForward(self: *Self, amt: isize) SeekError!void {
+ return self.seekForwardFn(self, amt);
+ }
+
+ pub fn getEndPos(self: *Self) GetSeekPosError!usize {
+ return self.getEndPosFn(self);
+ }
+
+ pub fn getPos(self: *Self) GetSeekPosError!usize {
+ return self.getPosFn(self);
+ }
+ };
+}
diff --git a/std/json.zig b/std/json.zig
index 23573b6d72..4d07d7b89d 100644
--- a/std/json.zig
+++ b/std/json.zig
@@ -910,7 +910,7 @@ fn checkNext(p: *TokenStream, id: Token.Id) void {
debug.assert(token.id == id);
}
-test "token" {
+test "json.token" {
const s =
\\{
\\ "Image": {
@@ -980,7 +980,7 @@ pub fn validate(s: []const u8) bool {
return p.complete;
}
-test "json validate" {
+test "json.validate" {
debug.assert(validate("{}"));
}
@@ -1188,7 +1188,7 @@ pub const Parser = struct {
}
var value = p.stack.pop();
- try p.pushToParent(value);
+ try p.pushToParent(&value);
},
Token.Id.String => {
try p.stack.append(try p.parseString(allocator, token, input, i));
@@ -1251,7 +1251,7 @@ pub const Parser = struct {
}
var value = p.stack.pop();
- try p.pushToParent(value);
+ try p.pushToParent(&value);
},
Token.Id.ObjectBegin => {
try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });
@@ -1312,19 +1312,19 @@ pub const Parser = struct {
}
}
- fn pushToParent(p: *Parser, value: Value) !void {
- switch (p.stack.at(p.stack.len - 1)) {
+ fn pushToParent(p: *Parser, value: *const Value) !void {
+ switch (p.stack.toSlice()[p.stack.len - 1]) {
// Object Parent -> [ ..., object, <key>, value ]
Value.String => |key| {
_ = p.stack.pop();
var object = &p.stack.items[p.stack.len - 1].Object;
- _ = try object.put(key, value);
+ _ = try object.put(key, value.*);
p.state = State.ObjectKey;
},
// Array Parent -> [ ..., <array>, value ]
Value.Array => |*array| {
- try array.append(value);
+ try array.append(value.*);
p.state = State.ArrayValue;
},
else => {
@@ -1348,7 +1348,7 @@ pub const Parser = struct {
}
};
-test "json parser dynamic" {
+test "json.parser.dynamic" {
var p = Parser.init(debug.global_allocator, false);
defer p.deinit();
@@ -1364,7 +1364,8 @@ test "json parser dynamic" {
\\ "Width": 100
\\ },
\\ "Animated" : false,
- \\ "IDs": [116, 943, 234, 38793]
+ \\ "IDs": [116, 943, 234, 38793],
+ \\ "ArrayOfObject": [{"n": "m"}]
\\ }
\\}
;
@@ -1387,4 +1388,10 @@ test "json parser dynamic" {
const animated = image.Object.get("Animated").?.value;
debug.assert(animated.Bool == false);
+
+ const array_of_object = image.Object.get("ArrayOfObject").?.value;
+ debug.assert(array_of_object.Array.len == 1);
+
+ const obj0 = array_of_object.Array.at(0).Object.get("n").?.value;
+ debug.assert(mem.eql(u8, obj0.String, "m"));
}
diff --git a/std/json_test.zig b/std/json_test.zig
index 8c8862441a..9e19ec592a 100644
--- a/std/json_test.zig
+++ b/std/json_test.zig
@@ -21,7 +21,7 @@ fn any(comptime s: []const u8) void {
//
// Additional tests not part of test JSONTestSuite.
-test "y_trailing_comma_after_empty" {
+test "json.test.y_trailing_comma_after_empty" {
ok(
\\{"1":[],"2":{},"3":"4"}
);
@@ -29,252 +29,252 @@ test "y_trailing_comma_after_empty" {
////////////////////////////////////////////////////////////////////////////////////////////////////
-test "y_array_arraysWithSpaces" {
+test "json.test.y_array_arraysWithSpaces" {
ok(
\\[[] ]
);
}
-test "y_array_empty" {
+test "json.test.y_array_empty" {
ok(
\\[]
);
}
-test "y_array_empty-string" {
+test "json.test.y_array_empty-string" {
ok(
\\[""]
);
}
-test "y_array_ending_with_newline" {
+test "json.test.y_array_ending_with_newline" {
ok(
\\["a"]
);
}
-test "y_array_false" {
+test "json.test.y_array_false" {
ok(
\\[false]
);
}
-test "y_array_heterogeneous" {
+test "json.test.y_array_heterogeneous" {
ok(
\\[null, 1, "1", {}]
);
}
-test "y_array_null" {
+test "json.test.y_array_null" {
ok(
\\[null]
);
}
-test "y_array_with_1_and_newline" {
+test "json.test.y_array_with_1_and_newline" {
ok(
\\[1
\\]
);
}
-test "y_array_with_leading_space" {
+test "json.test.y_array_with_leading_space" {
ok(
\\ [1]
);
}
-test "y_array_with_several_null" {
+test "json.test.y_array_with_several_null" {
ok(
\\[1,null,null,null,2]
);
}
-test "y_array_with_trailing_space" {
+test "json.test.y_array_with_trailing_space" {
ok("[2] ");
}
-test "y_number_0e+1" {
+test "json.test.y_number_0e+1" {
ok(
\\[0e+1]
);
}
-test "y_number_0e1" {
+test "json.test.y_number_0e1" {
ok(
\\[0e1]
);
}
-test "y_number_after_space" {
+test "json.test.y_number_after_space" {
ok(
\\[ 4]
);
}
-test "y_number_double_close_to_zero" {
+test "json.test.y_number_double_close_to_zero" {
ok(
\\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]
);
}
-test "y_number_int_with_exp" {
+test "json.test.y_number_int_with_exp" {
ok(
\\[20e1]
);
}
-test "y_number" {
+test "json.test.y_number" {
ok(
\\[123e65]
);
}
-test "y_number_minus_zero" {
+test "json.test.y_number_minus_zero" {
ok(
\\[-0]
);
}
-test "y_number_negative_int" {
+test "json.test.y_number_negative_int" {
ok(
\\[-123]
);
}
-test "y_number_negative_one" {
+test "json.test.y_number_negative_one" {
ok(
\\[-1]
);
}
-test "y_number_negative_zero" {
+test "json.test.y_number_negative_zero" {
ok(
\\[-0]
);
}
-test "y_number_real_capital_e" {
+test "json.test.y_number_real_capital_e" {
ok(
\\[1E22]
);
}
-test "y_number_real_capital_e_neg_exp" {
+test "json.test.y_number_real_capital_e_neg_exp" {
ok(
\\[1E-2]
);
}
-test "y_number_real_capital_e_pos_exp" {
+test "json.test.y_number_real_capital_e_pos_exp" {
ok(
\\[1E+2]
);
}
-test "y_number_real_exponent" {
+test "json.test.y_number_real_exponent" {
ok(
\\[123e45]
);
}
-test "y_number_real_fraction_exponent" {
+test "json.test.y_number_real_fraction_exponent" {
ok(
\\[123.456e78]
);
}
-test "y_number_real_neg_exp" {
+test "json.test.y_number_real_neg_exp" {
ok(
\\[1e-2]
);
}
-test "y_number_real_pos_exponent" {
+test "json.test.y_number_real_pos_exponent" {
ok(
\\[1e+2]
);
}
-test "y_number_simple_int" {
+test "json.test.y_number_simple_int" {
ok(
\\[123]
);
}
-test "y_number_simple_real" {
+test "json.test.y_number_simple_real" {
ok(
\\[123.456789]
);
}
-test "y_object_basic" {
+test "json.test.y_object_basic" {
ok(
\\{"asd":"sdf"}
);
}
-test "y_object_duplicated_key_and_value" {
+test "json.test.y_object_duplicated_key_and_value" {
ok(
\\{"a":"b","a":"b"}
);
}
-test "y_object_duplicated_key" {
+test "json.test.y_object_duplicated_key" {
ok(
\\{"a":"b","a":"c"}
);
}
-test "y_object_empty" {
+test "json.test.y_object_empty" {
ok(
\\{}
);
}
-test "y_object_empty_key" {
+test "json.test.y_object_empty_key" {
ok(
\\{"":0}
);
}
-test "y_object_escaped_null_in_key" {
+test "json.test.y_object_escaped_null_in_key" {
ok(
\\{"foo\u0000bar": 42}
);
}
-test "y_object_extreme_numbers" {
+test "json.test.y_object_extreme_numbers" {
ok(
\\{ "min": -1.0e+28, "max": 1.0e+28 }
);
}
-test "y_object" {
+test "json.test.y_object" {
ok(
\\{"asd":"sdf", "dfg":"fgh"}
);
}
-test "y_object_long_strings" {
+test "json.test.y_object_long_strings" {
ok(
\\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
);
}
-test "y_object_simple" {
+test "json.test.y_object_simple" {
ok(
\\{"a":[]}
);
}
-test "y_object_string_unicode" {
+test "json.test.y_object_string_unicode" {
ok(
\\{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" }
);
}
-test "y_object_with_newlines" {
+test "json.test.y_object_with_newlines" {
ok(
\\{
\\"a": "b"
@@ -282,419 +282,419 @@ test "y_object_with_newlines" {
);
}
-test "y_string_1_2_3_bytes_UTF-8_sequences" {
+test "json.test.y_string_1_2_3_bytes_UTF-8_sequences" {
ok(
\\["\u0060\u012a\u12AB"]
);
}
-test "y_string_accepted_surrogate_pair" {
+test "json.test.y_string_accepted_surrogate_pair" {
ok(
\\["\uD801\udc37"]
);
}
-test "y_string_accepted_surrogate_pairs" {
+test "json.test.y_string_accepted_surrogate_pairs" {
ok(
\\["\ud83d\ude39\ud83d\udc8d"]
);
}
-test "y_string_allowed_escapes" {
+test "json.test.y_string_allowed_escapes" {
ok(
\\["\"\\\/\b\f\n\r\t"]
);
}
-test "y_string_backslash_and_u_escaped_zero" {
+test "json.test.y_string_backslash_and_u_escaped_zero" {
ok(
\\["\\u0000"]
);
}
-test "y_string_backslash_doublequotes" {
+test "json.test.y_string_backslash_doublequotes" {
ok(
\\["\""]
);
}
-test "y_string_comments" {
+test "json.test.y_string_comments" {
ok(
\\["a/*b*/c/*d//e"]
);
}
-test "y_string_double_escape_a" {
+test "json.test.y_string_double_escape_a" {
ok(
\\["\\a"]
);
}
-test "y_string_double_escape_n" {
+test "json.test.y_string_double_escape_n" {
ok(
\\["\\n"]
);
}
-test "y_string_escaped_control_character" {
+test "json.test.y_string_escaped_control_character" {
ok(
\\["\u0012"]
);
}
-test "y_string_escaped_noncharacter" {
+test "json.test.y_string_escaped_noncharacter" {
ok(
\\["\uFFFF"]
);
}
-test "y_string_in_array" {
+test "json.test.y_string_in_array" {
ok(
\\["asd"]
);
}
-test "y_string_in_array_with_leading_space" {
+test "json.test.y_string_in_array_with_leading_space" {
ok(
\\[ "asd"]
);
}
-test "y_string_last_surrogates_1_and_2" {
+test "json.test.y_string_last_surrogates_1_and_2" {
ok(
\\["\uDBFF\uDFFF"]
);
}
-test "y_string_nbsp_uescaped" {
+test "json.test.y_string_nbsp_uescaped" {
ok(
\\["new\u00A0line"]
);
}
-test "y_string_nonCharacterInUTF-8_U+10FFFF" {
+test "json.test.y_string_nonCharacterInUTF-8_U+10FFFF" {
ok(
\\["􏿿"]
);
}
-test "y_string_nonCharacterInUTF-8_U+FFFF" {
+test "json.test.y_string_nonCharacterInUTF-8_U+FFFF" {
ok(
\\["￿"]
);
}
-test "y_string_null_escape" {
+test "json.test.y_string_null_escape" {
ok(
\\["\u0000"]
);
}
-test "y_string_one-byte-utf-8" {
+test "json.test.y_string_one-byte-utf-8" {
ok(
\\["\u002c"]
);
}
-test "y_string_pi" {
+test "json.test.y_string_pi" {
ok(
\\["π"]
);
}
-test "y_string_reservedCharacterInUTF-8_U+1BFFF" {
+test "json.test.y_string_reservedCharacterInUTF-8_U+1BFFF" {
ok(
\\["𛿿"]
);
}
-test "y_string_simple_ascii" {
+test "json.test.y_string_simple_ascii" {
ok(
\\["asd "]
);
}
-test "y_string_space" {
+test "json.test.y_string_space" {
ok(
\\" "
);
}
-test "y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" {
+test "json.test.y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" {
ok(
\\["\uD834\uDd1e"]
);
}
-test "y_string_three-byte-utf-8" {
+test "json.test.y_string_three-byte-utf-8" {
ok(
\\["\u0821"]
);
}
-test "y_string_two-byte-utf-8" {
+test "json.test.y_string_two-byte-utf-8" {
ok(
\\["\u0123"]
);
}
-test "y_string_u+2028_line_sep" {
+test "json.test.y_string_u+2028_line_sep" {
ok("[\"\xe2\x80\xa8\"]");
}
-test "y_string_u+2029_par_sep" {
+test "json.test.y_string_u+2029_par_sep" {
ok("[\"\xe2\x80\xa9\"]");
}
-test "y_string_uescaped_newline" {
+test "json.test.y_string_uescaped_newline" {
ok(
\\["new\u000Aline"]
);
}
-test "y_string_uEscape" {
+test "json.test.y_string_uEscape" {
ok(
\\["\u0061\u30af\u30EA\u30b9"]
);
}
-test "y_string_unescaped_char_delete" {
+test "json.test.y_string_unescaped_char_delete" {
ok("[\"\x7f\"]");
}
-test "y_string_unicode_2" {
+test "json.test.y_string_unicode_2" {
ok(
\\["⍂㈴⍂"]
);
}
-test "y_string_unicodeEscapedBackslash" {
+test "json.test.y_string_unicodeEscapedBackslash" {
ok(
\\["\u005C"]
);
}
-test "y_string_unicode_escaped_double_quote" {
+test "json.test.y_string_unicode_escaped_double_quote" {
ok(
\\["\u0022"]
);
}
-test "y_string_unicode" {
+test "json.test.y_string_unicode" {
ok(
\\["\uA66D"]
);
}
-test "y_string_unicode_U+10FFFE_nonchar" {
+test "json.test.y_string_unicode_U+10FFFE_nonchar" {
ok(
\\["\uDBFF\uDFFE"]
);
}
-test "y_string_unicode_U+1FFFE_nonchar" {
+test "json.test.y_string_unicode_U+1FFFE_nonchar" {
ok(
\\["\uD83F\uDFFE"]
);
}
-test "y_string_unicode_U+200B_ZERO_WIDTH_SPACE" {
+test "json.test.y_string_unicode_U+200B_ZERO_WIDTH_SPACE" {
ok(
\\["\u200B"]
);
}
-test "y_string_unicode_U+2064_invisible_plus" {
+test "json.test.y_string_unicode_U+2064_invisible_plus" {
ok(
\\["\u2064"]
);
}
-test "y_string_unicode_U+FDD0_nonchar" {
+test "json.test.y_string_unicode_U+FDD0_nonchar" {
ok(
\\["\uFDD0"]
);
}
-test "y_string_unicode_U+FFFE_nonchar" {
+test "json.test.y_string_unicode_U+FFFE_nonchar" {
ok(
\\["\uFFFE"]
);
}
-test "y_string_utf8" {
+test "json.test.y_string_utf8" {
ok(
\\["€𝄞"]
);
}
-test "y_string_with_del_character" {
+test "json.test.y_string_with_del_character" {
ok("[\"a\x7fa\"]");
}
-test "y_structure_lonely_false" {
+test "json.test.y_structure_lonely_false" {
ok(
\\false
);
}
-test "y_structure_lonely_int" {
+test "json.test.y_structure_lonely_int" {
ok(
\\42
);
}
-test "y_structure_lonely_negative_real" {
+test "json.test.y_structure_lonely_negative_real" {
ok(
\\-0.1
);
}
-test "y_structure_lonely_null" {
+test "json.test.y_structure_lonely_null" {
ok(
\\null
);
}
-test "y_structure_lonely_string" {
+test "json.test.y_structure_lonely_string" {
ok(
\\"asd"
);
}
-test "y_structure_lonely_true" {
+test "json.test.y_structure_lonely_true" {
ok(
\\true
);
}
-test "y_structure_string_empty" {
+test "json.test.y_structure_string_empty" {
ok(
\\""
);
}
-test "y_structure_trailing_newline" {
+test "json.test.y_structure_trailing_newline" {
ok(
\\["a"]
);
}
-test "y_structure_true_in_array" {
+test "json.test.y_structure_true_in_array" {
ok(
\\[true]
);
}
-test "y_structure_whitespace_array" {
+test "json.test.y_structure_whitespace_array" {
ok(" [] ");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
-test "n_array_1_true_without_comma" {
+test "json.test.n_array_1_true_without_comma" {
err(
\\[1 true]
);
}
-test "n_array_a_invalid_utf8" {
+test "json.test.n_array_a_invalid_utf8" {
err(
\\[aå]
);
}
-test "n_array_colon_instead_of_comma" {
+test "json.test.n_array_colon_instead_of_comma" {
err(
\\["": 1]
);
}
-test "n_array_comma_after_close" {
+test "json.test.n_array_comma_after_close" {
//err(
// \\[""],
//);
}
-test "n_array_comma_and_number" {
+test "json.test.n_array_comma_and_number" {
err(
\\[,1]
);
}
-test "n_array_double_comma" {
+test "json.test.n_array_double_comma" {
err(
\\[1,,2]
);
}
-test "n_array_double_extra_comma" {
+test "json.test.n_array_double_extra_comma" {
err(
\\["x",,]
);
}
-test "n_array_extra_close" {
+test "json.test.n_array_extra_close" {
err(
\\["x"]]
);
}
-test "n_array_extra_comma" {
+test "json.test.n_array_extra_comma" {
//err(
// \\["",]
//);
}
-test "n_array_incomplete_invalid_value" {
+test "json.test.n_array_incomplete_invalid_value" {
err(
\\[x
);
}
-test "n_array_incomplete" {
+test "json.test.n_array_incomplete" {
err(
\\["x"
);
}
-test "n_array_inner_array_no_comma" {
+test "json.test.n_array_inner_array_no_comma" {
err(
\\[3[4]]
);
}
-test "n_array_invalid_utf8" {
+test "json.test.n_array_invalid_utf8" {
err(
\\[ÿ]
);
}
-test "n_array_items_separated_by_semicolon" {
+test "json.test.n_array_items_separated_by_semicolon" {
err(
\\[1:2]
);
}
-test "n_array_just_comma" {
+test "json.test.n_array_just_comma" {
err(
\\[,]
);
}
-test "n_array_just_minus" {
+test "json.test.n_array_just_minus" {
err(
\\[-]
);
}
-test "n_array_missing_value" {
+test "json.test.n_array_missing_value" {
err(
\\[ , ""]
);
}
-test "n_array_newlines_unclosed" {
+test "json.test.n_array_newlines_unclosed" {
err(
\\["a",
\\4
@@ -702,41 +702,41 @@ test "n_array_newlines_unclosed" {
);
}
-test "n_array_number_and_comma" {
+test "json.test.n_array_number_and_comma" {
err(
\\[1,]
);
}
-test "n_array_number_and_several_commas" {
+test "json.test.n_array_number_and_several_commas" {
err(
\\[1,,]
);
}
-test "n_array_spaces_vertical_tab_formfeed" {
+test "json.test.n_array_spaces_vertical_tab_formfeed" {
err("[\"\x0aa\"\\f]");
}
-test "n_array_star_inside" {
+test "json.test.n_array_star_inside" {
err(
\\[*]
);
}
-test "n_array_unclosed" {
+test "json.test.n_array_unclosed" {
err(
\\[""
);
}
-test "n_array_unclosed_trailing_comma" {
+test "json.test.n_array_unclosed_trailing_comma" {
err(
\\[1,
);
}
-test "n_array_unclosed_with_new_lines" {
+test "json.test.n_array_unclosed_with_new_lines" {
err(
\\[1,
\\1
@@ -744,956 +744,956 @@ test "n_array_unclosed_with_new_lines" {
);
}
-test "n_array_unclosed_with_object_inside" {
+test "json.test.n_array_unclosed_with_object_inside" {
err(
\\[{}
);
}
-test "n_incomplete_false" {
+test "json.test.n_incomplete_false" {
err(
\\[fals]
);
}
-test "n_incomplete_null" {
+test "json.test.n_incomplete_null" {
err(
\\[nul]
);
}
-test "n_incomplete_true" {
+test "json.test.n_incomplete_true" {
err(
\\[tru]
);
}
-test "n_multidigit_number_then_00" {
+test "json.test.n_multidigit_number_then_00" {
err("123\x00");
}
-test "n_number_0.1.2" {
+test "json.test.n_number_0.1.2" {
err(
\\[0.1.2]
);
}
-test "n_number_-01" {
+test "json.test.n_number_-01" {
err(
\\[-01]
);
}
-test "n_number_0.3e" {
+test "json.test.n_number_0.3e" {
err(
\\[0.3e]
);
}
-test "n_number_0.3e+" {
+test "json.test.n_number_0.3e+" {
err(
\\[0.3e+]
);
}
-test "n_number_0_capital_E" {
+test "json.test.n_number_0_capital_E" {
err(
\\[0E]
);
}
-test "n_number_0_capital_E+" {
+test "json.test.n_number_0_capital_E+" {
err(
\\[0E+]
);
}
-test "n_number_0.e1" {
+test "json.test.n_number_0.e1" {
err(
\\[0.e1]
);
}
-test "n_number_0e" {
+test "json.test.n_number_0e" {
err(
\\[0e]
);
}
-test "n_number_0e+" {
+test "json.test.n_number_0e+" {
err(
\\[0e+]
);
}
-test "n_number_1_000" {
+test "json.test.n_number_1_000" {
err(
\\[1 000.0]
);
}
-test "n_number_1.0e-" {
+test "json.test.n_number_1.0e-" {
err(
\\[1.0e-]
);
}
-test "n_number_1.0e" {
+test "json.test.n_number_1.0e" {
err(
\\[1.0e]
);
}
-test "n_number_1.0e+" {
+test "json.test.n_number_1.0e+" {
err(
\\[1.0e+]
);
}
-test "n_number_-1.0." {
+test "json.test.n_number_-1.0." {
err(
\\[-1.0.]
);
}
-test "n_number_1eE2" {
+test "json.test.n_number_1eE2" {
err(
\\[1eE2]
);
}
-test "n_number_.-1" {
+test "json.test.n_number_.-1" {
err(
\\[.-1]
);
}
-test "n_number_+1" {
+test "json.test.n_number_+1" {
err(
\\[+1]
);
}
-test "n_number_.2e-3" {
+test "json.test.n_number_.2e-3" {
err(
\\[.2e-3]
);
}
-test "n_number_2.e-3" {
+test "json.test.n_number_2.e-3" {
err(
\\[2.e-3]
);
}
-test "n_number_2.e+3" {
+test "json.test.n_number_2.e+3" {
err(
\\[2.e+3]
);
}
-test "n_number_2.e3" {
+test "json.test.n_number_2.e3" {
err(
\\[2.e3]
);
}
-test "n_number_-2." {
+test "json.test.n_number_-2." {
err(
\\[-2.]
);
}
-test "n_number_9.e+" {
+test "json.test.n_number_9.e+" {
err(
\\[9.e+]
);
}
-test "n_number_expression" {
+test "json.test.n_number_expression" {
err(
\\[1+2]
);
}
-test "n_number_hex_1_digit" {
+test "json.test.n_number_hex_1_digit" {
err(
\\[0x1]
);
}
-test "n_number_hex_2_digits" {
+test "json.test.n_number_hex_2_digits" {
err(
\\[0x42]
);
}
-test "n_number_infinity" {
+test "json.test.n_number_infinity" {
err(
\\[Infinity]
);
}
-test "n_number_+Inf" {
+test "json.test.n_number_+Inf" {
err(
\\[+Inf]
);
}
-test "n_number_Inf" {
+test "json.test.n_number_Inf" {
err(
\\[Inf]
);
}
-test "n_number_invalid+-" {
+test "json.test.n_number_invalid+-" {
err(
\\[0e+-1]
);
}
-test "n_number_invalid-negative-real" {
+test "json.test.n_number_invalid-negative-real" {
err(
\\[-123.123foo]
);
}
-test "n_number_invalid-utf-8-in-bigger-int" {
+test "json.test.n_number_invalid-utf-8-in-bigger-int" {
err(
\\[123å]
);
}
-test "n_number_invalid-utf-8-in-exponent" {
+test "json.test.n_number_invalid-utf-8-in-exponent" {
err(
\\[1e1å]
);
}
-test "n_number_invalid-utf-8-in-int" {
+test "json.test.n_number_invalid-utf-8-in-int" {
err(
\\[0å]
);
}
-test "n_number_++" {
+test "json.test.n_number_++" {
err(
\\[++1234]
);
}
-test "n_number_minus_infinity" {
+test "json.test.n_number_minus_infinity" {
err(
\\[-Infinity]
);
}
-test "n_number_minus_sign_with_trailing_garbage" {
+test "json.test.n_number_minus_sign_with_trailing_garbage" {
err(
\\[-foo]
);
}
-test "n_number_minus_space_1" {
+test "json.test.n_number_minus_space_1" {
err(
\\[- 1]
);
}
-test "n_number_-NaN" {
+test "json.test.n_number_-NaN" {
err(
\\[-NaN]
);
}
-test "n_number_NaN" {
+test "json.test.n_number_NaN" {
err(
\\[NaN]
);
}
-test "n_number_neg_int_starting_with_zero" {
+test "json.test.n_number_neg_int_starting_with_zero" {
err(
\\[-012]
);
}
-test "n_number_neg_real_without_int_part" {
+test "json.test.n_number_neg_real_without_int_part" {
err(
\\[-.123]
);
}
-test "n_number_neg_with_garbage_at_end" {
+test "json.test.n_number_neg_with_garbage_at_end" {
err(
\\[-1x]
);
}
-test "n_number_real_garbage_after_e" {
+test "json.test.n_number_real_garbage_after_e" {
err(
\\[1ea]
);
}
-test "n_number_real_with_invalid_utf8_after_e" {
+test "json.test.n_number_real_with_invalid_utf8_after_e" {
err(
\\[1eå]
);
}
-test "n_number_real_without_fractional_part" {
+test "json.test.n_number_real_without_fractional_part" {
err(
\\[1.]
);
}
-test "n_number_starting_with_dot" {
+test "json.test.n_number_starting_with_dot" {
err(
\\[.123]
);
}
-test "n_number_U+FF11_fullwidth_digit_one" {
+test "json.test.n_number_U+FF11_fullwidth_digit_one" {
err(
\\[1]
);
}
-test "n_number_with_alpha_char" {
+test "json.test.n_number_with_alpha_char" {
err(
\\[1.8011670033376514H-308]
);
}
-test "n_number_with_alpha" {
+test "json.test.n_number_with_alpha" {
err(
\\[1.2a-3]
);
}
-test "n_number_with_leading_zero" {
+test "json.test.n_number_with_leading_zero" {
err(
\\[012]
);
}
-test "n_object_bad_value" {
+test "json.test.n_object_bad_value" {
err(
\\["x", truth]
);
}
-test "n_object_bracket_key" {
+test "json.test.n_object_bracket_key" {
err(
\\{[: "x"}
);
}
-test "n_object_comma_instead_of_colon" {
+test "json.test.n_object_comma_instead_of_colon" {
err(
\\{"x", null}
);
}
-test "n_object_double_colon" {
+test "json.test.n_object_double_colon" {
err(
\\{"x"::"b"}
);
}
-test "n_object_emoji" {
+test "json.test.n_object_emoji" {
err(
\\{🇨🇭}
);
}
-test "n_object_garbage_at_end" {
+test "json.test.n_object_garbage_at_end" {
err(
\\{"a":"a" 123}
);
}
-test "n_object_key_with_single_quotes" {
+test "json.test.n_object_key_with_single_quotes" {
err(
\\{key: 'value'}
);
}
-test "n_object_lone_continuation_byte_in_key_and_trailing_comma" {
+test "json.test.n_object_lone_continuation_byte_in_key_and_trailing_comma" {
err(
\\{"¹":"0",}
);
}
-test "n_object_missing_colon" {
+test "json.test.n_object_missing_colon" {
err(
\\{"a" b}
);
}
-test "n_object_missing_key" {
+test "json.test.n_object_missing_key" {
err(
\\{:"b"}
);
}
-test "n_object_missing_semicolon" {
+test "json.test.n_object_missing_semicolon" {
err(
\\{"a" "b"}
);
}
-test "n_object_missing_value" {
+test "json.test.n_object_missing_value" {
err(
\\{"a":
);
}
-test "n_object_no-colon" {
+test "json.test.n_object_no-colon" {
err(
\\{"a"
);
}
-test "n_object_non_string_key_but_huge_number_instead" {
+test "json.test.n_object_non_string_key_but_huge_number_instead" {
err(
\\{9999E9999:1}
);
}
-test "n_object_non_string_key" {
+test "json.test.n_object_non_string_key" {
err(
\\{1:1}
);
}
-test "n_object_repeated_null_null" {
+test "json.test.n_object_repeated_null_null" {
err(
\\{null:null,null:null}
);
}
-test "n_object_several_trailing_commas" {
+test "json.test.n_object_several_trailing_commas" {
err(
\\{"id":0,,,,,}
);
}
-test "n_object_single_quote" {
+test "json.test.n_object_single_quote" {
err(
\\{'a':0}
);
}
-test "n_object_trailing_comma" {
+test "json.test.n_object_trailing_comma" {
err(
\\{"id":0,}
);
}
-test "n_object_trailing_comment" {
+test "json.test.n_object_trailing_comment" {
err(
\\{"a":"b"}/**/
);
}
-test "n_object_trailing_comment_open" {
+test "json.test.n_object_trailing_comment_open" {
err(
\\{"a":"b"}/**//
);
}
-test "n_object_trailing_comment_slash_open_incomplete" {
+test "json.test.n_object_trailing_comment_slash_open_incomplete" {
err(
\\{"a":"b"}/
);
}
-test "n_object_trailing_comment_slash_open" {
+test "json.test.n_object_trailing_comment_slash_open" {
err(
\\{"a":"b"}//
);
}
-test "n_object_two_commas_in_a_row" {
+test "json.test.n_object_two_commas_in_a_row" {
err(
\\{"a":"b",,"c":"d"}
);
}
-test "n_object_unquoted_key" {
+test "json.test.n_object_unquoted_key" {
err(
\\{a: "b"}
);
}
-test "n_object_unterminated-value" {
+test "json.test.n_object_unterminated-value" {
err(
\\{"a":"a
);
}
-test "n_object_with_single_string" {
+test "json.test.n_object_with_single_string" {
err(
\\{ "foo" : "bar", "a" }
);
}
-test "n_object_with_trailing_garbage" {
+test "json.test.n_object_with_trailing_garbage" {
err(
\\{"a":"b"}#
);
}
-test "n_single_space" {
+test "json.test.n_single_space" {
err(" ");
}
-test "n_string_1_surrogate_then_escape" {
+test "json.test.n_string_1_surrogate_then_escape" {
err(
\\["\uD800\"]
);
}
-test "n_string_1_surrogate_then_escape_u1" {
+test "json.test.n_string_1_surrogate_then_escape_u1" {
err(
\\["\uD800\u1"]
);
}
-test "n_string_1_surrogate_then_escape_u1x" {
+test "json.test.n_string_1_surrogate_then_escape_u1x" {
err(
\\["\uD800\u1x"]
);
}
-test "n_string_1_surrogate_then_escape_u" {
+test "json.test.n_string_1_surrogate_then_escape_u" {
err(
\\["\uD800\u"]
);
}
-test "n_string_accentuated_char_no_quotes" {
+test "json.test.n_string_accentuated_char_no_quotes" {
err(
\\[é]
);
}
-test "n_string_backslash_00" {
+test "json.test.n_string_backslash_00" {
err("[\"\x00\"]");
}
-test "n_string_escaped_backslash_bad" {
+test "json.test.n_string_escaped_backslash_bad" {
err(
\\["\\\"]
);
}
-test "n_string_escaped_ctrl_char_tab" {
+test "json.test.n_string_escaped_ctrl_char_tab" {
err("\x5b\x22\x5c\x09\x22\x5d");
}
-test "n_string_escaped_emoji" {
+test "json.test.n_string_escaped_emoji" {
err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]");
}
-test "n_string_escape_x" {
+test "json.test.n_string_escape_x" {
err(
\\["\x00"]
);
}
-test "n_string_incomplete_escaped_character" {
+test "json.test.n_string_incomplete_escaped_character" {
err(
\\["\u00A"]
);
}
-test "n_string_incomplete_escape" {
+test "json.test.n_string_incomplete_escape" {
err(
\\["\"]
);
}
-test "n_string_incomplete_surrogate_escape_invalid" {
+test "json.test.n_string_incomplete_surrogate_escape_invalid" {
err(
\\["\uD800\uD800\x"]
);
}
-test "n_string_incomplete_surrogate" {
+test "json.test.n_string_incomplete_surrogate" {
err(
\\["\uD834\uDd"]
);
}
-test "n_string_invalid_backslash_esc" {
+test "json.test.n_string_invalid_backslash_esc" {
err(
\\["\a"]
);
}
-test "n_string_invalid_unicode_escape" {
+test "json.test.n_string_invalid_unicode_escape" {
err(
\\["\uqqqq"]
);
}
-test "n_string_invalid_utf8_after_escape" {
+test "json.test.n_string_invalid_utf8_after_escape" {
err("[\"\\\x75\xc3\xa5\"]");
}
-test "n_string_invalid-utf-8-in-escape" {
+test "json.test.n_string_invalid-utf-8-in-escape" {
err(
\\["\uå"]
);
}
-test "n_string_leading_uescaped_thinspace" {
+test "json.test.n_string_leading_uescaped_thinspace" {
err(
\\[\u0020"asd"]
);
}
-test "n_string_no_quotes_with_bad_escape" {
+test "json.test.n_string_no_quotes_with_bad_escape" {
err(
\\[\n]
);
}
-test "n_string_single_doublequote" {
+test "json.test.n_string_single_doublequote" {
err(
\\"
);
}
-test "n_string_single_quote" {
+test "json.test.n_string_single_quote" {
err(
\\['single quote']
);
}
-test "n_string_single_string_no_double_quotes" {
+test "json.test.n_string_single_string_no_double_quotes" {
err(
\\abc
);
}
-test "n_string_start_escape_unclosed" {
+test "json.test.n_string_start_escape_unclosed" {
err(
\\["\
);
}
-test "n_string_unescaped_crtl_char" {
+test "json.test.n_string_unescaped_crtl_char" {
err("[\"a\x00a\"]");
}
-test "n_string_unescaped_newline" {
+test "json.test.n_string_unescaped_newline" {
err(
\\["new
\\line"]
);
}
-test "n_string_unescaped_tab" {
+test "json.test.n_string_unescaped_tab" {
err("[\"\t\"]");
}
-test "n_string_unicode_CapitalU" {
+test "json.test.n_string_unicode_CapitalU" {
err(
\\"\UA66D"
);
}
-test "n_string_with_trailing_garbage" {
+test "json.test.n_string_with_trailing_garbage" {
err(
\\""x
);
}
-test "n_structure_100000_opening_arrays" {
+test "json.test.n_structure_100000_opening_arrays" {
err("[" ** 100000);
}
-test "n_structure_angle_bracket_." {
+test "json.test.n_structure_angle_bracket_." {
err(
\\<.>
);
}
-test "n_structure_angle_bracket_null" {
+test "json.test.n_structure_angle_bracket_null" {
err(
\\[<null>]
);
}
-test "n_structure_array_trailing_garbage" {
+test "json.test.n_structure_array_trailing_garbage" {
err(
\\[1]x
);
}
-test "n_structure_array_with_extra_array_close" {
+test "json.test.n_structure_array_with_extra_array_close" {
err(
\\[1]]
);
}
-test "n_structure_array_with_unclosed_string" {
+test "json.test.n_structure_array_with_unclosed_string" {
err(
\\["asd]
);
}
-test "n_structure_ascii-unicode-identifier" {
+test "json.test.n_structure_ascii-unicode-identifier" {
err(
\\aå
);
}
-test "n_structure_capitalized_True" {
+test "json.test.n_structure_capitalized_True" {
err(
\\[True]
);
}
-test "n_structure_close_unopened_array" {
+test "json.test.n_structure_close_unopened_array" {
err(
\\1]
);
}
-test "n_structure_comma_instead_of_closing_brace" {
+test "json.test.n_structure_comma_instead_of_closing_brace" {
err(
\\{"x": true,
);
}
-test "n_structure_double_array" {
+test "json.test.n_structure_double_array" {
err(
\\[][]
);
}
-test "n_structure_end_array" {
+test "json.test.n_structure_end_array" {
err(
\\]
);
}
-test "n_structure_incomplete_UTF8_BOM" {
+test "json.test.n_structure_incomplete_UTF8_BOM" {
err(
\\ï»{}
);
}
-test "n_structure_lone-invalid-utf-8" {
+test "json.test.n_structure_lone-invalid-utf-8" {
err(
\\å
);
}
-test "n_structure_lone-open-bracket" {
+test "json.test.n_structure_lone-open-bracket" {
err(
\\[
);
}
-test "n_structure_no_data" {
+test "json.test.n_structure_no_data" {
err(
\\
);
}
-test "n_structure_null-byte-outside-string" {
+test "json.test.n_structure_null-byte-outside-string" {
err("[\x00]");
}
-test "n_structure_number_with_trailing_garbage" {
+test "json.test.n_structure_number_with_trailing_garbage" {
err(
\\2@
);
}
-test "n_structure_object_followed_by_closing_object" {
+test "json.test.n_structure_object_followed_by_closing_object" {
err(
\\{}}
);
}
-test "n_structure_object_unclosed_no_value" {
+test "json.test.n_structure_object_unclosed_no_value" {
err(
\\{"":
);
}
-test "n_structure_object_with_comment" {
+test "json.test.n_structure_object_with_comment" {
err(
\\{"a":/*comment*/"b"}
);
}
-test "n_structure_object_with_trailing_garbage" {
+test "json.test.n_structure_object_with_trailing_garbage" {
err(
\\{"a": true} "x"
);
}
-test "n_structure_open_array_apostrophe" {
+test "json.test.n_structure_open_array_apostrophe" {
err(
\\['
);
}
-test "n_structure_open_array_comma" {
+test "json.test.n_structure_open_array_comma" {
err(
\\[,
);
}
-test "n_structure_open_array_object" {
+test "json.test.n_structure_open_array_object" {
err("[{\"\":" ** 50000);
}
-test "n_structure_open_array_open_object" {
+test "json.test.n_structure_open_array_open_object" {
err(
\\[{
);
}
-test "n_structure_open_array_open_string" {
+test "json.test.n_structure_open_array_open_string" {
err(
\\["a
);
}
-test "n_structure_open_array_string" {
+test "json.test.n_structure_open_array_string" {
err(
\\["a"
);
}
-test "n_structure_open_object_close_array" {
+test "json.test.n_structure_open_object_close_array" {
err(
\\{]
);
}
-test "n_structure_open_object_comma" {
+test "json.test.n_structure_open_object_comma" {
err(
\\{,
);
}
-test "n_structure_open_object" {
+test "json.test.n_structure_open_object" {
err(
\\{
);
}
-test "n_structure_open_object_open_array" {
+test "json.test.n_structure_open_object_open_array" {
err(
\\{[
);
}
-test "n_structure_open_object_open_string" {
+test "json.test.n_structure_open_object_open_string" {
err(
\\{"a
);
}
-test "n_structure_open_object_string_with_apostrophes" {
+test "json.test.n_structure_open_object_string_with_apostrophes" {
err(
\\{'a'
);
}
-test "n_structure_open_open" {
+test "json.test.n_structure_open_open" {
err(
\\["\{["\{["\{["\{
);
}
-test "n_structure_single_eacute" {
+test "json.test.n_structure_single_eacute" {
err(
\\é
);
}
-test "n_structure_single_star" {
+test "json.test.n_structure_single_star" {
err(
\\*
);
}
-test "n_structure_trailing_#" {
+test "json.test.n_structure_trailing_#" {
err(
\\{"a":"b"}#{}
);
}
-test "n_structure_U+2060_word_joined" {
+test "json.test.n_structure_U+2060_word_joined" {
err(
\\[⁠]
);
}
-test "n_structure_uescaped_LF_before_string" {
+test "json.test.n_structure_uescaped_LF_before_string" {
err(
\\[\u000A""]
);
}
-test "n_structure_unclosed_array" {
+test "json.test.n_structure_unclosed_array" {
err(
\\[1
);
}
-test "n_structure_unclosed_array_partial_null" {
+test "json.test.n_structure_unclosed_array_partial_null" {
err(
\\[ false, nul
);
}
-test "n_structure_unclosed_array_unfinished_false" {
+test "json.test.n_structure_unclosed_array_unfinished_false" {
err(
\\[ true, fals
);
}
-test "n_structure_unclosed_array_unfinished_true" {
+test "json.test.n_structure_unclosed_array_unfinished_true" {
err(
\\[ false, tru
);
}
-test "n_structure_unclosed_object" {
+test "json.test.n_structure_unclosed_object" {
err(
\\{"asd":"asd"
);
}
-test "n_structure_unicode-identifier" {
+test "json.test.n_structure_unicode-identifier" {
err(
\\Ã¥
);
}
-test "n_structure_UTF8_BOM_no_data" {
+test "json.test.n_structure_UTF8_BOM_no_data" {
err(
\\
);
}
-test "n_structure_whitespace_formfeed" {
+test "json.test.n_structure_whitespace_formfeed" {
err("[\x0c]");
}
-test "n_structure_whitespace_U+2060_word_joiner" {
+test "json.test.n_structure_whitespace_U+2060_word_joiner" {
err(
\\[⁠]
);
@@ -1701,203 +1701,203 @@ test "n_structure_whitespace_U+2060_word_joiner" {
////////////////////////////////////////////////////////////////////////////////////////////////////
-test "i_number_double_huge_neg_exp" {
+test "json.test.i_number_double_huge_neg_exp" {
any(
\\[123.456e-789]
);
}
-test "i_number_huge_exp" {
+test "json.test.i_number_huge_exp" {
any(
\\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]
);
}
-test "i_number_neg_int_huge_exp" {
+test "json.test.i_number_neg_int_huge_exp" {
any(
\\[-1e+9999]
);
}
-test "i_number_pos_double_huge_exp" {
+test "json.test.i_number_pos_double_huge_exp" {
any(
\\[1.5e+9999]
);
}
-test "i_number_real_neg_overflow" {
+test "json.test.i_number_real_neg_overflow" {
any(
\\[-123123e100000]
);
}
-test "i_number_real_pos_overflow" {
+test "json.test.i_number_real_pos_overflow" {
any(
\\[123123e100000]
);
}
-test "i_number_real_underflow" {
+test "json.test.i_number_real_underflow" {
any(
\\[123e-10000000]
);
}
-test "i_number_too_big_neg_int" {
+test "json.test.i_number_too_big_neg_int" {
any(
\\[-123123123123123123123123123123]
);
}
-test "i_number_too_big_pos_int" {
+test "json.test.i_number_too_big_pos_int" {
any(
\\[100000000000000000000]
);
}
-test "i_number_very_big_negative_int" {
+test "json.test.i_number_very_big_negative_int" {
any(
\\[-237462374673276894279832749832423479823246327846]
);
}
-test "i_object_key_lone_2nd_surrogate" {
+test "json.test.i_object_key_lone_2nd_surrogate" {
any(
\\{"\uDFAA":0}
);
}
-test "i_string_1st_surrogate_but_2nd_missing" {
+test "json.test.i_string_1st_surrogate_but_2nd_missing" {
any(
\\["\uDADA"]
);
}
-test "i_string_1st_valid_surrogate_2nd_invalid" {
+test "json.test.i_string_1st_valid_surrogate_2nd_invalid" {
any(
\\["\uD888\u1234"]
);
}
-test "i_string_incomplete_surrogate_and_escape_valid" {
+test "json.test.i_string_incomplete_surrogate_and_escape_valid" {
any(
\\["\uD800\n"]
);
}
-test "i_string_incomplete_surrogate_pair" {
+test "json.test.i_string_incomplete_surrogate_pair" {
any(
\\["\uDd1ea"]
);
}
-test "i_string_incomplete_surrogates_escape_valid" {
+test "json.test.i_string_incomplete_surrogates_escape_valid" {
any(
\\["\uD800\uD800\n"]
);
}
-test "i_string_invalid_lonely_surrogate" {
+test "json.test.i_string_invalid_lonely_surrogate" {
any(
\\["\ud800"]
);
}
-test "i_string_invalid_surrogate" {
+test "json.test.i_string_invalid_surrogate" {
any(
\\["\ud800abc"]
);
}
-test "i_string_invalid_utf-8" {
+test "json.test.i_string_invalid_utf-8" {
any(
\\["ÿ"]
);
}
-test "i_string_inverted_surrogates_U+1D11E" {
+test "json.test.i_string_inverted_surrogates_U+1D11E" {
any(
\\["\uDd1e\uD834"]
);
}
-test "i_string_iso_latin_1" {
+test "json.test.i_string_iso_latin_1" {
any(
\\["é"]
);
}
-test "i_string_lone_second_surrogate" {
+test "json.test.i_string_lone_second_surrogate" {
any(
\\["\uDFAA"]
);
}
-test "i_string_lone_utf8_continuation_byte" {
+test "json.test.i_string_lone_utf8_continuation_byte" {
any(
\\[""]
);
}
-test "i_string_not_in_unicode_range" {
+test "json.test.i_string_not_in_unicode_range" {
any(
\\["ô¿¿¿"]
);
}
-test "i_string_overlong_sequence_2_bytes" {
+test "json.test.i_string_overlong_sequence_2_bytes" {
any(
\\["À¯"]
);
}
-test "i_string_overlong_sequence_6_bytes" {
+test "json.test.i_string_overlong_sequence_6_bytes" {
any(
\\["üƒ¿¿¿¿"]
);
}
-test "i_string_overlong_sequence_6_bytes_null" {
+test "json.test.i_string_overlong_sequence_6_bytes_null" {
any(
\\["ü€€€€€"]
);
}
-test "i_string_truncated-utf-8" {
+test "json.test.i_string_truncated-utf-8" {
any(
\\["àÿ"]
);
}
-test "i_string_utf16BE_no_BOM" {
+test "json.test.i_string_utf16BE_no_BOM" {
any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d");
}
-test "i_string_utf16LE_no_BOM" {
+test "json.test.i_string_utf16LE_no_BOM" {
any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
}
-test "i_string_UTF-16LE_with_BOM" {
+test "json.test.i_string_UTF-16LE_with_BOM" {
any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
}
-test "i_string_UTF-8_invalid_sequence" {
+test "json.test.i_string_UTF-8_invalid_sequence" {
any(
\\["日шú"]
);
}
-test "i_string_UTF8_surrogate_U+D800" {
+test "json.test.i_string_UTF8_surrogate_U+D800" {
any(
\\["í €"]
);
}
-test "i_structure_500_nested_arrays" {
+test "json.test.i_structure_500_nested_arrays" {
any(("[" ** 500) ++ ("]" ** 500));
}
-test "i_structure_UTF-8_BOM_empty_object" {
+test "json.test.i_structure_UTF-8_BOM_empty_object" {
any(
\\{}
);
diff --git a/std/linked_list.zig b/std/linked_list.zig
index 46cbeb03c4..c3db55b5a6 100644
--- a/std/linked_list.zig
+++ b/std/linked_list.zig
@@ -82,6 +82,28 @@ pub fn LinkedList(comptime T: type) type {
list.len += 1;
}
+ /// Concatenate list2 onto the end of list1, removing all entries from the former.
+ ///
+ /// Arguments:
+ /// list1: the list to concatenate onto
+ /// list2: the list to be concatenated
+ pub fn concatByMoving(list1: *Self, list2: *Self) void {
+ const l2_first = list2.first orelse return;
+ if (list1.last) |l1_last| {
+ l1_last.next = list2.first;
+ l2_first.prev = list1.last;
+ list1.len += list2.len;
+ } else {
+ // list1 was empty
+ list1.first = list2.first;
+ list1.len = list2.len;
+ }
+ list1.last = list2.last;
+ list2.first = null;
+ list2.last = null;
+ list2.len = 0;
+ }
+
/// Insert a new node at the end of the list.
///
/// Arguments:
@@ -247,3 +269,77 @@ test "basic linked list test" {
assert(list.last.?.data == 4);
assert(list.len == 2);
}
+
+test "linked list concatenation" {
+ const allocator = debug.global_allocator;
+ var list1 = LinkedList(u32).init();
+ var list2 = LinkedList(u32).init();
+
+ var one = try list1.createNode(1, allocator);
+ defer list1.destroyNode(one, allocator);
+ var two = try list1.createNode(2, allocator);
+ defer list1.destroyNode(two, allocator);
+ var three = try list1.createNode(3, allocator);
+ defer list1.destroyNode(three, allocator);
+ var four = try list1.createNode(4, allocator);
+ defer list1.destroyNode(four, allocator);
+ var five = try list1.createNode(5, allocator);
+ defer list1.destroyNode(five, allocator);
+
+ list1.append(one);
+ list1.append(two);
+ list2.append(three);
+ list2.append(four);
+ list2.append(five);
+
+ list1.concatByMoving(&list2);
+
+ assert(list1.last == five);
+ assert(list1.len == 5);
+ assert(list2.first == null);
+ assert(list2.last == null);
+ assert(list2.len == 0);
+
+ // Traverse forwards.
+ {
+ var it = list1.first;
+ var index: u32 = 1;
+ while (it) |node| : (it = node.next) {
+ assert(node.data == index);
+ index += 1;
+ }
+ }
+
+ // Traverse backwards.
+ {
+ var it = list1.last;
+ var index: u32 = 1;
+ while (it) |node| : (it = node.prev) {
+ assert(node.data == (6 - index));
+ index += 1;
+ }
+ }
+
+ // Swap them back, this verifies that concating to an empty list works.
+ list2.concatByMoving(&list1);
+
+ // Traverse forwards.
+ {
+ var it = list2.first;
+ var index: u32 = 1;
+ while (it) |node| : (it = node.next) {
+ assert(node.data == index);
+ index += 1;
+ }
+ }
+
+ // Traverse backwards.
+ {
+ var it = list2.last;
+ var index: u32 = 1;
+ while (it) |node| : (it = node.prev) {
+ assert(node.data == (6 - index));
+ index += 1;
+ }
+ }
+}
diff --git a/std/math/index.zig b/std/math/index.zig
index de09a6e944..f37de2505b 100644
--- a/std/math/index.zig
+++ b/std/math/index.zig
@@ -6,6 +6,13 @@ const assert = std.debug.assert;
pub const e = 2.71828182845904523536028747135266249775724709369995;
pub const pi = 3.14159265358979323846264338327950288419716939937510;
+// From a small c++ [program using boost float128](https://github.com/winksaville/cpp_boost_float128)
+pub const f128_true_min = @bitCast(f128, u128(0x00000000000000000000000000000001));
+pub const f128_min = @bitCast(f128, u128(0x00010000000000000000000000000000));
+pub const f128_max = @bitCast(f128, u128(0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
+pub const f128_epsilon = @bitCast(f128, u128(0x3F8F0000000000000000000000000000));
+pub const f128_toint = 1.0 / f128_epsilon;
+
// float.h details
pub const f64_true_min = 4.94065645841246544177e-324;
pub const f64_min = 2.2250738585072014e-308;
@@ -365,6 +372,69 @@ pub fn Log2Int(comptime T: type) type {
return @IntType(false, count);
}
+pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type {
+ assert(from <= to);
+ if (from == 0 and to == 0) {
+ return u0;
+ }
+ const is_signed = from < 0;
+ const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement
+ const base = log2(largest_positive_integer);
+ const upper = (1 << base) - 1;
+ var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1;
+ if (is_signed) {
+ magnitude_bits += 1;
+ }
+ return @IntType(is_signed, magnitude_bits);
+}
+
+test "math.IntFittingRange" {
+ assert(IntFittingRange(0, 0) == u0);
+ assert(IntFittingRange(0, 1) == u1);
+ assert(IntFittingRange(0, 2) == u2);
+ assert(IntFittingRange(0, 3) == u2);
+ assert(IntFittingRange(0, 4) == u3);
+ assert(IntFittingRange(0, 7) == u3);
+ assert(IntFittingRange(0, 8) == u4);
+ assert(IntFittingRange(0, 9) == u4);
+ assert(IntFittingRange(0, 15) == u4);
+ assert(IntFittingRange(0, 16) == u5);
+ assert(IntFittingRange(0, 17) == u5);
+ assert(IntFittingRange(0, 4095) == u12);
+ assert(IntFittingRange(2000, 4095) == u12);
+ assert(IntFittingRange(0, 4096) == u13);
+ assert(IntFittingRange(2000, 4096) == u13);
+ assert(IntFittingRange(0, 4097) == u13);
+ assert(IntFittingRange(2000, 4097) == u13);
+ assert(IntFittingRange(0, 123456789123456798123456789) == u87);
+ assert(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177);
+
+ assert(IntFittingRange(-1, -1) == i1);
+ assert(IntFittingRange(-1, 0) == i1);
+ assert(IntFittingRange(-1, 1) == i2);
+ assert(IntFittingRange(-2, -2) == i2);
+ assert(IntFittingRange(-2, -1) == i2);
+ assert(IntFittingRange(-2, 0) == i2);
+ assert(IntFittingRange(-2, 1) == i2);
+ assert(IntFittingRange(-2, 2) == i3);
+ assert(IntFittingRange(-1, 2) == i3);
+ assert(IntFittingRange(-1, 3) == i3);
+ assert(IntFittingRange(-1, 4) == i4);
+ assert(IntFittingRange(-1, 7) == i4);
+ assert(IntFittingRange(-1, 8) == i5);
+ assert(IntFittingRange(-1, 9) == i5);
+ assert(IntFittingRange(-1, 15) == i5);
+ assert(IntFittingRange(-1, 16) == i6);
+ assert(IntFittingRange(-1, 17) == i6);
+ assert(IntFittingRange(-1, 4095) == i13);
+ assert(IntFittingRange(-4096, 4095) == i13);
+ assert(IntFittingRange(-1, 4096) == i14);
+ assert(IntFittingRange(-4097, 4095) == i14);
+ assert(IntFittingRange(-1, 4097) == i14);
+ assert(IntFittingRange(-1, 123456789123456798123456789) == i88);
+ assert(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178);
+}
+
test "math overflow functions" {
testOverflow();
comptime testOverflow();
diff --git a/std/mem.zig b/std/mem.zig
index 6b37dfe401..fb5f6fd5da 100644
--- a/std/mem.zig
+++ b/std/mem.zig
@@ -410,12 +410,8 @@ test "mem.indexOf" {
/// Reads an integer from memory with size equal to bytes.len.
/// T specifies the return type, which must be large enough to store
/// the result.
-/// See also ::readIntBE or ::readIntLE.
-pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
- if (T.bit_count == 8) {
- return bytes[0];
- }
- var result: T = 0;
+pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.Endian) ReturnType {
+ var result: ReturnType = 0;
switch (endian) {
builtin.Endian.Big => {
for (bytes) |b| {
@@ -423,172 +419,270 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
}
},
builtin.Endian.Little => {
- const ShiftType = math.Log2Int(T);
+ const ShiftType = math.Log2Int(ReturnType);
for (bytes) |b, index| {
- result = result | (T(b) << @intCast(ShiftType, index * 8));
+ result = result | (ReturnType(b) << @intCast(ShiftType, index * 8));
}
},
}
return result;
}
-/// Reads a big-endian int of type T from bytes.
-/// bytes.len must be exactly @sizeOf(T).
-pub fn readIntBE(comptime T: type, bytes: []const u8) T {
- if (T.is_signed) {
- return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes));
- }
- assert(bytes.len == @sizeOf(T));
- if (T == u8) return bytes[0];
- var result: T = 0;
- {
- comptime var i = 0;
- inline while (i < @sizeOf(T)) : (i += 1) {
- result = (result << 8) | T(bytes[i]);
- }
+/// Reads an integer from memory with bit count specified by T.
+/// The bit count of T must be evenly divisible by 8.
+/// This function cannot fail and cannot cause undefined behavior.
+/// Assumes the endianness of memory is native. This means the function can
+/// simply pointer cast memory.
+pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
+ comptime assert(T.bit_count % 8 == 0);
+ return @ptrCast(*align(1) const T, bytes).*;
+}
+
+/// Reads an integer from memory with bit count specified by T.
+/// The bit count of T must be evenly divisible by 8.
+/// This function cannot fail and cannot cause undefined behavior.
+/// Assumes the endianness of memory is foreign, so it must byte-swap.
+pub fn readIntForeign(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
+ return @bswap(T, readIntNative(T, bytes));
+}
+
+pub const readIntLittle = switch (builtin.endian) {
+ builtin.Endian.Little => readIntNative,
+ builtin.Endian.Big => readIntForeign,
+};
+
+pub const readIntBig = switch (builtin.endian) {
+ builtin.Endian.Little => readIntForeign,
+ builtin.Endian.Big => readIntNative,
+};
+
+/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
+/// and ignores extra bytes.
+/// Note that @sizeOf(u24) is 3.
+/// The bit count of T must be evenly divisible by 8.
+/// Assumes the endianness of memory is native. This means the function can
+/// simply pointer cast memory.
+pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
+ assert(@sizeOf(u24) == 3);
+ assert(bytes.len >= @sizeOf(T));
+ // TODO https://github.com/ziglang/zig/issues/863
+ return readIntNative(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr));
+}
+
+/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
+/// and ignores extra bytes.
+/// Note that @sizeOf(u24) is 3.
+/// The bit count of T must be evenly divisible by 8.
+/// Assumes the endianness of memory is foreign, so it must byte-swap.
+pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
+ return @bswap(T, readIntSliceNative(T, bytes));
+}
+
+pub const readIntSliceLittle = switch (builtin.endian) {
+ builtin.Endian.Little => readIntSliceNative,
+ builtin.Endian.Big => readIntSliceForeign,
+};
+
+pub const readIntSliceBig = switch (builtin.endian) {
+ builtin.Endian.Little => readIntSliceForeign,
+ builtin.Endian.Big => readIntSliceNative,
+};
+
+/// Reads an integer from memory with bit count specified by T.
+/// The bit count of T must be evenly divisible by 8.
+/// This function cannot fail and cannot cause undefined behavior.
+pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.Endian) T {
+ if (endian == builtin.endian) {
+ return readIntNative(T, bytes);
+ } else {
+ return readIntForeign(T, bytes);
}
- return result;
}
-/// Reads a little-endian int of type T from bytes.
-/// bytes.len must be exactly @sizeOf(T).
-pub fn readIntLE(comptime T: type, bytes: []const u8) T {
- if (T.is_signed) {
- return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes));
+/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
+/// and ignores extra bytes.
+/// Note that @sizeOf(u24) is 3.
+/// The bit count of T must be evenly divisible by 8.
+pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
+ assert(@sizeOf(u24) == 3);
+ assert(bytes.len >= @sizeOf(T));
+ // TODO https://github.com/ziglang/zig/issues/863
+ return readInt(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr), endian);
+}
+
+test "comptime read/write int" {
+ comptime {
+ var bytes: [2]u8 = undefined;
+ std.mem.writeIntLittle(u16, &bytes, 0x1234);
+ const result = std.mem.readIntBig(u16, &bytes);
+ std.debug.assert(result == 0x3412);
}
- assert(bytes.len == @sizeOf(T));
- if (T == u8) return bytes[0];
- var result: T = 0;
- {
- comptime var i = 0;
- inline while (i < @sizeOf(T)) : (i += 1) {
- result |= T(bytes[i]) << i * 8;
- }
+ comptime {
+ var bytes: [2]u8 = undefined;
+ std.mem.writeIntBig(u16, &bytes, 0x1234);
+ const result = std.mem.readIntLittle(u16, &bytes);
+ std.debug.assert(result == 0x3412);
}
- return result;
}
-test "readIntBE/LE" {
- assert(readIntBE(u0, []u8{}) == 0x0);
- assert(readIntLE(u0, []u8{}) == 0x0);
+test "readIntBig and readIntLittle" {
+ assert(readIntSliceBig(u0, []u8{}) == 0x0);
+ assert(readIntSliceLittle(u0, []u8{}) == 0x0);
- assert(readIntBE(u8, []u8{0x32}) == 0x32);
- assert(readIntLE(u8, []u8{0x12}) == 0x12);
+ assert(readIntSliceBig(u8, []u8{0x32}) == 0x32);
+ assert(readIntSliceLittle(u8, []u8{0x12}) == 0x12);
- assert(readIntBE(u16, []u8{0x12, 0x34}) == 0x1234);
- assert(readIntLE(u16, []u8{0x12, 0x34}) == 0x3412);
+ assert(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234);
+ assert(readIntSliceLittle(u16, []u8{ 0x12, 0x34 }) == 0x3412);
- assert(readIntBE(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
- assert(readIntLE(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
+ assert(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
+ assert(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
- assert(readIntBE(i8, []u8{0xff}) == -1);
- assert(readIntLE(i8, []u8{0xfe}) == -2);
+ assert(readIntSliceBig(i8, []u8{0xff}) == -1);
+ assert(readIntSliceLittle(i8, []u8{0xfe}) == -2);
- assert(readIntBE(i16, []u8{0xff, 0xfd}) == -3);
- assert(readIntLE(i16, []u8{0xfc, 0xff}) == -4);
+ assert(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3);
+ assert(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4);
}
-/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes
-/// to fill the entire buffer provided.
-/// value must be an integer.
-pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {
- const uint = @IntType(false, @typeOf(value).bit_count);
- var bits = @truncate(uint, value);
- switch (endian) {
- builtin.Endian.Big => {
- var index: usize = buf.len;
- while (index != 0) {
- index -= 1;
+/// Writes an integer to memory, storing it in twos-complement.
+/// This function always succeeds, has defined behavior for all inputs, and
+/// accepts any integer bit width.
+/// This function stores in native endian, which means it is implemented as a simple
+/// memory store.
+pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
+ @ptrCast(*align(1) T, buf).* = value;
+}
- buf[index] = @truncate(u8, bits);
- bits >>= 8;
- }
- },
- builtin.Endian.Little => {
- for (buf) |*b| {
- b.* = @truncate(u8, bits);
- bits >>= 8;
- }
- },
+/// Writes an integer to memory, storing it in twos-complement.
+/// This function always succeeds, has defined behavior for all inputs, but
+/// the integer bit width must be divisible by 8.
+/// This function stores in foreign endian, which means it does a @bswap first.
+pub fn writeIntForeign(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
+ writeIntNative(T, buf, @bswap(T, value));
+}
+
+pub const writeIntLittle = switch (builtin.endian) {
+ builtin.Endian.Little => writeIntNative,
+ builtin.Endian.Big => writeIntForeign,
+};
+
+pub const writeIntBig = switch (builtin.endian) {
+ builtin.Endian.Little => writeIntForeign,
+ builtin.Endian.Big => writeIntNative,
+};
+
+/// Writes an integer to memory, storing it in twos-complement.
+/// This function always succeeds, has defined behavior for all inputs, but
+/// the integer bit width must be divisible by 8.
+pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: builtin.Endian) void {
+ comptime assert(T.bit_count % 8 == 0);
+ if (endian == builtin.endian) {
+ return writeIntNative(T, buffer, value);
+ } else {
+ return writeIntForeign(T, buffer, value);
}
- assert(bits == 0);
}
-pub fn writeIntBE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
- assert(T.bit_count % 8 == 0);
+/// Writes a twos-complement little-endian integer to memory.
+/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
+/// The bit count of T must be divisible by 8.
+/// Any extra bytes in buffer after writing the integer are set to zero. To
+/// avoid the branch to check for extra buffer bytes, use writeIntLittle
+/// instead.
+pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
+ comptime assert(@sizeOf(u24) == 3);
+ comptime assert(T.bit_count % 8 == 0);
+ assert(buffer.len >= @sizeOf(T));
+
+ // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
const uint = @IntType(false, T.bit_count);
- if (uint == u0) {
- return;
- }
- var bits = @bitCast(uint, value);
- if (uint == u8) {
- buf[0] = bits;
- return;
+ var bits = @truncate(uint, value);
+ for (buffer) |*b| {
+ b.* = @truncate(u8, bits);
+ bits >>= 8;
}
- var index: usize = buf.len;
+}
+
+/// Writes a twos-complement big-endian integer to memory.
+/// Asserts that buffer.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
+/// The bit count of T must be divisible by 8.
+/// Any extra bytes in buffer before writing the integer are set to zero. To
+/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.
+pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
+ comptime assert(@sizeOf(u24) == 3);
+ comptime assert(T.bit_count % 8 == 0);
+ assert(buffer.len >= @sizeOf(T));
+
+ // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
+ const uint = @IntType(false, T.bit_count);
+ var bits = @truncate(uint, value);
+ var index: usize = buffer.len;
while (index != 0) {
index -= 1;
-
- buf[index] = @truncate(u8, bits);
+ buffer[index] = @truncate(u8, bits);
bits >>= 8;
}
- assert(bits == 0);
}
-pub fn writeIntLE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
- assert(T.bit_count % 8 == 0);
- const uint = @IntType(false, T.bit_count);
- if (uint == u0) {
- return;
- }
- var bits = @bitCast(uint, value);
- if (uint == u8) {
- buf[0] = bits;
- return;
- }
- // FIXME: this should just be for (buf).
- // See https://github.com/ziglang/zig/issues/1663
- for (buf.*) |*b| {
- b.* = @truncate(u8, bits);
- bits >>= 8;
+pub const writeIntSliceNative = switch (builtin.endian) {
+ builtin.Endian.Little => writeIntSliceLittle,
+ builtin.Endian.Big => writeIntSliceBig,
+};
+
+pub const writeIntSliceForeign = switch (builtin.endian) {
+ builtin.Endian.Little => writeIntSliceBig,
+ builtin.Endian.Big => writeIntSliceLittle,
+};
+
+/// Writes a twos-complement integer to memory, with the specified endianness.
+/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
+/// The bit count of T must be evenly divisible by 8.
+/// Any extra bytes in buffer not part of the integer are set to zero, with
+/// respect to endianness. To avoid the branch to check for extra buffer bytes,
+/// use writeInt instead.
+pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void {
+ comptime assert(T.bit_count % 8 == 0);
+ switch (endian) {
+ builtin.Endian.Little => return writeIntSliceLittle(T, buffer, value),
+ builtin.Endian.Big => return writeIntSliceBig(T, buffer, value),
}
- assert(bits == 0);
}
-test "writeIntBE/LE" {
+test "writeIntBig and writeIntLittle" {
var buf0: [0]u8 = undefined;
var buf1: [1]u8 = undefined;
var buf2: [2]u8 = undefined;
var buf9: [9]u8 = undefined;
- writeIntBE(u0, &buf0, 0x0);
+ writeIntBig(u0, &buf0, 0x0);
assert(eql_slice_u8(buf0[0..], []u8{}));
- writeIntLE(u0, &buf0, 0x0);
+ writeIntLittle(u0, &buf0, 0x0);
assert(eql_slice_u8(buf0[0..], []u8{}));
- writeIntBE(u8, &buf1, 0x12);
+ writeIntBig(u8, &buf1, 0x12);
assert(eql_slice_u8(buf1[0..], []u8{0x12}));
- writeIntLE(u8, &buf1, 0x34);
+ writeIntLittle(u8, &buf1, 0x34);
assert(eql_slice_u8(buf1[0..], []u8{0x34}));
- writeIntBE(u16, &buf2, 0x1234);
+ writeIntBig(u16, &buf2, 0x1234);
assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
- writeIntLE(u16, &buf2, 0x5678);
+ writeIntLittle(u16, &buf2, 0x5678);
assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
- writeIntBE(u72, &buf9, 0x123456789abcdef024);
+ writeIntBig(u72, &buf9, 0x123456789abcdef024);
assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
- writeIntLE(u72, &buf9, 0xfedcba9876543210ec);
+ writeIntLittle(u72, &buf9, 0xfedcba9876543210ec);
assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
- writeIntBE(i8, &buf1, -1);
+ writeIntBig(i8, &buf1, -1);
assert(eql_slice_u8(buf1[0..], []u8{0xff}));
- writeIntLE(i8, &buf1, -2);
+ writeIntLittle(i8, &buf1, -2);
assert(eql_slice_u8(buf1[0..], []u8{0xfe}));
- writeIntBE(i16, &buf2, -3);
+ writeIntBig(i16, &buf2, -3);
assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
- writeIntLE(i16, &buf2, -4);
+ writeIntLittle(i16, &buf2, -4);
assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
}
@@ -737,12 +831,12 @@ fn testReadIntImpl() void {
0x56,
0x78,
};
- assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
- assert(readIntBE(u32, bytes) == 0x12345678);
- assert(readIntBE(i32, bytes) == 0x12345678);
- assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412);
- assert(readIntLE(u32, bytes) == 0x78563412);
- assert(readIntLE(i32, bytes) == 0x78563412);
+ assert(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678);
+ assert(readIntBig(u32, &bytes) == 0x12345678);
+ assert(readIntBig(i32, &bytes) == 0x12345678);
+ assert(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412);
+ assert(readIntLittle(u32, &bytes) == 0x78563412);
+ assert(readIntLittle(i32, &bytes) == 0x78563412);
}
{
const buf = []u8{
@@ -751,7 +845,7 @@ fn testReadIntImpl() void {
0x12,
0x34,
};
- const answer = readInt(buf, u64, builtin.Endian.Big);
+ const answer = readInt(u32, &buf, builtin.Endian.Big);
assert(answer == 0x00001234);
}
{
@@ -761,7 +855,7 @@ fn testReadIntImpl() void {
0x00,
0x00,
};
- const answer = readInt(buf, u64, builtin.Endian.Little);
+ const answer = readInt(u32, &buf, builtin.Endian.Little);
assert(answer == 0x00003412);
}
{
@@ -769,21 +863,33 @@ fn testReadIntImpl() void {
0xff,
0xfe,
};
- assert(readIntBE(u16, bytes) == 0xfffe);
- assert(readIntBE(i16, bytes) == -0x0002);
- assert(readIntLE(u16, bytes) == 0xfeff);
- assert(readIntLE(i16, bytes) == -0x0101);
+ assert(readIntBig(u16, &bytes) == 0xfffe);
+ assert(readIntBig(i16, &bytes) == -0x0002);
+ assert(readIntLittle(u16, &bytes) == 0xfeff);
+ assert(readIntLittle(i16, &bytes) == -0x0101);
}
}
-test "testWriteInt" {
+test "std.mem.writeIntSlice" {
testWriteIntImpl();
comptime testWriteIntImpl();
}
fn testWriteIntImpl() void {
var bytes: [8]u8 = undefined;
- writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big);
+ writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big);
+ assert(eql(u8, bytes, []u8{
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ }));
+
+ writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little);
+ assert(eql(u8, bytes, []u8{
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ }));
+
+ writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big);
assert(eql(u8, bytes, []u8{
0x12,
0x34,
@@ -795,7 +901,7 @@ fn testWriteIntImpl() void {
0xBE,
}));
- writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little);
+ writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little);
assert(eql(u8, bytes, []u8{
0x12,
0x34,
@@ -807,7 +913,7 @@ fn testWriteIntImpl() void {
0xBE,
}));
- writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
+ writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big);
assert(eql(u8, bytes, []u8{
0x00,
0x00,
@@ -819,7 +925,7 @@ fn testWriteIntImpl() void {
0x78,
}));
- writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);
+ writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little);
assert(eql(u8, bytes, []u8{
0x12,
0x34,
@@ -831,7 +937,7 @@ fn testWriteIntImpl() void {
0x00,
}));
- writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);
+ writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big);
assert(eql(u8, bytes, []u8{
0x00,
0x00,
@@ -843,7 +949,7 @@ fn testWriteIntImpl() void {
0x34,
}));
- writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);
+ writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little);
assert(eql(u8, bytes, []u8{
0x34,
0x12,
@@ -941,29 +1047,52 @@ test "std.mem.rotate" {
}));
}
-// TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by
-// endian-casting the pointer and then dereferencing
+/// Converts a little-endian integer to host endianness.
+pub fn littleToNative(comptime T: type, x: T) T {
+ return switch (builtin.endian) {
+ builtin.Endian.Little => x,
+ builtin.Endian.Big => @bswap(T, x),
+ };
+}
-pub fn endianSwapIfLe(comptime T: type, x: T) T {
- return endianSwapIf(builtin.Endian.Little, T, x);
+/// Converts a big-endian integer to host endianness.
+pub fn bigToNative(comptime T: type, x: T) T {
+ return switch (builtin.endian) {
+ builtin.Endian.Little => @bswap(T, x),
+ builtin.Endian.Big => x,
+ };
}
-pub fn endianSwapIfBe(comptime T: type, x: T) T {
- return endianSwapIf(builtin.Endian.Big, T, x);
+/// Converts an integer from specified endianness to host endianness.
+pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T {
+ return switch (endianness_of_x) {
+ builtin.Endian.Little => littleToNative(T, x),
+ builtin.Endian.Big => bigToNative(T, x),
+ };
}
-pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T {
- return if (builtin.endian == endian) endianSwap(T, x) else x;
+/// Converts an integer which has host endianness to the desired endianness.
+pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T {
+ return switch (desired_endianness) {
+ builtin.Endian.Little => nativeToLittle(T, x),
+ builtin.Endian.Big => nativeToBig(T, x),
+ };
}
-pub fn endianSwap(comptime T: type, x: T) T {
- var buf: [@sizeOf(T)]u8 = undefined;
- mem.writeInt(buf[0..], x, builtin.Endian.Little);
- return mem.readInt(buf, T, builtin.Endian.Big);
+/// Converts an integer which has host endianness to little endian.
+pub fn nativeToLittle(comptime T: type, x: T) T {
+ return switch (builtin.endian) {
+ builtin.Endian.Little => x,
+ builtin.Endian.Big => @bswap(T, x),
+ };
}
-test "std.mem.endianSwap" {
- assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE);
+/// Converts an integer which has host endianness to big endian.
+pub fn nativeToBig(comptime T: type, x: T) T {
+ return switch (builtin.endian) {
+ builtin.Endian.Little => @bswap(T, x),
+ builtin.Endian.Big => x,
+ };
}
fn AsBytesReturnType(comptime P: type) type {
diff --git a/std/meta/index.zig b/std/meta/index.zig
index 20e66fbe3d..69a3097288 100644
--- a/std/meta/index.zig
+++ b/std/meta/index.zig
@@ -76,6 +76,25 @@ test "std.meta.tagName" {
debug.assert(mem.eql(u8, tagName(u2b), "D"));
}
+pub fn stringToEnum(comptime T: type, str: []const u8) ?T {
+ inline for (@typeInfo(T).Enum.fields) |enumField| {
+ if (std.mem.eql(u8, str, enumField.name)) {
+ return @field(T, enumField.name);
+ }
+ }
+ return null;
+}
+
+test "std.meta.stringToEnum" {
+ const E1 = enum {
+ A,
+ B,
+ };
+ debug.assert(E1.A == stringToEnum(E1, "A").?);
+ debug.assert(E1.B == stringToEnum(E1, "B").?);
+ debug.assert(null == stringToEnum(E1, "C"));
+}
+
pub fn bitCount(comptime T: type) u32 {
return switch (@typeInfo(T)) {
TypeId.Int => |info| info.bits,
@@ -483,3 +502,32 @@ test "std.meta.eql" {
debug.assert(eql(EU.tst(false), EU.tst(false)));
debug.assert(!eql(EU.tst(false), EU.tst(true)));
}
+
+test "intToEnum with error return" {
+ const E1 = enum {
+ A,
+ };
+ const E2 = enum {
+ A,
+ B,
+ };
+
+ var zero: u8 = 0;
+ var one: u16 = 1;
+ debug.assert(intToEnum(E1, zero) catch unreachable == E1.A);
+ debug.assert(intToEnum(E2, one) catch unreachable == E2.B);
+ debug.assertError(intToEnum(E1, one), error.InvalidEnumTag);
+}
+
+pub const IntToEnumError = error{InvalidEnumTag};
+
+pub fn intToEnum(comptime Tag: type, tag_int: var) IntToEnumError!Tag {
+ comptime var i = 0;
+ inline while (i != @memberCount(Tag)) : (i += 1) {
+ const this_tag_value = @field(Tag, @memberName(Tag, i));
+ if (tag_int == @enumToInt(this_tag_value)) {
+ return this_tag_value;
+ }
+ }
+ return error.InvalidEnumTag;
+}
diff --git a/std/net.zig b/std/net.zig
index 006a9d4ac5..968c1f019f 100644
--- a/std/net.zig
+++ b/std/net.zig
@@ -23,7 +23,7 @@ pub const Address = struct {
.os_addr = posix.sockaddr{
.in = posix.sockaddr_in{
.family = posix.AF_INET,
- .port = std.mem.endianSwapIfLe(u16, _port),
+ .port = mem.nativeToBig(u16, _port),
.addr = ip4,
.zero = []u8{0} ** 8,
},
@@ -37,7 +37,7 @@ pub const Address = struct {
.os_addr = posix.sockaddr{
.in6 = posix.sockaddr_in6{
.family = posix.AF_INET6,
- .port = std.mem.endianSwapIfLe(u16, _port),
+ .port = mem.nativeToBig(u16, _port),
.flowinfo = 0,
.addr = ip6.addr,
.scope_id = ip6.scope_id,
@@ -47,7 +47,7 @@ pub const Address = struct {
}
pub fn port(self: Address) u16 {
- return std.mem.endianSwapIfLe(u16, self.os_addr.in.port);
+ return mem.bigToNative(u16, self.os_addr.in.port);
}
pub fn initPosix(addr: posix.sockaddr) Address {
@@ -57,12 +57,12 @@ pub const Address = struct {
pub fn format(self: *const Address, out_stream: var) !void {
switch (self.os_addr.in.family) {
posix.AF_INET => {
- const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in.port);
+ const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port);
const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
},
posix.AF_INET6 => {
- const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in6.port);
+ const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port);
try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
},
else => try out_stream.write("(unrecognized address family)"),
@@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr {
}
test "std.net.parseIp4" {
- assert((try parseIp4("127.0.0.1")) == std.mem.endianSwapIfLe(u32, 0x7f000001));
+ assert((try parseIp4("127.0.0.1")) == mem.bigToNative(u32, 0x7f000001));
testParseIp4Fail("256.0.0.1", error.Overflow);
testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
diff --git a/std/os/child_process.zig b/std/os/child_process.zig
index 9361d78829..0aa896ff1b 100644
--- a/std/os/child_process.zig
+++ b/std/os/child_process.zig
@@ -390,6 +390,19 @@ pub const ChildProcess = struct {
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.stdin_behavior == StdIo.Pipe) {
+ os.close(stdin_pipe[0]);
+ os.close(stdin_pipe[1]);
+ }
+ if (self.stdout_behavior == StdIo.Pipe) {
+ os.close(stdout_pipe[0]);
+ os.close(stdout_pipe[1]);
+ }
+ if (self.stderr_behavior == StdIo.Pipe) {
+ os.close(stderr_pipe[0]);
+ os.close(stderr_pipe[1]);
+ }
+
if (self.cwd) |cwd| {
os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err);
}
@@ -794,10 +807,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
fn writeIntFd(fd: i32, value: ErrInt) !void {
const stream = &os.File.openHandle(fd).outStream().stream;
- stream.writeIntNe(ErrInt, value) catch return error.SystemResources;
+ stream.writeIntNative(ErrInt, value) catch return error.SystemResources;
}
fn readIntFd(fd: i32) !ErrInt {
const stream = &os.File.openHandle(fd).inStream().stream;
- return stream.readIntNe(ErrInt) catch return error.SystemResources;
+ return stream.readIntNative(ErrInt) catch return error.SystemResources;
}
diff --git a/std/os/file.zig b/std/os/file.zig
index 962428d4ca..2ae547c694 100644
--- a/std/os/file.zig
+++ b/std/os/file.zig
@@ -228,9 +228,16 @@ pub const File = struct {
return os.isTty(self.handle);
}
- pub fn seekForward(self: File, amount: isize) !void {
+ pub const SeekError = error{
+ /// TODO make this error impossible to get
+ Overflow,
+ Unseekable,
+ Unexpected,
+ };
+
+ pub fn seekForward(self: File, amount: isize) SeekError!void {
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);
const err = posix.getErrno(result);
if (err > 0) {
@@ -259,9 +266,9 @@ pub const File = struct {
}
}
- pub fn seekTo(self: File, pos: usize) !void {
+ pub fn seekTo(self: File, pos: usize) SeekError!void {
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
const ipos = try math.cast(isize, pos);
const result = posix.lseek(self.handle, ipos, posix.SEEK_SET);
const err = posix.getErrno(result);
@@ -293,9 +300,16 @@ pub const File = struct {
}
}
- pub fn getPos(self: File) !usize {
+ pub const GetSeekPosError = error{
+ Overflow,
+ SystemResources,
+ Unseekable,
+ Unexpected,
+ };
+
+ pub fn getPos(self: File) GetSeekPosError!usize {
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);
const err = posix.getErrno(result);
if (err > 0) {
@@ -323,13 +337,13 @@ pub const File = struct {
}
assert(pos >= 0);
- return math.cast(usize, pos) catch error.FilePosLargerThanPointerRange;
+ return math.cast(usize, pos);
},
else => @compileError("unsupported OS"),
}
}
- pub fn getEndPos(self: File) !usize {
+ pub fn getEndPos(self: File) GetSeekPosError!usize {
if (is_posix) {
const stat = try os.posixFStat(self.handle);
return @intCast(usize, stat.size);
@@ -431,6 +445,18 @@ pub const File = struct {
};
}
+ pub fn seekableStream(file: File) SeekableStream {
+ return SeekableStream{
+ .file = file,
+ .stream = SeekableStream.Stream{
+ .seekToFn = SeekableStream.seekToFn,
+ .seekForwardFn = SeekableStream.seekForwardFn,
+ .getPosFn = SeekableStream.getPosFn,
+ .getEndPosFn = SeekableStream.getEndPosFn,
+ },
+ };
+ }
+
/// Implementation of io.InStream trait for File
pub const InStream = struct {
file: File,
@@ -458,4 +484,32 @@ pub const File = struct {
return self.file.write(bytes);
}
};
+
+ /// Implementation of io.SeekableStream trait for File
+ pub const SeekableStream = struct {
+ file: File,
+ stream: Stream,
+
+ pub const Stream = io.SeekableStream(SeekError, GetSeekPosError);
+
+ pub fn seekToFn(seekable_stream: *Stream, pos: usize) SeekError!void {
+ const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
+ return self.file.seekTo(pos);
+ }
+
+ pub fn seekForwardFn(seekable_stream: *Stream, amt: isize) SeekError!void {
+ const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
+ return self.file.seekForward(amt);
+ }
+
+ pub fn getEndPosFn(seekable_stream: *Stream) GetSeekPosError!usize {
+ const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
+ return self.file.getEndPos();
+ }
+
+ pub fn getPosFn(seekable_stream: *Stream) GetSeekPosError!usize {
+ const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
+ return self.file.getPos();
+ }
+ };
};
diff --git a/std/os/freebsd/errno.zig b/std/os/freebsd/errno.zig
new file mode 100644
index 0000000000..0a0d825f5a
--- /dev/null
+++ b/std/os/freebsd/errno.zig
@@ -0,0 +1,121 @@
+pub const EPERM = 1; // Operation not permitted
+pub const ENOENT = 2; // No such file or directory
+pub const ESRCH = 3; // No such process
+pub const EINTR = 4; // Interrupted system call
+pub const EIO = 5; // Input/output error
+pub const ENXIO = 6; // Device not configured
+pub const E2BIG = 7; // Argument list too long
+pub const ENOEXEC = 8; // Exec format error
+pub const EBADF = 9; // Bad file descriptor
+pub const ECHILD = 10; // No child processes
+pub const EDEADLK = 11; // Resource deadlock avoided
+// 11 was EAGAIN
+pub const ENOMEM = 12; // Cannot allocate memory
+pub const EACCES = 13; // Permission denied
+pub const EFAULT = 14; // Bad address
+pub const ENOTBLK = 15; // Block device required
+pub const EBUSY = 16; // Device busy
+pub const EEXIST = 17; // File exists
+pub const EXDEV = 18; // Cross-device link
+pub const ENODEV = 19; // Operation not supported by device
+pub const ENOTDIR = 20; // Not a directory
+pub const EISDIR = 21; // Is a directory
+pub const EINVAL = 22; // Invalid argument
+pub const ENFILE = 23; // Too many open files in system
+pub const EMFILE = 24; // Too many open files
+pub const ENOTTY = 25; // Inappropriate ioctl for device
+pub const ETXTBSY = 26; // Text file busy
+pub const EFBIG = 27; // File too large
+pub const ENOSPC = 28; // No space left on device
+pub const ESPIPE = 29; // Illegal seek
+pub const EROFS = 30; // Read-only filesystem
+pub const EMLINK = 31; // Too many links
+pub const EPIPE = 32; // Broken pipe
+
+// math software
+pub const EDOM = 33; // Numerical argument out of domain
+pub const ERANGE = 34; // Result too large
+
+// non-blocking and interrupt i/o
+pub const EAGAIN = 35; // Resource temporarily unavailable
+pub const EWOULDBLOCK = EAGAIN; // Operation would block
+pub const EINPROGRESS = 36; // Operation now in progress
+pub const EALREADY = 37; // Operation already in progress
+
+// ipc/network software -- argument errors
+pub const ENOTSOCK = 38; // Socket operation on non-socket
+pub const EDESTADDRREQ = 39; // Destination address required
+pub const EMSGSIZE = 40; // Message too long
+pub const EPROTOTYPE = 41; // Protocol wrong type for socket
+pub const ENOPROTOOPT = 42; // Protocol not available
+pub const EPROTONOSUPPORT = 43; // Protocol not supported
+pub const ESOCKTNOSUPPORT = 44; // Socket type not supported
+pub const EOPNOTSUPP = 45; // Operation not supported
+pub const ENOTSUP = EOPNOTSUPP; // Operation not supported
+pub const EPFNOSUPPORT = 46; // Protocol family not supported
+pub const EAFNOSUPPORT = 47; // Address family not supported by protocol family
+pub const EADDRINUSE = 48; // Address already in use
+pub const EADDRNOTAVAIL = 49; // Can't assign requested address
+
+// ipc/network software -- operational errors
+pub const ENETDOWN = 50; // Network is down
+pub const ENETUNREACH = 51; // Network is unreachable
+pub const ENETRESET = 52; // Network dropped connection on reset
+pub const ECONNABORTED = 53; // Software caused connection abort
+pub const ECONNRESET = 54; // Connection reset by peer
+pub const ENOBUFS = 55; // No buffer space available
+pub const EISCONN = 56; // Socket is already connected
+pub const ENOTCONN = 57; // Socket is not connected
+pub const ESHUTDOWN = 58; // Can't send after socket shutdown
+pub const ETOOMANYREFS = 59; // Too many references: can't splice
+pub const ETIMEDOUT = 60; // Operation timed out
+pub const ECONNREFUSED = 61; // Connection refused
+
+pub const ELOOP = 62; // Too many levels of symbolic links
+pub const ENAMETOOLONG = 63; // File name too long
+
+// should be rearranged
+pub const EHOSTDOWN = 64; // Host is down
+pub const EHOSTUNREACH = 65; // No route to host
+pub const ENOTEMPTY = 66; // Directory not empty
+
+// quotas & mush
+pub const EPROCLIM = 67; // Too many processes
+pub const EUSERS = 68; // Too many users
+pub const EDQUOT = 69; // Disc quota exceeded
+
+// Network File System
+pub const ESTALE = 70; // Stale NFS file handle
+pub const EREMOTE = 71; // Too many levels of remote in path
+pub const EBADRPC = 72; // RPC struct is bad
+pub const ERPCMISMATCH = 73; // RPC version wrong
+pub const EPROGUNAVAIL = 74; // RPC prog. not avail
+pub const EPROGMISMATCH = 75; // Program version wrong
+pub const EPROCUNAVAIL = 76; // Bad procedure for program
+
+pub const ENOLCK = 77; // No locks available
+pub const ENOSYS = 78; // Function not implemented
+
+pub const EFTYPE = 79; // Inappropriate file type or format
+pub const EAUTH = 80; // Authentication error
+pub const ENEEDAUTH = 81; // Need authenticator
+pub const EIDRM = 82; // Identifier removed
+pub const ENOMSG = 83; // No message of desired type
+pub const EOVERFLOW = 84; // Value too large to be stored in data type
+pub const ECANCELED = 85; // Operation canceled
+pub const EILSEQ = 86; // Illegal byte sequence
+pub const ENOATTR = 87; // Attribute not found
+
+pub const EDOOFUS = 88; // Programming error
+
+pub const EBADMSG = 89; // Bad message
+pub const EMULTIHOP = 90; // Multihop attempted
+pub const ENOLINK = 91; // Link has been severed
+pub const EPROTO = 92; // Protocol error
+
+pub const ENOTCAPABLE = 93; // Capabilities insufficient
+pub const ECAPMODE = 94; // Not permitted in capability mode
+pub const ENOTRECOVERABLE = 95; // State not recoverable
+pub const EOWNERDEAD = 96; // Previous owner died
+
+pub const ELAST = 96; // Must be equal largest errno
diff --git a/std/os/freebsd/index.zig b/std/os/freebsd/index.zig
new file mode 100644
index 0000000000..34a3414a48
--- /dev/null
+++ b/std/os/freebsd/index.zig
@@ -0,0 +1,801 @@
+const assert = @import("../debug.zig").assert;
+const builtin = @import("builtin");
+const arch = switch (builtin.arch) {
+ builtin.Arch.x86_64 => @import("x86_64.zig"),
+ else => @compileError("unsupported arch"),
+};
+pub use @import("syscall.zig");
+pub use @import("errno.zig");
+
+const std = @import("../../index.zig");
+const c = std.c;
+const maxInt = std.math.maxInt;
+pub const Kevent = c.Kevent;
+
+pub const PATH_MAX = 1024;
+
+pub const STDIN_FILENO = 0;
+pub const STDOUT_FILENO = 1;
+pub const STDERR_FILENO = 2;
+
+pub const PROT_NONE = 0;
+pub const PROT_READ = 1;
+pub const PROT_WRITE = 2;
+pub const PROT_EXEC = 4;
+
+pub const MAP_FAILED = maxInt(usize);
+pub const MAP_SHARED = 0x0001;
+pub const MAP_PRIVATE = 0x0002;
+pub const MAP_FIXED = 0x0010;
+pub const MAP_STACK = 0x0400;
+pub const MAP_NOSYNC = 0x0800;
+pub const MAP_ANON = 0x1000;
+pub const MAP_ANONYMOUS = MAP_ANON;
+pub const MAP_FILE = 0;
+pub const MAP_NORESERVE = 0;
+
+pub const MAP_GUARD = 0x00002000;
+pub const MAP_EXCL = 0x00004000;
+pub const MAP_NOCORE = 0x00020000;
+pub const MAP_PREFAULT_READ = 0x00040000;
+pub const MAP_32BIT = 0x00080000;
+
+pub const WNOHANG = 1;
+pub const WUNTRACED = 2;
+pub const WSTOPPED = WUNTRACED;
+pub const WCONTINUED = 4;
+pub const WNOWAIT = 8;
+pub const WEXITED = 16;
+pub const WTRAPPED = 32;
+
+pub const SA_ONSTACK = 0x0001;
+pub const SA_RESTART = 0x0002;
+pub const SA_RESETHAND = 0x0004;
+pub const SA_NOCLDSTOP = 0x0008;
+pub const SA_NODEFER = 0x0010;
+pub const SA_NOCLDWAIT = 0x0020;
+pub const SA_SIGINFO = 0x0040;
+
+pub const SIGHUP = 1;
+pub const SIGINT = 2;
+pub const SIGQUIT = 3;
+pub const SIGILL = 4;
+pub const SIGTRAP = 5;
+pub const SIGABRT = 6;
+pub const SIGIOT = SIGABRT;
+pub const SIGEMT = 7;
+pub const SIGFPE = 8;
+pub const SIGKILL = 9;
+pub const SIGBUS = 10;
+pub const SIGSEGV = 11;
+pub const SIGSYS = 12;
+pub const SIGPIPE = 13;
+pub const SIGALRM = 14;
+pub const SIGTERM = 15;
+pub const SIGURG = 16;
+pub const SIGSTOP = 17;
+pub const SIGTSTP = 18;
+pub const SIGCONT = 19;
+pub const SIGCHLD = 20;
+pub const SIGTTIN = 21;
+pub const SIGTTOU = 22;
+pub const SIGIO = 23;
+pub const SIGXCPU = 24;
+pub const SIGXFSZ = 25;
+pub const SIGVTALRM = 26;
+pub const SIGPROF = 27;
+pub const SIGWINCH = 28;
+pub const SIGINFO = 29;
+pub const SIGUSR1 = 30;
+pub const SIGUSR2 = 31;
+pub const SIGTHR = 32;
+pub const SIGLWP = SIGTHR;
+pub const SIGLIBRT = 33;
+
+pub const SIGRTMIN = 65;
+pub const SIGRTMAX = 126;
+
+pub const O_RDONLY = 0o0;
+pub const O_WRONLY = 0o1;
+pub const O_RDWR = 0o2;
+pub const O_ACCMODE = 0o3;
+
+pub const O_CREAT = 0o100;
+pub const O_EXCL = 0o200;
+pub const O_NOCTTY = 0o400;
+pub const O_TRUNC = 0o1000;
+pub const O_APPEND = 0o2000;
+pub const O_NONBLOCK = 0o4000;
+pub const O_DSYNC = 0o10000;
+pub const O_SYNC = 0o4010000;
+pub const O_RSYNC = 0o4010000;
+pub const O_DIRECTORY = 0o200000;
+pub const O_NOFOLLOW = 0o400000;
+pub const O_CLOEXEC = 0o2000000;
+
+pub const O_ASYNC = 0o20000;
+pub const O_DIRECT = 0o40000;
+pub const O_LARGEFILE = 0;
+pub const O_NOATIME = 0o1000000;
+pub const O_PATH = 0o10000000;
+pub const O_TMPFILE = 0o20200000;
+pub const O_NDELAY = O_NONBLOCK;
+
+pub const F_DUPFD = 0;
+pub const F_GETFD = 1;
+pub const F_SETFD = 2;
+pub const F_GETFL = 3;
+pub const F_SETFL = 4;
+
+pub const F_SETOWN = 8;
+pub const F_GETOWN = 9;
+pub const F_SETSIG = 10;
+pub const F_GETSIG = 11;
+
+pub const F_GETLK = 5;
+pub const F_SETLK = 6;
+pub const F_SETLKW = 7;
+
+pub const F_SETOWN_EX = 15;
+pub const F_GETOWN_EX = 16;
+
+pub const F_GETOWNER_UIDS = 17;
+
+pub const SEEK_SET = 0;
+pub const SEEK_CUR = 1;
+pub const SEEK_END = 2;
+
+pub const SIG_BLOCK = 1;
+pub const SIG_UNBLOCK = 2;
+pub const SIG_SETMASK = 3;
+
+pub const SOCK_STREAM = 1;
+pub const SOCK_DGRAM = 2;
+pub const SOCK_RAW = 3;
+pub const SOCK_RDM = 4;
+pub const SOCK_SEQPACKET = 5;
+
+pub const SOCK_CLOEXEC = 0x10000000;
+pub const SOCK_NONBLOCK = 0x20000000;
+
+pub const PROTO_ip = 0o000;
+pub const PROTO_icmp = 0o001;
+pub const PROTO_igmp = 0o002;
+pub const PROTO_ggp = 0o003;
+pub const PROTO_ipencap = 0o004;
+pub const PROTO_st = 0o005;
+pub const PROTO_tcp = 0o006;
+pub const PROTO_egp = 0o010;
+pub const PROTO_pup = 0o014;
+pub const PROTO_udp = 0o021;
+pub const PROTO_hmp = 0o024;
+pub const PROTO_xns_idp = 0o026;
+pub const PROTO_rdp = 0o033;
+pub const PROTO_iso_tp4 = 0o035;
+pub const PROTO_xtp = 0o044;
+pub const PROTO_ddp = 0o045;
+pub const PROTO_idpr_cmtp = 0o046;
+pub const PROTO_ipv6 = 0o051;
+pub const PROTO_ipv6_route = 0o053;
+pub const PROTO_ipv6_frag = 0o054;
+pub const PROTO_idrp = 0o055;
+pub const PROTO_rsvp = 0o056;
+pub const PROTO_gre = 0o057;
+pub const PROTO_esp = 0o062;
+pub const PROTO_ah = 0o063;
+pub const PROTO_skip = 0o071;
+pub const PROTO_ipv6_icmp = 0o072;
+pub const PROTO_ipv6_nonxt = 0o073;
+pub const PROTO_ipv6_opts = 0o074;
+pub const PROTO_rspf = 0o111;
+pub const PROTO_vmtp = 0o121;
+pub const PROTO_ospf = 0o131;
+pub const PROTO_ipip = 0o136;
+pub const PROTO_encap = 0o142;
+pub const PROTO_pim = 0o147;
+pub const PROTO_raw = 0o377;
+
+pub const PF_UNSPEC = 0;
+pub const PF_LOCAL = 1;
+pub const PF_UNIX = PF_LOCAL;
+pub const PF_FILE = PF_LOCAL;
+pub const PF_INET = 2;
+pub const PF_AX25 = 3;
+pub const PF_IPX = 4;
+pub const PF_APPLETALK = 5;
+pub const PF_NETROM = 6;
+pub const PF_BRIDGE = 7;
+pub const PF_ATMPVC = 8;
+pub const PF_X25 = 9;
+pub const PF_INET6 = 10;
+pub const PF_ROSE = 11;
+pub const PF_DECnet = 12;
+pub const PF_NETBEUI = 13;
+pub const PF_SECURITY = 14;
+pub const PF_KEY = 15;
+pub const PF_NETLINK = 16;
+pub const PF_ROUTE = PF_NETLINK;
+pub const PF_PACKET = 17;
+pub const PF_ASH = 18;
+pub const PF_ECONET = 19;
+pub const PF_ATMSVC = 20;
+pub const PF_RDS = 21;
+pub const PF_SNA = 22;
+pub const PF_IRDA = 23;
+pub const PF_PPPOX = 24;
+pub const PF_WANPIPE = 25;
+pub const PF_LLC = 26;
+pub const PF_IB = 27;
+pub const PF_MPLS = 28;
+pub const PF_CAN = 29;
+pub const PF_TIPC = 30;
+pub const PF_BLUETOOTH = 31;
+pub const PF_IUCV = 32;
+pub const PF_RXRPC = 33;
+pub const PF_ISDN = 34;
+pub const PF_PHONET = 35;
+pub const PF_IEEE802154 = 36;
+pub const PF_CAIF = 37;
+pub const PF_ALG = 38;
+pub const PF_NFC = 39;
+pub const PF_VSOCK = 40;
+pub const PF_MAX = 41;
+
+pub const AF_UNSPEC = PF_UNSPEC;
+pub const AF_LOCAL = PF_LOCAL;
+pub const AF_UNIX = AF_LOCAL;
+pub const AF_FILE = AF_LOCAL;
+pub const AF_INET = PF_INET;
+pub const AF_AX25 = PF_AX25;
+pub const AF_IPX = PF_IPX;
+pub const AF_APPLETALK = PF_APPLETALK;
+pub const AF_NETROM = PF_NETROM;
+pub const AF_BRIDGE = PF_BRIDGE;
+pub const AF_ATMPVC = PF_ATMPVC;
+pub const AF_X25 = PF_X25;
+pub const AF_INET6 = PF_INET6;
+pub const AF_ROSE = PF_ROSE;
+pub const AF_DECnet = PF_DECnet;
+pub const AF_NETBEUI = PF_NETBEUI;
+pub const AF_SECURITY = PF_SECURITY;
+pub const AF_KEY = PF_KEY;
+pub const AF_NETLINK = PF_NETLINK;
+pub const AF_ROUTE = PF_ROUTE;
+pub const AF_PACKET = PF_PACKET;
+pub const AF_ASH = PF_ASH;
+pub const AF_ECONET = PF_ECONET;
+pub const AF_ATMSVC = PF_ATMSVC;
+pub const AF_RDS = PF_RDS;
+pub const AF_SNA = PF_SNA;
+pub const AF_IRDA = PF_IRDA;
+pub const AF_PPPOX = PF_PPPOX;
+pub const AF_WANPIPE = PF_WANPIPE;
+pub const AF_LLC = PF_LLC;
+pub const AF_IB = PF_IB;
+pub const AF_MPLS = PF_MPLS;
+pub const AF_CAN = PF_CAN;
+pub const AF_TIPC = PF_TIPC;
+pub const AF_BLUETOOTH = PF_BLUETOOTH;
+pub const AF_IUCV = PF_IUCV;
+pub const AF_RXRPC = PF_RXRPC;
+pub const AF_ISDN = PF_ISDN;
+pub const AF_PHONET = PF_PHONET;
+pub const AF_IEEE802154 = PF_IEEE802154;
+pub const AF_CAIF = PF_CAIF;
+pub const AF_ALG = PF_ALG;
+pub const AF_NFC = PF_NFC;
+pub const AF_VSOCK = PF_VSOCK;
+pub const AF_MAX = PF_MAX;
+
+pub const DT_UNKNOWN = 0;
+pub const DT_FIFO = 1;
+pub const DT_CHR = 2;
+pub const DT_DIR = 4;
+pub const DT_BLK = 6;
+pub const DT_REG = 8;
+pub const DT_LNK = 10;
+pub const DT_SOCK = 12;
+pub const DT_WHT = 14;
+
+/// add event to kq (implies enable)
+pub const EV_ADD = 0x0001;
+
+/// delete event from kq
+pub const EV_DELETE = 0x0002;
+
+/// enable event
+pub const EV_ENABLE = 0x0004;
+
+/// disable event (not reported)
+pub const EV_DISABLE = 0x0008;
+
+/// only report one occurrence
+pub const EV_ONESHOT = 0x0010;
+
+/// clear event state after reporting
+pub const EV_CLEAR = 0x0020;
+
+/// force immediate event output
+/// ... with or without EV_ERROR
+/// ... use KEVENT_FLAG_ERROR_EVENTS
+/// on syscalls supporting flags
+pub const EV_RECEIPT = 0x0040;
+
+/// disable event after reporting
+pub const EV_DISPATCH = 0x0080;
+
+pub const EVFILT_READ = -1;
+pub const EVFILT_WRITE = -2;
+
+/// attached to aio requests
+pub const EVFILT_AIO = -3;
+
+/// attached to vnodes
+pub const EVFILT_VNODE = -4;
+
+/// attached to struct proc
+pub const EVFILT_PROC = -5;
+
+/// attached to struct proc
+pub const EVFILT_SIGNAL = -6;
+
+/// timers
+pub const EVFILT_TIMER = -7;
+
+/// Process descriptors
+pub const EVFILT_PROCDESC = -8;
+
+/// Filesystem events
+pub const EVFILT_FS = -9;
+
+pub const EVFILT_LIO = -10;
+
+/// User events
+pub const EVFILT_USER = -11;
+
+/// Sendfile events
+pub const EVFILT_SENDFILE = -12;
+
+pub const EVFILT_EMPTY = -13;
+
+/// On input, NOTE_TRIGGER causes the event to be triggered for output.
+pub const NOTE_TRIGGER = 0x01000000;
+
+/// ignore input fflags
+pub const NOTE_FFNOP = 0x00000000;
+
+/// and fflags
+pub const NOTE_FFAND = 0x40000000;
+
+/// or fflags
+pub const NOTE_FFOR = 0x80000000;
+
+/// copy fflags
+pub const NOTE_FFCOPY = 0xc0000000;
+
+/// mask for operations
+pub const NOTE_FFCTRLMASK = 0xc0000000;
+pub const NOTE_FFLAGSMASK = 0x00ffffff;
+
+/// low water mark
+pub const NOTE_LOWAT = 0x00000001;
+
+/// behave like poll()
+pub const NOTE_FILE_POLL = 0x00000002;
+
+/// vnode was removed
+pub const NOTE_DELETE = 0x00000001;
+
+/// data contents changed
+pub const NOTE_WRITE = 0x00000002;
+
+/// size increased
+pub const NOTE_EXTEND = 0x00000004;
+
+/// attributes changed
+pub const NOTE_ATTRIB = 0x00000008;
+
+/// link count changed
+pub const NOTE_LINK = 0x00000010;
+
+/// vnode was renamed
+pub const NOTE_RENAME = 0x00000020;
+
+/// vnode access was revoked
+pub const NOTE_REVOKE = 0x00000040;
+
+/// vnode was opened
+pub const NOTE_OPEN = 0x00000080;
+
+/// file closed, fd did not allow write
+pub const NOTE_CLOSE = 0x00000100;
+
+/// file closed, fd did allow write
+pub const NOTE_CLOSE_WRITE = 0x00000200;
+
+/// file was read
+pub const NOTE_READ = 0x00000400;
+
+/// process exited
+pub const NOTE_EXIT = 0x80000000;
+
+/// process forked
+pub const NOTE_FORK = 0x40000000;
+
+/// process exec'd
+pub const NOTE_EXEC = 0x20000000;
+
+/// mask for signal & exit status
+pub const NOTE_PDATAMASK = 0x000fffff;
+pub const NOTE_PCTRLMASK = (~NOTE_PDATAMASK);
+
+/// data is seconds
+pub const NOTE_SECONDS = 0x00000001;
+
+/// data is milliseconds
+pub const NOTE_MSECONDS = 0x00000002;
+
+/// data is microseconds
+pub const NOTE_USECONDS = 0x00000004;
+
+/// data is nanoseconds
+pub const NOTE_NSECONDS = 0x00000008;
+
+/// timeout is absolute
+pub const NOTE_ABSTIME = 0x00000010;
+
+pub const TCGETS = 0x5401;
+pub const TCSETS = 0x5402;
+pub const TCSETSW = 0x5403;
+pub const TCSETSF = 0x5404;
+pub const TCGETA = 0x5405;
+pub const TCSETA = 0x5406;
+pub const TCSETAW = 0x5407;
+pub const TCSETAF = 0x5408;
+pub const TCSBRK = 0x5409;
+pub const TCXONC = 0x540A;
+pub const TCFLSH = 0x540B;
+pub const TIOCEXCL = 0x540C;
+pub const TIOCNXCL = 0x540D;
+pub const TIOCSCTTY = 0x540E;
+pub const TIOCGPGRP = 0x540F;
+pub const TIOCSPGRP = 0x5410;
+pub const TIOCOUTQ = 0x5411;
+pub const TIOCSTI = 0x5412;
+pub const TIOCGWINSZ = 0x5413;
+pub const TIOCSWINSZ = 0x5414;
+pub const TIOCMGET = 0x5415;
+pub const TIOCMBIS = 0x5416;
+pub const TIOCMBIC = 0x5417;
+pub const TIOCMSET = 0x5418;
+pub const TIOCGSOFTCAR = 0x5419;
+pub const TIOCSSOFTCAR = 0x541A;
+pub const FIONREAD = 0x541B;
+pub const TIOCINQ = FIONREAD;
+pub const TIOCLINUX = 0x541C;
+pub const TIOCCONS = 0x541D;
+pub const TIOCGSERIAL = 0x541E;
+pub const TIOCSSERIAL = 0x541F;
+pub const TIOCPKT = 0x5420;
+pub const FIONBIO = 0x5421;
+pub const TIOCNOTTY = 0x5422;
+pub const TIOCSETD = 0x5423;
+pub const TIOCGETD = 0x5424;
+pub const TCSBRKP = 0x5425;
+pub const TIOCSBRK = 0x5427;
+pub const TIOCCBRK = 0x5428;
+pub const TIOCGSID = 0x5429;
+pub const TIOCGRS485 = 0x542E;
+pub const TIOCSRS485 = 0x542F;
+pub const TIOCGPTN = 0x80045430;
+pub const TIOCSPTLCK = 0x40045431;
+pub const TIOCGDEV = 0x80045432;
+pub const TCGETX = 0x5432;
+pub const TCSETX = 0x5433;
+pub const TCSETXF = 0x5434;
+pub const TCSETXW = 0x5435;
+pub const TIOCSIG = 0x40045436;
+pub const TIOCVHANGUP = 0x5437;
+pub const TIOCGPKT = 0x80045438;
+pub const TIOCGPTLCK = 0x80045439;
+pub const TIOCGEXCL = 0x80045440;
+
+fn unsigned(s: i32) u32 {
+ return @bitCast(u32, s);
+}
+fn signed(s: u32) i32 {
+ return @bitCast(i32, s);
+}
+pub fn WEXITSTATUS(s: i32) i32 {
+ return signed((unsigned(s) & 0xff00) >> 8);
+}
+pub fn WTERMSIG(s: i32) i32 {
+ return signed(unsigned(s) & 0x7f);
+}
+pub fn WSTOPSIG(s: i32) i32 {
+ return WEXITSTATUS(s);
+}
+pub fn WIFEXITED(s: i32) bool {
+ return WTERMSIG(s) == 0;
+}
+pub fn WIFSTOPPED(s: i32) bool {
+ return @intCast(u16, (((unsigned(s) & 0xffff) *% 0x10001) >> 8)) > 0x7f00;
+}
+pub fn WIFSIGNALED(s: i32) bool {
+ return (unsigned(s) & 0xffff) -% 1 < 0xff;
+}
+
+pub const winsize = extern struct {
+ ws_row: u16,
+ ws_col: u16,
+ ws_xpixel: u16,
+ ws_ypixel: u16,
+};
+
+/// Get the errno from a syscall return value, or 0 for no error.
+pub fn getErrno(r: usize) usize {
+ const signed_r = @bitCast(isize, r);
+ return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0;
+}
+
+pub fn dup2(old: i32, new: i32) usize {
+ return arch.syscall2(SYS_dup2, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)));
+}
+
+pub fn chdir(path: [*]const u8) usize {
+ return arch.syscall1(SYS_chdir, @ptrToInt(path));
+}
+
+pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
+ return arch.syscall3(SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp));
+}
+
+pub fn fork() usize {
+ return arch.syscall0(SYS_fork);
+}
+
+pub fn getcwd(buf: [*]u8, size: usize) usize {
+ return arch.syscall2(SYS___getcwd, @ptrToInt(buf), size);
+}
+
+pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
+ return arch.syscall3(SYS_getdents, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
+}
+
+pub fn isatty(fd: i32) bool {
+ var wsz: winsize = undefined;
+ return arch.syscall3(SYS_ioctl, @bitCast(usize, isize(fd)), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
+}
+
+pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
+ return arch.syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
+}
+
+pub fn mkdir(path: [*]const u8, mode: u32) usize {
+ return arch.syscall2(SYS_mkdir, @ptrToInt(path), mode);
+}
+
+pub fn mmap(address: ?*u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) usize {
+ return arch.syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
+}
+
+pub fn munmap(address: usize, length: usize) usize {
+ return arch.syscall2(SYS_munmap, address, length);
+}
+
+pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
+ return arch.syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
+}
+
+pub fn rmdir(path: [*]const u8) usize {
+ return arch.syscall1(SYS_rmdir, @ptrToInt(path));
+}
+
+pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
+ return arch.syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
+}
+
+pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
+ return arch.syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
+}
+
+pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: usize) usize {
+ return arch.syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
+}
+
+pub fn pipe(fd: *[2]i32) usize {
+ return pipe2(fd, 0);
+}
+
+pub fn pipe2(fd: *[2]i32, flags: usize) usize {
+ return arch.syscall2(SYS_pipe2, @ptrToInt(fd), flags);
+}
+
+pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
+ return arch.syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
+}
+
+pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
+ return arch.syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
+}
+
+pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: usize) usize {
+ return arch.syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
+}
+
+pub fn rename(old: [*]const u8, new: [*]const u8) usize {
+ return arch.syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
+}
+
+pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
+ return arch.syscall3(SYS_open, @ptrToInt(path), flags, perm);
+}
+
+pub fn create(path: [*]const u8, perm: usize) usize {
+ return arch.syscall2(SYS_creat, @ptrToInt(path), perm);
+}
+
+pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize {
+ return arch.syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode);
+}
+
+pub fn close(fd: i32) usize {
+ return arch.syscall1(SYS_close, @bitCast(usize, isize(fd)));
+}
+
+pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {
+ return arch.syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), ref_pos);
+}
+
+pub fn exit(status: i32) noreturn {
+ _ = arch.syscall1(SYS_exit, @bitCast(usize, isize(status)));
+ unreachable;
+}
+
+pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
+ return arch.syscall3(SYS_getrandom, @ptrToInt(buf), count, usize(flags));
+}
+
+pub fn kill(pid: i32, sig: i32) usize {
+ return arch.syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig)));
+}
+
+pub fn unlink(path: [*]const u8) usize {
+ return arch.syscall1(SYS_unlink, @ptrToInt(path));
+}
+
+pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
+ return arch.syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
+}
+
+pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
+ return arch.syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem));
+}
+
+pub fn setuid(uid: u32) usize {
+ return arch.syscall1(SYS_setuid, uid);
+}
+
+pub fn setgid(gid: u32) usize {
+ return arch.syscall1(SYS_setgid, gid);
+}
+
+pub fn setreuid(ruid: u32, euid: u32) usize {
+ return arch.syscall2(SYS_setreuid, ruid, euid);
+}
+
+pub fn setregid(rgid: u32, egid: u32) usize {
+ return arch.syscall2(SYS_setregid, rgid, egid);
+}
+
+const NSIG = 32;
+
+pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize));
+pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0);
+pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1);
+
+/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
+pub const Sigaction = extern struct {
+ /// signal handler
+ __sigaction_u: extern union {
+ __sa_handler: extern fn (i32) void,
+ __sa_sigaction: extern fn (i32, *__siginfo, usize) void,
+ },
+
+ /// see signal options
+ sa_flags: u32,
+
+ /// signal mask to apply
+ sa_mask: sigset_t,
+};
+
+pub const _SIG_WORDS = 4;
+pub const _SIG_MAXSIG = 128;
+
+pub inline fn _SIG_IDX(sig: usize) usize {
+ return sig - 1;
+}
+pub inline fn _SIG_WORD(sig: usize) usize {
+ return_SIG_IDX(sig) >> 5;
+}
+pub inline fn _SIG_BIT(sig: usize) usize {
+ return 1 << (_SIG_IDX(sig) & 31);
+}
+pub inline fn _SIG_VALID(sig: usize) usize {
+ return sig <= _SIG_MAXSIG and sig > 0;
+}
+
+pub const sigset_t = extern struct {
+ __bits: [_SIG_WORDS]u32,
+};
+
+pub fn raise(sig: i32) usize {
+ // TODO have a chat with the freebsd folks and make sure there's no bug in
+ // their libc. musl-libc blocks signals in between these calls because
+ // if a signal handler runs and forks between the gettid and sending the
+ // signal, the parent will get 2 signals, one from itself and one from the child
+ // if the protection does not belong here, then it belongs in abort(),
+ // like it does in freebsd's libc.
+ var id: usize = undefined;
+ const rc = arch.syscall1(SYS_thr_self, @ptrToInt(&id));
+ if (getErrno(rc) != 0) return rc;
+ return arch.syscall2(SYS_thr_kill, id, @bitCast(usize, isize(sig)));
+}
+
+pub const Stat = arch.Stat;
+pub const timespec = arch.timespec;
+
+pub fn fstat(fd: i32, stat_buf: *Stat) usize {
+ return arch.syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf));
+}
+
+pub const iovec = extern struct {
+ iov_base: [*]u8,
+ iov_len: usize,
+};
+
+pub const iovec_const = extern struct {
+ iov_base: [*]const u8,
+ iov_len: usize,
+};
+
+// TODO avoid libc dependency
+pub fn kqueue() usize {
+ return errnoWrap(c.kqueue());
+}
+
+// TODO avoid libc dependency
+pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: ?*const timespec) usize {
+ return errnoWrap(c.kevent(
+ kq,
+ changelist.ptr,
+ @intCast(c_int, changelist.len),
+ eventlist.ptr,
+ @intCast(c_int, eventlist.len),
+ timeout,
+ ));
+}
+
+// TODO avoid libc dependency
+pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
+ return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen));
+}
+
+// TODO avoid libc dependency
+pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
+ return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen));
+}
+
+// TODO avoid libc dependency
+pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize {
+ return errnoWrap(c.sysctlnametomib(name, wibp, sizep));
+}
+
+// TODO avoid libc dependency
+
+/// Takes the return value from a syscall and formats it back in the way
+/// that the kernel represents it to libc. Errno was a mistake, let's make
+/// it go away forever.
+fn errnoWrap(value: isize) usize {
+ return @bitCast(usize, if (value == -1) -isize(c._errno().*) else value);
+}
diff --git a/std/os/freebsd/syscall.zig b/std/os/freebsd/syscall.zig
new file mode 100644
index 0000000000..6cdd71de3b
--- /dev/null
+++ b/std/os/freebsd/syscall.zig
@@ -0,0 +1,493 @@
+pub const SYS_syscall = 0;
+pub const SYS_exit = 1;
+pub const SYS_fork = 2;
+pub const SYS_read = 3;
+pub const SYS_write = 4;
+pub const SYS_open = 5;
+pub const SYS_close = 6;
+pub const SYS_wait4 = 7;
+// 8 is old creat
+pub const SYS_link = 9;
+pub const SYS_unlink = 10;
+// 11 is obsolete execv
+pub const SYS_chdir = 12;
+pub const SYS_fchdir = 13;
+pub const SYS_freebsd11_mknod = 14;
+pub const SYS_chmod = 15;
+pub const SYS_chown = 16;
+pub const SYS_break = 17;
+// 18 is freebsd4 getfsstat
+// 19 is old lseek
+pub const SYS_getpid = 20;
+pub const SYS_mount = 21;
+pub const SYS_unmount = 22;
+pub const SYS_setuid = 23;
+pub const SYS_getuid = 24;
+pub const SYS_geteuid = 25;
+pub const SYS_ptrace = 26;
+pub const SYS_recvmsg = 27;
+pub const SYS_sendmsg = 28;
+pub const SYS_recvfrom = 29;
+pub const SYS_accept = 30;
+pub const SYS_getpeername = 31;
+pub const SYS_getsockname = 32;
+pub const SYS_access = 33;
+pub const SYS_chflags = 34;
+pub const SYS_fchflags = 35;
+pub const SYS_sync = 36;
+pub const SYS_kill = 37;
+// 38 is old stat
+pub const SYS_getppid = 39;
+// 40 is old lstat
+pub const SYS_dup = 41;
+pub const SYS_freebsd10_pipe = 42;
+pub const SYS_getegid = 43;
+pub const SYS_profil = 44;
+pub const SYS_ktrace = 45;
+// 46 is old sigaction
+pub const SYS_getgid = 47;
+// 48 is old sigprocmask
+pub const SYS_getlogin = 49;
+pub const SYS_setlogin = 50;
+pub const SYS_acct = 51;
+// 52 is old sigpending
+pub const SYS_sigaltstack = 53;
+pub const SYS_ioctl = 54;
+pub const SYS_reboot = 55;
+pub const SYS_revoke = 56;
+pub const SYS_symlink = 57;
+pub const SYS_readlink = 58;
+pub const SYS_execve = 59;
+pub const SYS_umask = 60;
+pub const SYS_chroot = 61;
+// 62 is old fstat
+// 63 is old getkerninfo
+// 64 is old getpagesize
+pub const SYS_msync = 65;
+pub const SYS_vfork = 66;
+// 67 is obsolete vread
+// 68 is obsolete vwrite
+// 69 is obsolete sbrk (still present on some platforms)
+pub const SYS_sstk = 70;
+// 71 is old mmap
+pub const SYS_vadvise = 72;
+pub const SYS_munmap = 73;
+pub const SYS_mprotect = 74;
+pub const SYS_madvise = 75;
+// 76 is obsolete vhangup
+// 77 is obsolete vlimit
+pub const SYS_mincore = 78;
+pub const SYS_getgroups = 79;
+pub const SYS_setgroups = 80;
+pub const SYS_getpgrp = 81;
+pub const SYS_setpgid = 82;
+pub const SYS_setitimer = 83;
+// 84 is old wait
+pub const SYS_swapon = 85;
+pub const SYS_getitimer = 86;
+// 87 is old gethostname
+// 88 is old sethostname
+pub const SYS_getdtablesize = 89;
+pub const SYS_dup2 = 90;
+pub const SYS_fcntl = 92;
+pub const SYS_select = 93;
+pub const SYS_fsync = 95;
+pub const SYS_setpriority = 96;
+pub const SYS_socket = 97;
+pub const SYS_connect = 98;
+// 99 is old accept
+pub const SYS_getpriority = 100;
+// 101 is old send
+// 102 is old recv
+// 103 is old sigreturn
+pub const SYS_bind = 104;
+pub const SYS_setsockopt = 105;
+pub const SYS_listen = 106;
+// 107 is obsolete vtimes
+// 108 is old sigvec
+// 109 is old sigblock
+// 110 is old sigsetmask
+// 111 is old sigsuspend
+// 112 is old sigstack
+// 113 is old recvmsg
+// 114 is old sendmsg
+// 115 is obsolete vtrace
+pub const SYS_gettimeofday = 116;
+pub const SYS_getrusage = 117;
+pub const SYS_getsockopt = 118;
+pub const SYS_readv = 120;
+pub const SYS_writev = 121;
+pub const SYS_settimeofday = 122;
+pub const SYS_fchown = 123;
+pub const SYS_fchmod = 124;
+// 125 is old recvfrom
+pub const SYS_setreuid = 126;
+pub const SYS_setregid = 127;
+pub const SYS_rename = 128;
+// 129 is old truncate
+// 130 is old ftruncate
+pub const SYS_flock = 131;
+pub const SYS_mkfifo = 132;
+pub const SYS_sendto = 133;
+pub const SYS_shutdown = 134;
+pub const SYS_socketpair = 135;
+pub const SYS_mkdir = 136;
+pub const SYS_rmdir = 137;
+pub const SYS_utimes = 138;
+// 139 is obsolete 4.2 sigreturn
+pub const SYS_adjtime = 140;
+// 141 is old getpeername
+// 142 is old gethostid
+// 143 is old sethostid
+// 144 is old getrlimit
+// 145 is old setrlimit
+// 146 is old killpg
+pub const SYS_setsid = 147;
+pub const SYS_quotactl = 148;
+// 149 is old quota
+// 150 is old getsockname
+pub const SYS_nlm_syscall = 154;
+pub const SYS_nfssvc = 155;
+// 156 is old getdirentries
+// 157 is freebsd4 statfs
+// 158 is freebsd4 fstatfs
+pub const SYS_lgetfh = 160;
+pub const SYS_getfh = 161;
+// 162 is freebsd4 getdomainname
+// 163 is freebsd4 setdomainname
+// 164 is freebsd4 uname
+pub const SYS_sysarch = 165;
+pub const SYS_rtprio = 166;
+pub const SYS_semsys = 169;
+pub const SYS_msgsys = 170;
+pub const SYS_shmsys = 171;
+// 173 is freebsd6 pread
+// 174 is freebsd6 pwrite
+pub const SYS_setfib = 175;
+pub const SYS_ntp_adjtime = 176;
+pub const SYS_setgid = 181;
+pub const SYS_setegid = 182;
+pub const SYS_seteuid = 183;
+// 184 is obsolete lfs_bmapv
+// 185 is obsolete lfs_markv
+// 186 is obsolete lfs_segclean
+// 187 is obsolete lfs_segwait
+pub const SYS_freebsd11_stat = 188;
+pub const SYS_freebsd11_fstat = 189;
+pub const SYS_freebsd11_lstat = 190;
+pub const SYS_pathconf = 191;
+pub const SYS_fpathconf = 192;
+pub const SYS_getrlimit = 194;
+pub const SYS_setrlimit = 195;
+pub const SYS_freebsd11_getdirentries = 196;
+// 197 is freebsd6 mmap
+pub const SYS___syscall = 198;
+// 199 is freebsd6 lseek
+// 200 is freebsd6 truncate
+// 201 is freebsd6 ftruncate
+pub const SYS___sysctl = 202;
+pub const SYS_mlock = 203;
+pub const SYS_munlock = 204;
+pub const SYS_undelete = 205;
+pub const SYS_futimes = 206;
+pub const SYS_getpgid = 207;
+pub const SYS_poll = 209;
+pub const SYS_freebsd7___semctl = 220;
+pub const SYS_semget = 221;
+pub const SYS_semop = 222;
+pub const SYS_freebsd7_msgctl = 224;
+pub const SYS_msgget = 225;
+pub const SYS_msgsnd = 226;
+pub const SYS_msgrcv = 227;
+pub const SYS_shmat = 228;
+pub const SYS_freebsd7_shmctl = 229;
+pub const SYS_shmdt = 230;
+pub const SYS_shmget = 231;
+pub const SYS_clock_gettime = 232;
+pub const SYS_clock_settime = 233;
+pub const SYS_clock_getres = 234;
+pub const SYS_ktimer_create = 235;
+pub const SYS_ktimer_delete = 236;
+pub const SYS_ktimer_settime = 237;
+pub const SYS_ktimer_gettime = 238;
+pub const SYS_ktimer_getoverrun = 239;
+pub const SYS_nanosleep = 240;
+pub const SYS_ffclock_getcounter = 241;
+pub const SYS_ffclock_setestimate = 242;
+pub const SYS_ffclock_getestimate = 243;
+pub const SYS_clock_nanosleep = 244;
+pub const SYS_clock_getcpuclockid2 = 247;
+pub const SYS_ntp_gettime = 248;
+pub const SYS_minherit = 250;
+pub const SYS_rfork = 251;
+// 252 is obsolete openbsd_poll
+pub const SYS_issetugid = 253;
+pub const SYS_lchown = 254;
+pub const SYS_aio_read = 255;
+pub const SYS_aio_write = 256;
+pub const SYS_lio_listio = 257;
+pub const SYS_freebsd11_getdents = 272;
+pub const SYS_lchmod = 274;
+// 275 is obsolete netbsd_lchown
+pub const SYS_lutimes = 276;
+// 277 is obsolete netbsd_msync
+pub const SYS_freebsd11_nstat = 278;
+pub const SYS_freebsd11_nfstat = 279;
+pub const SYS_freebsd11_nlstat = 280;
+pub const SYS_preadv = 289;
+pub const SYS_pwritev = 290;
+// 297 is freebsd4 fhstatfs
+pub const SYS_fhopen = 298;
+pub const SYS_freebsd11_fhstat = 299;
+pub const SYS_modnext = 300;
+pub const SYS_modstat = 301;
+pub const SYS_modfnext = 302;
+pub const SYS_modfind = 303;
+pub const SYS_kldload = 304;
+pub const SYS_kldunload = 305;
+pub const SYS_kldfind = 306;
+pub const SYS_kldnext = 307;
+pub const SYS_kldstat = 308;
+pub const SYS_kldfirstmod = 309;
+pub const SYS_getsid = 310;
+pub const SYS_setresuid = 311;
+pub const SYS_setresgid = 312;
+// 313 is obsolete signanosleep
+pub const SYS_aio_return = 314;
+pub const SYS_aio_suspend = 315;
+pub const SYS_aio_cancel = 316;
+pub const SYS_aio_error = 317;
+// 318 is freebsd6 aio_read
+// 319 is freebsd6 aio_write
+// 320 is freebsd6 lio_listio
+pub const SYS_yield = 321;
+// 322 is obsolete thr_sleep
+// 323 is obsolete thr_wakeup
+pub const SYS_mlockall = 324;
+pub const SYS_munlockall = 325;
+pub const SYS___getcwd = 326;
+pub const SYS_sched_setparam = 327;
+pub const SYS_sched_getparam = 328;
+pub const SYS_sched_setscheduler = 329;
+pub const SYS_sched_getscheduler = 330;
+pub const SYS_sched_yield = 331;
+pub const SYS_sched_get_priority_max = 332;
+pub const SYS_sched_get_priority_min = 333;
+pub const SYS_sched_rr_get_interval = 334;
+pub const SYS_utrace = 335;
+// 336 is freebsd4 sendfile
+pub const SYS_kldsym = 337;
+pub const SYS_jail = 338;
+pub const SYS_nnpfs_syscall = 339;
+pub const SYS_sigprocmask = 340;
+pub const SYS_sigsuspend = 341;
+// 342 is freebsd4 sigaction
+pub const SYS_sigpending = 343;
+// 344 is freebsd4 sigreturn
+pub const SYS_sigtimedwait = 345;
+pub const SYS_sigwaitinfo = 346;
+pub const SYS___acl_get_file = 347;
+pub const SYS___acl_set_file = 348;
+pub const SYS___acl_get_fd = 349;
+pub const SYS___acl_set_fd = 350;
+pub const SYS___acl_delete_file = 351;
+pub const SYS___acl_delete_fd = 352;
+pub const SYS___acl_aclcheck_file = 353;
+pub const SYS___acl_aclcheck_fd = 354;
+pub const SYS_extattrctl = 355;
+pub const SYS_extattr_set_file = 356;
+pub const SYS_extattr_get_file = 357;
+pub const SYS_extattr_delete_file = 358;
+pub const SYS_aio_waitcomplete = 359;
+pub const SYS_getresuid = 360;
+pub const SYS_getresgid = 361;
+pub const SYS_kqueue = 362;
+pub const SYS_freebsd11_kevent = 363;
+// 364 is obsolete __cap_get_proc
+// 365 is obsolete __cap_set_proc
+// 366 is obsolete __cap_get_fd
+// 367 is obsolete __cap_get_file
+// 368 is obsolete __cap_set_fd
+// 369 is obsolete __cap_set_file
+pub const SYS_extattr_set_fd = 371;
+pub const SYS_extattr_get_fd = 372;
+pub const SYS_extattr_delete_fd = 373;
+pub const SYS___setugid = 374;
+pub const SYS_eaccess = 376;
+pub const SYS_afs3_syscall = 377;
+pub const SYS_nmount = 378;
+// 379 is obsolete kse_exit
+// 380 is obsolete kse_wakeup
+// 381 is obsolete kse_create
+// 382 is obsolete kse_thr_interrupt
+// 383 is obsolete kse_release
+pub const SYS___mac_get_proc = 384;
+pub const SYS___mac_set_proc = 385;
+pub const SYS___mac_get_fd = 386;
+pub const SYS___mac_get_file = 387;
+pub const SYS___mac_set_fd = 388;
+pub const SYS___mac_set_file = 389;
+pub const SYS_kenv = 390;
+pub const SYS_lchflags = 391;
+pub const SYS_uuidgen = 392;
+pub const SYS_sendfile = 393;
+pub const SYS_mac_syscall = 394;
+pub const SYS_freebsd11_getfsstat = 395;
+pub const SYS_freebsd11_statfs = 396;
+pub const SYS_freebsd11_fstatfs = 397;
+pub const SYS_freebsd11_fhstatfs = 398;
+pub const SYS_ksem_close = 400;
+pub const SYS_ksem_post = 401;
+pub const SYS_ksem_wait = 402;
+pub const SYS_ksem_trywait = 403;
+pub const SYS_ksem_init = 404;
+pub const SYS_ksem_open = 405;
+pub const SYS_ksem_unlink = 406;
+pub const SYS_ksem_getvalue = 407;
+pub const SYS_ksem_destroy = 408;
+pub const SYS___mac_get_pid = 409;
+pub const SYS___mac_get_link = 410;
+pub const SYS___mac_set_link = 411;
+pub const SYS_extattr_set_link = 412;
+pub const SYS_extattr_get_link = 413;
+pub const SYS_extattr_delete_link = 414;
+pub const SYS___mac_execve = 415;
+pub const SYS_sigaction = 416;
+pub const SYS_sigreturn = 417;
+pub const SYS_getcontext = 421;
+pub const SYS_setcontext = 422;
+pub const SYS_swapcontext = 423;
+pub const SYS_swapoff = 424;
+pub const SYS___acl_get_link = 425;
+pub const SYS___acl_set_link = 426;
+pub const SYS___acl_delete_link = 427;
+pub const SYS___acl_aclcheck_link = 428;
+pub const SYS_sigwait = 429;
+pub const SYS_thr_create = 430;
+pub const SYS_thr_exit = 431;
+pub const SYS_thr_self = 432;
+pub const SYS_thr_kill = 433;
+pub const SYS_jail_attach = 436;
+pub const SYS_extattr_list_fd = 437;
+pub const SYS_extattr_list_file = 438;
+pub const SYS_extattr_list_link = 439;
+// 440 is obsolete kse_switchin
+pub const SYS_ksem_timedwait = 441;
+pub const SYS_thr_suspend = 442;
+pub const SYS_thr_wake = 443;
+pub const SYS_kldunloadf = 444;
+pub const SYS_audit = 445;
+pub const SYS_auditon = 446;
+pub const SYS_getauid = 447;
+pub const SYS_setauid = 448;
+pub const SYS_getaudit = 449;
+pub const SYS_setaudit = 450;
+pub const SYS_getaudit_addr = 451;
+pub const SYS_setaudit_addr = 452;
+pub const SYS_auditctl = 453;
+pub const SYS__umtx_op = 454;
+pub const SYS_thr_new = 455;
+pub const SYS_sigqueue = 456;
+pub const SYS_kmq_open = 457;
+pub const SYS_kmq_setattr = 458;
+pub const SYS_kmq_timedreceive = 459;
+pub const SYS_kmq_timedsend = 460;
+pub const SYS_kmq_notify = 461;
+pub const SYS_kmq_unlink = 462;
+pub const SYS_abort2 = 463;
+pub const SYS_thr_set_name = 464;
+pub const SYS_aio_fsync = 465;
+pub const SYS_rtprio_thread = 466;
+pub const SYS_sctp_peeloff = 471;
+pub const SYS_sctp_generic_sendmsg = 472;
+pub const SYS_sctp_generic_sendmsg_iov = 473;
+pub const SYS_sctp_generic_recvmsg = 474;
+pub const SYS_pread = 475;
+pub const SYS_pwrite = 476;
+pub const SYS_mmap = 477;
+pub const SYS_lseek = 478;
+pub const SYS_truncate = 479;
+pub const SYS_ftruncate = 480;
+pub const SYS_thr_kill2 = 481;
+pub const SYS_shm_open = 482;
+pub const SYS_shm_unlink = 483;
+pub const SYS_cpuset = 484;
+pub const SYS_cpuset_setid = 485;
+pub const SYS_cpuset_getid = 486;
+pub const SYS_cpuset_getaffinity = 487;
+pub const SYS_cpuset_setaffinity = 488;
+pub const SYS_faccessat = 489;
+pub const SYS_fchmodat = 490;
+pub const SYS_fchownat = 491;
+pub const SYS_fexecve = 492;
+pub const SYS_freebsd11_fstatat = 493;
+pub const SYS_futimesat = 494;
+pub const SYS_linkat = 495;
+pub const SYS_mkdirat = 496;
+pub const SYS_mkfifoat = 497;
+pub const SYS_freebsd11_mknodat = 498;
+pub const SYS_openat = 499;
+pub const SYS_readlinkat = 500;
+pub const SYS_renameat = 501;
+pub const SYS_symlinkat = 502;
+pub const SYS_unlinkat = 503;
+pub const SYS_posix_openpt = 504;
+pub const SYS_gssd_syscall = 505;
+pub const SYS_jail_get = 506;
+pub const SYS_jail_set = 507;
+pub const SYS_jail_remove = 508;
+pub const SYS_closefrom = 509;
+pub const SYS___semctl = 510;
+pub const SYS_msgctl = 511;
+pub const SYS_shmctl = 512;
+pub const SYS_lpathconf = 513;
+// 514 is obsolete cap_new
+pub const SYS___cap_rights_get = 515;
+pub const SYS_cap_enter = 516;
+pub const SYS_cap_getmode = 517;
+pub const SYS_pdfork = 518;
+pub const SYS_pdkill = 519;
+pub const SYS_pdgetpid = 520;
+pub const SYS_pselect = 522;
+pub const SYS_getloginclass = 523;
+pub const SYS_setloginclass = 524;
+pub const SYS_rctl_get_racct = 525;
+pub const SYS_rctl_get_rules = 526;
+pub const SYS_rctl_get_limits = 527;
+pub const SYS_rctl_add_rule = 528;
+pub const SYS_rctl_remove_rule = 529;
+pub const SYS_posix_fallocate = 530;
+pub const SYS_posix_fadvise = 531;
+pub const SYS_wait6 = 532;
+pub const SYS_cap_rights_limit = 533;
+pub const SYS_cap_ioctls_limit = 534;
+pub const SYS_cap_ioctls_get = 535;
+pub const SYS_cap_fcntls_limit = 536;
+pub const SYS_cap_fcntls_get = 537;
+pub const SYS_bindat = 538;
+pub const SYS_connectat = 539;
+pub const SYS_chflagsat = 540;
+pub const SYS_accept4 = 541;
+pub const SYS_pipe2 = 542;
+pub const SYS_aio_mlock = 543;
+pub const SYS_procctl = 544;
+pub const SYS_ppoll = 545;
+pub const SYS_futimens = 546;
+pub const SYS_utimensat = 547;
+// 548 is obsolete numa_getaffinity
+// 549 is obsolete numa_setaffinity
+pub const SYS_fdatasync = 550;
+pub const SYS_fstat = 551;
+pub const SYS_fstatat = 552;
+pub const SYS_fhstat = 553;
+pub const SYS_getdirentries = 554;
+pub const SYS_statfs = 555;
+pub const SYS_fstatfs = 556;
+pub const SYS_getfsstat = 557;
+pub const SYS_fhstatfs = 558;
+pub const SYS_mknodat = 559;
+pub const SYS_kevent = 560;
+pub const SYS_cpuset_getdomain = 561;
+pub const SYS_cpuset_setdomain = 562;
+pub const SYS_getrandom = 563;
+pub const SYS_MAXSYSCALL = 564;
diff --git a/std/os/freebsd/x86_64.zig b/std/os/freebsd/x86_64.zig
new file mode 100644
index 0000000000..509075386f
--- /dev/null
+++ b/std/os/freebsd/x86_64.zig
@@ -0,0 +1,136 @@
+const freebsd = @import("index.zig");
+const socklen_t = freebsd.socklen_t;
+const iovec = freebsd.iovec;
+
+pub const SYS_sbrk = 69;
+
+pub fn syscall0(number: usize) usize {
+ return asm volatile ("syscall"
+ : [ret] "={rax}" (-> usize)
+ : [number] "{rax}" (number)
+ : "rcx", "r11"
+ );
+}
+
+pub fn syscall1(number: usize, arg1: usize) usize {
+ return asm volatile ("syscall"
+ : [ret] "={rax}" (-> usize)
+ : [number] "{rax}" (number),
+ [arg1] "{rdi}" (arg1)
+ : "rcx", "r11"
+ );
+}
+
+pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize {
+ return asm volatile ("syscall"
+ : [ret] "={rax}" (-> usize)
+ : [number] "{rax}" (number),
+ [arg1] "{rdi}" (arg1),
+ [arg2] "{rsi}" (arg2)
+ : "rcx", "r11"
+ );
+}
+
+pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {
+ return asm volatile ("syscall"
+ : [ret] "={rax}" (-> usize)
+ : [number] "{rax}" (number),
+ [arg1] "{rdi}" (arg1),
+ [arg2] "{rsi}" (arg2),
+ [arg3] "{rdx}" (arg3)
+ : "rcx", "r11"
+ );
+}
+
+pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
+ return asm volatile ("syscall"
+ : [ret] "={rax}" (-> usize)
+ : [number] "{rax}" (number),
+ [arg1] "{rdi}" (arg1),
+ [arg2] "{rsi}" (arg2),
+ [arg3] "{rdx}" (arg3),
+ [arg4] "{r10}" (arg4)
+ : "rcx", "r11"
+ );
+}
+
+pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
+ return asm volatile ("syscall"
+ : [ret] "={rax}" (-> usize)
+ : [number] "{rax}" (number),
+ [arg1] "{rdi}" (arg1),
+ [arg2] "{rsi}" (arg2),
+ [arg3] "{rdx}" (arg3),
+ [arg4] "{r10}" (arg4),
+ [arg5] "{r8}" (arg5)
+ : "rcx", "r11"
+ );
+}
+
+pub fn syscall6(
+ number: usize,
+ arg1: usize,
+ arg2: usize,
+ arg3: usize,
+ arg4: usize,
+ arg5: usize,
+ arg6: usize,
+) usize {
+ return asm volatile ("syscall"
+ : [ret] "={rax}" (-> usize)
+ : [number] "{rax}" (number),
+ [arg1] "{rdi}" (arg1),
+ [arg2] "{rsi}" (arg2),
+ [arg3] "{rdx}" (arg3),
+ [arg4] "{r10}" (arg4),
+ [arg5] "{r8}" (arg5),
+ [arg6] "{r9}" (arg6)
+ : "rcx", "r11"
+ );
+}
+
+pub nakedcc fn restore_rt() void {
+ asm volatile ("syscall"
+ :
+ : [number] "{rax}" (usize(SYS_rt_sigreturn))
+ : "rcx", "r11"
+ );
+}
+
+pub const msghdr = extern struct {
+ msg_name: *u8,
+ msg_namelen: socklen_t,
+ msg_iov: *iovec,
+ msg_iovlen: i32,
+ __pad1: i32,
+ msg_control: *u8,
+ msg_controllen: socklen_t,
+ __pad2: socklen_t,
+ msg_flags: i32,
+};
+
+/// Renamed to Stat to not conflict with the stat function.
+pub const Stat = extern struct {
+ dev: u64,
+ ino: u64,
+ nlink: usize,
+
+ mode: u32,
+ uid: u32,
+ gid: u32,
+ __pad0: u32,
+ rdev: u64,
+ size: i64,
+ blksize: isize,
+ blocks: i64,
+
+ atim: timespec,
+ mtim: timespec,
+ ctim: timespec,
+ __unused: [3]isize,
+};
+
+pub const timespec = extern struct {
+ tv_sec: isize,
+ tv_nsec: isize,
+};
diff --git a/std/os/get_app_data_dir.zig b/std/os/get_app_data_dir.zig
index da9c6c3cb4..ae133bb4b1 100644
--- a/std/os/get_app_data_dir.zig
+++ b/std/os/get_app_data_dir.zig
@@ -43,7 +43,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
};
return os.path.join(allocator, home_dir, "Library", "Application Support", appname);
},
- builtin.Os.linux => {
+ builtin.Os.linux, builtin.Os.freebsd => {
const home_dir = os.getEnvPosix("HOME") orelse {
// TODO look in /etc/passwd
return error.AppDataDirUnavailable;
diff --git a/std/os/get_user_id.zig b/std/os/get_user_id.zig
index c0c1b1cc4b..9a4d1ab275 100644
--- a/std/os/get_user_id.zig
+++ b/std/os/get_user_id.zig
@@ -11,7 +11,7 @@ pub const UserInfo = struct {
/// POSIX function which gets a uid from username.
pub fn getUserInfo(name: []const u8) !UserInfo {
return switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => posixGetUserInfo(name),
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => posixGetUserInfo(name),
else => @compileError("Unsupported OS"),
};
}
diff --git a/std/os/index.zig b/std/os/index.zig
index e1915a2012..b19679c969 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -3,7 +3,7 @@ const builtin = @import("builtin");
const Os = builtin.Os;
const is_windows = builtin.os == Os.windows;
const is_posix = switch (builtin.os) {
- builtin.Os.linux, builtin.Os.macosx => true,
+ builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => true,
else => false,
};
const os = @This();
@@ -24,10 +24,12 @@ test "std.os" {
pub const windows = @import("windows/index.zig");
pub const darwin = @import("darwin.zig");
pub const linux = @import("linux/index.zig");
+pub const freebsd = @import("freebsd/index.zig");
pub const zen = @import("zen.zig");
pub const posix = switch (builtin.os) {
Os.linux => linux,
Os.macosx, Os.ios => darwin,
+ Os.freebsd => freebsd,
Os.zen => zen,
else => @compileError("Unsupported OS"),
};
@@ -40,7 +42,7 @@ pub const time = @import("time.zig");
pub const page_size = 4 * 1024;
pub const MAX_PATH_BYTES = switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => posix.PATH_MAX,
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => posix.PATH_MAX,
// Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
// If it would require 4 UTF-8 bytes, then there would be a surrogate
// pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
@@ -101,7 +103,7 @@ const math = std.math;
/// library implementation.
pub fn getRandomBytes(buf: []u8) !void {
switch (builtin.os) {
- Os.linux => while (true) {
+ Os.linux, Os.freebsd => while (true) {
// TODO check libc version and potentially call c.getrandom.
// See #397
const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
@@ -174,7 +176,7 @@ pub fn abort() noreturn {
c.abort();
}
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
_ = posix.raise(posix.SIGABRT);
_ = posix.raise(posix.SIGKILL);
while (true) {}
@@ -196,7 +198,7 @@ pub fn exit(status: u8) noreturn {
c.exit(status);
}
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
posix.exit(status);
},
Os.windows => {
@@ -419,7 +421,7 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off
}
}
},
- builtin.Os.linux => while (true) {
+ builtin.Os.linux, builtin.Os.freebsd => while (true) {
const rc = posix.pwritev(fd, iov, count, offset);
const err = posix.getErrno(rc);
switch (err) {
@@ -457,6 +459,7 @@ pub const PosixOpenError = error{
NoSpaceLeft,
NotDir,
PathAlreadyExists,
+ DeviceBusy,
/// See https://github.com/ziglang/zig/issues/1396
Unexpected,
@@ -495,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {
posix.ENOTDIR => return PosixOpenError.NotDir,
posix.EPERM => return PosixOpenError.AccessDenied,
posix.EEXIST => return PosixOpenError.PathAlreadyExists,
+ posix.EBUSY => return PosixOpenError.DeviceBusy,
else => return unexpectedErrorPosix(err),
}
}
@@ -687,7 +691,7 @@ pub fn getBaseAddress() usize {
};
return phdr - @sizeOf(ElfHeader);
},
- builtin.Os.macosx => return @ptrToInt(&std.c._mh_execute_header),
+ builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header),
builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),
else => @compileError("Unsupported OS"),
}
@@ -700,8 +704,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
errdefer result.deinit();
if (is_windows) {
- const ptr = windows.GetEnvironmentStringsA() orelse return error.OutOfMemory;
- defer assert(windows.FreeEnvironmentStringsA(ptr) != 0);
+ const ptr = windows.GetEnvironmentStringsW() orelse return error.OutOfMemory;
+ defer assert(windows.FreeEnvironmentStringsW(ptr) != 0);
var i: usize = 0;
while (true) {
@@ -710,17 +714,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
const key_start = i;
while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
- const key = ptr[key_start..i];
+ const key_w = ptr[key_start..i];
+ const key = try std.unicode.utf16leToUtf8Alloc(allocator, key_w);
+ errdefer allocator.free(key);
if (ptr[i] == '=') i += 1;
const value_start = i;
while (ptr[i] != 0) : (i += 1) {}
- const value = ptr[value_start..i];
+ const value_w = ptr[value_start..i];
+ const value = try std.unicode.utf16leToUtf8Alloc(allocator, value_w);
+ errdefer allocator.free(value);
i += 1; // skip over null byte
- try result.set(key, value);
+ try result.setMove(key, value);
}
} else {
for (posix_environ_raw) |ptr| {
@@ -738,6 +746,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
}
}
+test "os.getEnvMap" {
+ var env = try getEnvMap(std.debug.global_allocator);
+ defer env.deinit();
+}
+
/// TODO make this go through libc when we have it
pub fn getEnvPosix(key: []const u8) ?[]const u8 {
for (posix_environ_raw) |ptr| {
@@ -758,21 +771,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {
pub const GetEnvVarOwnedError = error{
OutOfMemory,
EnvironmentVariableNotFound,
+
+ /// See https://github.com/ziglang/zig/issues/1774
+ InvalidUtf8,
};
/// Caller must free returned memory.
/// TODO make this go through libc when we have it
pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
if (is_windows) {
- const key_with_null = try cstr.addNullByte(allocator, key);
+ const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
defer allocator.free(key_with_null);
- var buf = try allocator.alloc(u8, 256);
- errdefer allocator.free(buf);
+ var buf = try allocator.alloc(u16, 256);
+ defer allocator.free(buf);
while (true) {
const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;
- const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len);
+ const result = windows.GetEnvironmentVariableW(key_with_null.ptr, buf.ptr, windows_buf_len);
if (result == 0) {
const err = windows.GetLastError();
@@ -786,11 +802,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
}
if (result > buf.len) {
- buf = try allocator.realloc(u8, buf, result);
+ buf = try allocator.realloc(u16, buf, result);
continue;
}
- return allocator.shrink(u8, buf, result);
+ return std.unicode.utf16leToUtf8Alloc(allocator, buf) catch |err| switch (err) {
+ error.DanglingSurrogateHalf => return error.InvalidUtf8,
+ error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8,
+ error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8,
+ error.OutOfMemory => return error.OutOfMemory,
+ };
}
} else {
const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;
@@ -798,6 +819,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
}
}
+test "os.getEnvVarOwned" {
+ var ga = debug.global_allocator;
+ debug.assertError(getEnvVarOwned(ga, "BADENV"), error.EnvironmentVariableNotFound);
+}
+
/// Caller must free the returned memory.
pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
var buf: [MAX_PATH_BYTES]u8 = undefined;
@@ -1305,7 +1331,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {
const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path);
return deleteDirW(&dir_path_w);
},
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
const err = posix.getErrno(posix.rmdir(dir_path));
switch (err) {
0 => return,
@@ -1348,7 +1374,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {
const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path);
return deleteDirW(&dir_path_w);
},
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
const dir_path_c = try toPosixPath(dir_path);
return deleteDirC(&dir_path_c);
},
@@ -1378,6 +1404,7 @@ const DeleteTreeError = error{
FileSystem,
FileBusy,
DirNotEmpty,
+ DeviceBusy,
/// On Windows, file paths must be valid Unicode.
InvalidUtf8,
@@ -1439,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!
error.Unexpected,
error.InvalidUtf8,
error.BadPathName,
+ error.DeviceBusy,
=> return err,
};
defer dir.close();
@@ -1465,7 +1493,7 @@ pub const Dir = struct {
allocator: *Allocator,
pub const Handle = switch (builtin.os) {
- Os.macosx, Os.ios => struct {
+ Os.macosx, Os.ios, Os.freebsd => struct {
fd: i32,
seek: i64,
buf: []u8,
@@ -1521,6 +1549,7 @@ pub const Dir = struct {
OutOfMemory,
InvalidUtf8,
BadPathName,
+ DeviceBusy,
/// See https://github.com/ziglang/zig/issues/1396
Unexpected,
@@ -1541,7 +1570,7 @@ pub const Dir = struct {
.name_data = undefined,
};
},
- Os.macosx, Os.ios => Handle{
+ Os.macosx, Os.ios, Os.freebsd => Handle{
.fd = try posixOpen(
dir_path,
posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,
@@ -1572,7 +1601,7 @@ pub const Dir = struct {
Os.windows => {
_ = windows.FindClose(self.handle.handle);
},
- Os.macosx, Os.ios, Os.linux => {
+ Os.macosx, Os.ios, Os.linux, Os.freebsd => {
self.allocator.free(self.handle.buf);
os.close(self.handle.fd);
},
@@ -1587,6 +1616,7 @@ pub const Dir = struct {
Os.linux => return self.nextLinux(),
Os.macosx, Os.ios => return self.nextDarwin(),
Os.windows => return self.nextWindows(),
+ Os.freebsd => return self.nextFreebsd(),
else => @compileError("unimplemented"),
}
}
@@ -1726,6 +1756,11 @@ pub const Dir = struct {
};
}
}
+
+ fn nextFreebsd(self: *Dir) !?Entry {
+ //self.handle.buf = try self.allocator.alloc(u8, page_size);
+ @compileError("TODO implement dirs for FreeBSD");
+ }
};
pub fn changeCurDir(allocator: *Allocator, dir_path: []const u8) !void {
@@ -2164,7 +2199,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError {
pub fn openSelfExe() !os.File {
switch (builtin.os) {
Os.linux => return os.File.openReadC(c"/proc/self/exe"),
- Os.macosx, Os.ios => {
+ Os.macosx, Os.ios, Os.freebsd => {
var buf: [MAX_PATH_BYTES]u8 = undefined;
const self_exe_path = try selfExePath(&buf);
buf[self_exe_path.len] = 0;
@@ -2181,7 +2216,7 @@ pub fn openSelfExe() !os.File {
test "openSelfExe" {
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios, Os.windows => (try openSelfExe()).close(),
+ Os.linux, Os.macosx, Os.ios, Os.windows, Os.freebsd => (try openSelfExe()).close(),
else => return error.SkipZigTest, // Unsupported OS.
}
}
@@ -2212,6 +2247,7 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 {
pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
switch (builtin.os) {
Os.linux => return readLink(out_buffer, "/proc/self/exe"),
+ Os.freebsd => return readLink(out_buffer, "/proc/curproc/file"),
Os.windows => {
var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;
const utf16le_slice = try selfExePathW(&utf16le_buf);
@@ -2250,7 +2286,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {
// will not return null.
return path.dirname(full_exe_path).?;
},
- Os.windows, Os.macosx, Os.ios => {
+ Os.windows, Os.macosx, Os.ios, Os.freebsd => {
const self_exe_path = try selfExePath(out_buffer);
// Assume that the OS APIs return absolute paths, and therefore dirname
// will not return null.
@@ -3095,10 +3131,13 @@ pub const CpuCountError = error{
pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {
switch (builtin.os) {
- builtin.Os.macosx => {
+ builtin.Os.macosx, builtin.Os.freebsd => {
var count: c_int = undefined;
var count_len: usize = @sizeOf(c_int);
- const rc = posix.sysctlbyname(c"hw.logicalcpu", @ptrCast(*c_void, &count), &count_len, null, 0);
+ const rc = posix.sysctlbyname(switch (builtin.os) {
+ builtin.Os.macosx => c"hw.logicalcpu",
+ else => c"hw.ncpu",
+ }, @ptrCast(*c_void, &count), &count_len, null, 0);
const err = posix.getErrno(rc);
switch (err) {
0 => return @intCast(usize, count),
diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig
index c401eb3dc8..ec90755164 100644
--- a/std/os/linux/index.zig
+++ b/std/os/linux/index.zig
@@ -703,7 +703,7 @@ pub fn dup2(old: i32, new: i32) usize {
}
pub fn dup3(old: i32, new: i32, flags: u32) usize {
- return syscall3(SYS_dup3, @intCast(usize, old), @intCast(usize, new), flags);
+ return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), flags);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -747,7 +747,7 @@ pub fn getcwd(buf: [*]u8, size: usize) usize {
}
pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize {
- return syscall3(SYS_getdents64, @intCast(usize, fd), @ptrToInt(dirp), count);
+ return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
}
pub fn inotify_init1(flags: u32) usize {
@@ -755,16 +755,16 @@ pub fn inotify_init1(flags: u32) usize {
}
pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize {
- return syscall3(SYS_inotify_add_watch, @intCast(usize, fd), @ptrToInt(pathname), mask);
+ return syscall3(SYS_inotify_add_watch, @bitCast(usize, isize(fd)), @ptrToInt(pathname), mask);
}
pub fn inotify_rm_watch(fd: i32, wd: i32) usize {
- return syscall2(SYS_inotify_rm_watch, @intCast(usize, fd), @intCast(usize, wd));
+ return syscall2(SYS_inotify_rm_watch, @bitCast(usize, isize(fd)), @bitCast(usize, isize(wd)));
}
pub fn isatty(fd: i32) bool {
var wsz: winsize = undefined;
- return syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
+ return syscall3(SYS_ioctl, @bitCast(usize, isize(fd)), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -774,7 +774,7 @@ pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usiz
// TODO https://github.com/ziglang/zig/issues/265
pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
- return syscall4(SYS_readlinkat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
+ return syscall4(SYS_readlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -784,7 +784,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize {
// TODO https://github.com/ziglang/zig/issues/265
pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize {
- return syscall3(SYS_mkdirat, @intCast(usize, dirfd), @ptrToInt(path), mode);
+ return syscall3(SYS_mkdirat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -803,7 +803,7 @@ pub fn umount2(special: [*]const u8, flags: u32) usize {
}
pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
- return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @intCast(usize, fd), @bitCast(usize, offset));
+ return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
}
pub fn munmap(address: usize, length: usize) usize {
@@ -811,23 +811,23 @@ pub fn munmap(address: usize, length: usize) usize {
}
pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
- return syscall3(SYS_read, @intCast(usize, fd), @ptrToInt(buf), count);
+ return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
}
pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {
- return syscall4(SYS_preadv, @intCast(usize, fd), @ptrToInt(iov), count, offset);
+ return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
}
pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {
- return syscall3(SYS_readv, @intCast(usize, fd), @ptrToInt(iov), count);
+ return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
}
pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {
- return syscall3(SYS_writev, @intCast(usize, fd), @ptrToInt(iov), count);
+ return syscall3(SYS_writev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
}
pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize {
- return syscall4(SYS_pwritev, @intCast(usize, fd), @ptrToInt(iov), count, offset);
+ return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -842,12 +842,12 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
// TODO https://github.com/ziglang/zig/issues/265
pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
- return syscall3(SYS_symlinkat, @ptrToInt(existing), @intCast(usize, newfd), @ptrToInt(newpath));
+ return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(newfd)), @ptrToInt(newpath));
}
// TODO https://github.com/ziglang/zig/issues/265
pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
- return syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset);
+ return syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -856,7 +856,7 @@ pub fn access(path: [*]const u8, mode: u32) usize {
}
pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {
- return syscall3(SYS_faccessat, @intCast(usize, dirfd), @ptrToInt(path), mode);
+ return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
}
pub fn pipe(fd: *[2]i32) usize {
@@ -868,11 +868,11 @@ pub fn pipe2(fd: *[2]i32, flags: u32) usize {
}
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
- return syscall3(SYS_write, @intCast(usize, fd), @ptrToInt(buf), count);
+ return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
}
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
- return syscall4(SYS_pwrite, @intCast(usize, fd), @ptrToInt(buf), count, offset);
+ return syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -882,7 +882,7 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize {
// TODO https://github.com/ziglang/zig/issues/265
pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize {
- return syscall5(SYS_renameat2, @intCast(usize, oldfd), @ptrToInt(oldpath), @intCast(usize, newfd), @ptrToInt(newpath), flags);
+ return syscall5(SYS_renameat2, @bitCast(usize, isize(oldfd)), @ptrToInt(oldpath), @bitCast(usize, isize(newfd)), @ptrToInt(newpath), flags);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -897,7 +897,8 @@ pub fn create(path: [*]const u8, perm: usize) usize {
// TODO https://github.com/ziglang/zig/issues/265
pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize {
- return syscall4(SYS_openat, @intCast(usize, dirfd), @ptrToInt(path), flags, mode);
+ // dirfd could be negative, for example AT_FDCWD is -100
+ return syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode);
}
/// See also `clone` (from the arch-specific include)
@@ -911,11 +912,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
}
pub fn close(fd: i32) usize {
- return syscall1(SYS_close, @intCast(usize, fd));
+ return syscall1(SYS_close, @bitCast(usize, isize(fd)));
}
pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {
- return syscall3(SYS_lseek, @intCast(usize, fd), @bitCast(usize, offset), ref_pos);
+ return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), ref_pos);
}
pub fn exit(status: i32) noreturn {
@@ -933,7 +934,7 @@ pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
}
pub fn kill(pid: i32, sig: i32) usize {
- return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @intCast(usize, sig));
+ return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig)));
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -943,7 +944,7 @@ pub fn unlink(path: [*]const u8) usize {
// TODO https://github.com/ziglang/zig/issues/265
pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {
- return syscall3(SYS_unlinkat, @intCast(usize, dirfd), @ptrToInt(path), flags);
+ return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags);
}
pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
@@ -1120,8 +1121,8 @@ pub const empty_sigset = []usize{0} ** sigset_t.len;
pub fn raise(sig: i32) usize {
var set: sigset_t = undefined;
blockAppSignals(&set);
- const tid = @intCast(i32, syscall0(SYS_gettid));
- const ret = syscall2(SYS_tkill, @intCast(usize, tid), @intCast(usize, sig));
+ const tid = syscall0(SYS_gettid);
+ const ret = syscall2(SYS_tkill, tid, @bitCast(usize, isize(sig)));
restoreSignals(&set);
return ret;
}
@@ -1189,11 +1190,11 @@ pub const iovec_const = extern struct {
};
pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
- return syscall3(SYS_getsockname, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len));
+ return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
}
pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
- return syscall3(SYS_getpeername, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len));
+ return syscall3(SYS_getpeername, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
}
pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
@@ -1201,47 +1202,47 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
}
pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {
- return syscall5(SYS_setsockopt, @intCast(usize, fd), level, optname, @intCast(usize, optval), @ptrToInt(optlen));
+ return syscall5(SYS_setsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen));
}
pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
- return syscall5(SYS_getsockopt, @intCast(usize, fd), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
+ return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
}
pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize {
- return syscall3(SYS_sendmsg, @intCast(usize, fd), @ptrToInt(msg), flags);
+ return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
}
pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
- return syscall3(SYS_connect, @intCast(usize, fd), @ptrToInt(addr), len);
+ return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len);
}
pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
- return syscall3(SYS_recvmsg, @intCast(usize, fd), @ptrToInt(msg), flags);
+ return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
}
pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
- return syscall6(SYS_recvfrom, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
+ return syscall6(SYS_recvfrom, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
}
pub fn shutdown(fd: i32, how: i32) usize {
- return syscall2(SYS_shutdown, @intCast(usize, fd), @intCast(usize, how));
+ return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how)));
}
pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
- return syscall3(SYS_bind, @intCast(usize, fd), @ptrToInt(addr), @intCast(usize, len));
+ return syscall3(SYS_bind, @bitCast(usize, isize(fd)), @ptrToInt(addr), @intCast(usize, len));
}
pub fn listen(fd: i32, backlog: u32) usize {
- return syscall2(SYS_listen, @intCast(usize, fd), backlog);
+ return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog);
}
pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
- return syscall6(SYS_sendto, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
+ return syscall6(SYS_sendto, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
}
pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {
- return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(*fd[0]));
+ return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]));
}
pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
@@ -1249,11 +1250,11 @@ pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
}
pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize {
- return syscall4(SYS_accept4, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len), flags);
+ return syscall4(SYS_accept4, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len), flags);
}
pub fn fstat(fd: i32, stat_buf: *Stat) usize {
- return syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf));
+ return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf));
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -1268,7 +1269,7 @@ pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {
// TODO https://github.com/ziglang/zig/issues/265
pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize {
- return syscall4(SYS_fstatat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(stat_buf), flags);
+ return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -1355,7 +1356,7 @@ pub fn epoll_create1(flags: usize) usize {
}
pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
- return syscall4(SYS_epoll_ctl, @intCast(usize, epoll_fd), @intCast(usize, op), @intCast(usize, fd), @ptrToInt(ev));
+ return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev));
}
pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
@@ -1363,7 +1364,15 @@ pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout
}
pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {
- return syscall6(SYS_epoll_pwait, @intCast(usize, epoll_fd), @ptrToInt(events), @intCast(usize, maxevents), @intCast(usize, timeout), @ptrToInt(sigmask), @sizeOf(sigset_t));
+ return syscall6(
+ SYS_epoll_pwait,
+ @bitCast(usize, isize(epoll_fd)),
+ @ptrToInt(events),
+ @intCast(usize, maxevents),
+ @bitCast(usize, isize(timeout)),
+ @ptrToInt(sigmask),
+ @sizeOf(sigset_t),
+ );
}
pub fn eventfd(count: u32, flags: u32) usize {
@@ -1371,7 +1380,7 @@ pub fn eventfd(count: u32, flags: u32) usize {
}
pub fn timerfd_create(clockid: i32, flags: u32) usize {
- return syscall2(SYS_timerfd_create, @intCast(usize, clockid), flags);
+ return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags);
}
pub const itimerspec = extern struct {
@@ -1380,11 +1389,11 @@ pub const itimerspec = extern struct {
};
pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {
- return syscall2(SYS_timerfd_gettime, @intCast(usize, fd), @ptrToInt(curr_value));
+ return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value));
}
pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize {
- return syscall4(SYS_timerfd_settime, @intCast(usize, fd), flags, @ptrToInt(new_value), @ptrToInt(old_value));
+ return syscall4(SYS_timerfd_settime, @bitCast(usize, isize(fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value));
}
pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
diff --git a/std/os/path.zig b/std/os/path.zig
index b3cfec1a3a..e61a0f84bc 100644
--- a/std/os/path.zig
+++ b/std/os/path.zig
@@ -1093,6 +1093,7 @@ pub const RealError = error{
NoSpaceLeft,
FileSystem,
BadPathName,
+ DeviceBusy,
/// On Windows, file paths must be valid Unicode.
InvalidUtf8,
@@ -1183,11 +1184,20 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro
const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0);
defer os.close(fd);
- var buf: ["/proc/self/fd/-2147483648".len]u8 = undefined;
+ var buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined;
const proc_path = fmt.bufPrint(buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable;
return os.readLinkC(out_buffer, proc_path.ptr);
},
+ Os.freebsd => { // XXX requires fdescfs
+ const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0);
+ defer os.close(fd);
+
+ var buf: ["/dev/fd/-2147483648\x00".len]u8 = undefined;
+ const proc_path = fmt.bufPrint(buf[0..], "/dev/fd/{}\x00", fd) catch unreachable;
+
+ return os.readLinkC(out_buffer, proc_path.ptr);
+ },
else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
}
}
@@ -1202,7 +1212,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError!
const pathname_w = try windows_util.sliceToPrefixedFileW(pathname);
return realW(out_buffer, &pathname_w);
},
- Os.macosx, Os.ios, Os.linux => {
+ Os.macosx, Os.ios, Os.linux, Os.freebsd => {
const pathname_c = try os.toPosixPath(pathname);
return realC(out_buffer, &pathname_c);
},
diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig
index 7eec5faba9..202b8bffeb 100644
--- a/std/os/windows/kernel32.zig
+++ b/std/os/windows/kernel32.zig
@@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi
pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
-pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: [*]u8) BOOL;
+pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsW(penv: [*]u16) BOOL;
pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
@@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp
pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;
-pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8;
+pub extern "kernel32" stdcallcc fn GetEnvironmentStringsW() ?[*]u16;
-pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD;
+pub extern "kernel32" stdcallcc fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: LPWSTR, nSize: DWORD) DWORD;
pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;
diff --git a/std/os/zen.zig b/std/os/zen.zig
index 6ac480b890..76c4df9d62 100644
--- a/std/os/zen.zig
+++ b/std/os/zen.zig
@@ -12,20 +12,20 @@ pub const Message = struct {
args: [5]usize,
payload: ?[]const u8,
- pub fn from(mailbox_id: *const MailboxId) Message {
+ pub fn from(mailbox_id: MailboxId) Message {
return Message{
.sender = MailboxId.Undefined,
- .receiver = mailbox_id.*,
+ .receiver = mailbox_id,
.code = undefined,
.args = undefined,
.payload = null,
};
}
- pub fn to(mailbox_id: *const MailboxId, msg_code: usize, args: ...) Message {
+ pub fn to(mailbox_id: MailboxId, msg_code: usize, args: ...) Message {
var message = Message{
.sender = MailboxId.This,
- .receiver = mailbox_id.*,
+ .receiver = mailbox_id,
.code = msg_code,
.args = undefined,
.payload = null,
@@ -40,14 +40,14 @@ pub const Message = struct {
return message;
}
- pub fn as(self: *const Message, sender: *const MailboxId) Message {
- var message = self.*;
- message.sender = sender.*;
+ pub fn as(self: Message, sender: MailboxId) Message {
+ var message = self;
+ message.sender = sender;
return message;
}
- pub fn withPayload(self: *const Message, payload: []const u8) Message {
- var message = self.*;
+ pub fn withPayload(self: Message, payload: []const u8) Message {
+ var message = self;
message.payload = payload;
return message;
}
@@ -93,7 +93,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
STDIN_FILENO => {
var i: usize = 0;
while (i < count) : (i += 1) {
- send(Message.to(Server.Keyboard, 0));
+ send(&Message.to(Server.Keyboard, 0));
// FIXME: we should be certain that we are receiving from Keyboard.
var message = Message.from(MailboxId.This);
@@ -111,7 +111,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
switch (fd) {
STDOUT_FILENO, STDERR_FILENO => {
- send(Message.to(Server.Terminal, 1).withPayload(buf[0..count]));
+ send(&Message.to(Server.Terminal, 1).withPayload(buf[0..count]));
},
else => unreachable,
}
diff --git a/std/pdb.zig b/std/pdb.zig
index 17275ab2a5..0cfc6a6cda 100644
--- a/std/pdb.zig
+++ b/std/pdb.zig
@@ -34,6 +34,7 @@ pub const DbiStreamHeader = packed struct {
};
pub const SectionContribEntry = packed struct {
+ /// COFF Section index, 1-based
Section: u16,
Padding1: [2]u8,
Offset: u32,
@@ -507,11 +508,11 @@ const Msf = struct {
allocator,
);
- const stream_count = try self.directory.stream.readIntLe(u32);
+ const stream_count = try self.directory.stream.readIntLittle(u32);
const stream_sizes = try allocator.alloc(u32, stream_count);
for (stream_sizes) |*s| {
- const size = try self.directory.stream.readIntLe(u32);
+ const size = try self.directory.stream.readIntLittle(u32);
s.* = blockCountFromSize(size, superblock.BlockSize);
}
@@ -602,7 +603,7 @@ const MsfStream = struct {
var i: u32 = 0;
while (i < block_count) : (i += 1) {
- stream.blocks[i] = try in.readIntLe(u32);
+ stream.blocks[i] = try in.readIntLittle(u32);
}
return stream;
diff --git a/std/rand/index.zig b/std/rand/index.zig
index bb607a067e..c335063e64 100644
--- a/std/rand/index.zig
+++ b/std/rand/index.zig
@@ -5,7 +5,7 @@
// ```
// var buf: [8]u8 = undefined;
// try std.os.getRandomBytes(buf[0..]);
-// const seed = mem.readIntLE(u64, buf[0..8]);
+// const seed = mem.readIntSliceLittle(u64, buf[0..8]);
//
// var r = DefaultPrng.init(seed);
//
@@ -52,11 +52,24 @@ pub const Random = struct {
// use LE instead of native endian for better portability maybe?
// TODO: endian portability is pointless if the underlying prng isn't endian portable.
// TODO: document the endian portability of this library.
- const byte_aligned_result = mem.readIntLE(ByteAlignedT, rand_bytes);
+ const byte_aligned_result = mem.readIntSliceLittle(ByteAlignedT, rand_bytes);
const unsigned_result = @truncate(UnsignedT, byte_aligned_result);
return @bitCast(T, unsigned_result);
}
+ /// Constant-time implementation off ::uintLessThan.
+ /// The results of this function may be biased.
+ pub fn uintLessThanBiased(r: *Random, comptime T: type, less_than: T) T {
+ comptime assert(T.is_signed == false);
+ comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
+ assert(0 < less_than);
+ if (T.bit_count <= 32) {
+ return @intCast(T, limitRangeBiased(u32, r.int(u32), less_than));
+ } else {
+ return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));
+ }
+ }
+
/// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
/// This function assumes that the underlying ::fillFn produces evenly distributed values.
/// Within this assumption, the runtime of this function is exponentially distributed.
@@ -64,27 +77,52 @@ pub const Random = struct {
/// the runtime of this function would technically be unbounded.
/// However, if ::fillFn is backed by any evenly distributed pseudo random number generator,
/// this function is guaranteed to return.
- /// If you need deterministic runtime bounds, consider instead using `r.int(T) % less_than`,
- /// which will usually be biased toward smaller values.
+ /// If you need deterministic runtime bounds, use `::uintLessThanBiased`.
pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T {
- assert(T.is_signed == false);
+ comptime assert(T.is_signed == false);
+ comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
assert(0 < less_than);
-
- const last_group_size_minus_one: T = maxInt(T) % less_than;
- if (last_group_size_minus_one == less_than - 1) {
- // less_than is a power of two.
- assert(math.floorPowerOfTwo(T, less_than) == less_than);
- // There is no retry zone. The optimal retry_zone_start would be maxInt(T) + 1.
- return r.int(T) % less_than;
+ // Small is typically u32
+ const Small = @IntType(false, @divTrunc(T.bit_count + 31, 32) * 32);
+ // Large is typically u64
+ const Large = @IntType(false, Small.bit_count * 2);
+
+ // adapted from:
+ // http://www.pcg-random.org/posts/bounded-rands.html
+ // "Lemire's (with an extra tweak from me)"
+ var x: Small = r.int(Small);
+ var m: Large = Large(x) * Large(less_than);
+ var l: Small = @truncate(Small, m);
+ if (l < less_than) {
+ // TODO: workaround for https://github.com/ziglang/zig/issues/1770
+ // should be:
+ // var t: Small = -%less_than;
+ var t: Small = @bitCast(Small, -%@bitCast(@IntType(true, Small.bit_count), Small(less_than)));
+
+ if (t >= less_than) {
+ t -= less_than;
+ if (t >= less_than) {
+ t %= less_than;
+ }
+ }
+ while (l < t) {
+ x = r.int(Small);
+ m = Large(x) * Large(less_than);
+ l = @truncate(Small, m);
+ }
}
- const retry_zone_start = maxInt(T) - last_group_size_minus_one;
+ return @intCast(T, m >> Small.bit_count);
+ }
- while (true) {
- const rand_val = r.int(T);
- if (rand_val < retry_zone_start) {
- return rand_val % less_than;
- }
+ /// Constant-time implementation off ::uintAtMost.
+ /// The results of this function may be biased.
+ pub fn uintAtMostBiased(r: *Random, comptime T: type, at_most: T) T {
+ assert(T.is_signed == false);
+ if (at_most == maxInt(T)) {
+ // have the full range
+ return r.int(T);
}
+ return r.uintLessThanBiased(T, at_most + 1);
}
/// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.
@@ -99,6 +137,23 @@ pub const Random = struct {
return r.uintLessThan(T, at_most + 1);
}
+ /// Constant-time implementation off ::intRangeLessThan.
+ /// The results of this function may be biased.
+ pub fn intRangeLessThanBiased(r: *Random, comptime T: type, at_least: T, less_than: T) T {
+ assert(at_least < less_than);
+ if (T.is_signed) {
+ // Two's complement makes this math pretty easy.
+ const UnsignedT = @IntType(false, T.bit_count);
+ const lo = @bitCast(UnsignedT, at_least);
+ const hi = @bitCast(UnsignedT, less_than);
+ const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo);
+ return @bitCast(T, result);
+ } else {
+ // The signed implementation would work fine, but we can use stricter arithmetic operators here.
+ return at_least + r.uintLessThanBiased(T, less_than - at_least);
+ }
+ }
+
/// Returns an evenly distributed random integer `at_least <= i < less_than`.
/// See ::uintLessThan, which this function uses in most cases,
/// for commentary on the runtime of this function.
@@ -117,6 +172,23 @@ pub const Random = struct {
}
}
+ /// Constant-time implementation off ::intRangeAtMostBiased.
+ /// The results of this function may be biased.
+ pub fn intRangeAtMostBiased(r: *Random, comptime T: type, at_least: T, at_most: T) T {
+ assert(at_least <= at_most);
+ if (T.is_signed) {
+ // Two's complement makes this math pretty easy.
+ const UnsignedT = @IntType(false, T.bit_count);
+ const lo = @bitCast(UnsignedT, at_least);
+ const hi = @bitCast(UnsignedT, at_most);
+ const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo);
+ return @bitCast(T, result);
+ } else {
+ // The signed implementation would work fine, but we can use stricter arithmetic operators here.
+ return at_least + r.uintAtMostBiased(T, at_most - at_least);
+ }
+ }
+
/// Returns an evenly distributed random integer `at_least <= i <= at_most`.
/// See ::uintLessThan, which this function uses in most cases,
/// for commentary on the runtime of this function.
@@ -135,15 +207,11 @@ pub const Random = struct {
}
}
- /// Return a random integer/boolean type.
/// TODO: deprecated. use ::boolean or ::int instead.
pub fn scalar(r: *Random, comptime T: type) T {
- if (T == bool) return r.boolean();
- return r.int(T);
+ return if (T == bool) r.boolean() else r.int(T);
}
- /// Return a random integer with even distribution between `start`
- /// inclusive and `end` exclusive. `start` must be less than `end`.
/// TODO: deprecated. renamed to ::intRangeLessThan
pub fn range(r: *Random, comptime T: type, start: T, end: T) T {
return r.intRangeLessThan(T, start, end);
@@ -206,6 +274,20 @@ pub const Random = struct {
}
};
+/// Convert a random integer 0 <= random_int <= maxValue(T),
+/// into an integer 0 <= result < less_than.
+/// This function introduces a minor bias.
+pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T {
+ comptime assert(T.is_signed == false);
+ const T2 = @IntType(false, T.bit_count * 2);
+
+ // adapted from:
+ // http://www.pcg-random.org/posts/bounded-rands.html
+ // "Integer Multiplication (Biased)"
+ var m: T2 = T2(random_int) * T2(less_than);
+ return @intCast(T, m >> T.bit_count);
+}
+
const SequentialPrng = struct {
const Self = @This();
random: Random,
@@ -294,10 +376,19 @@ fn testRandomIntLessThan() void {
var r = SequentialPrng.init();
r.next_value = 0xff;
assert(r.random.uintLessThan(u8, 4) == 3);
- r.next_value = 0xff;
- assert(r.random.uintLessThan(u8, 3) == 0);
+ assert(r.next_value == 0);
+ assert(r.random.uintLessThan(u8, 4) == 0);
assert(r.next_value == 1);
+ r.next_value = 0;
+ assert(r.random.uintLessThan(u64, 32) == 0);
+
+ // trigger the bias rejection code path
+ r.next_value = 0;
+ assert(r.random.uintLessThan(u8, 3) == 0);
+ // verify we incremented twice
+ assert(r.next_value == 2);
+
r.next_value = 0xff;
assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);
r.next_value = 0xff;
@@ -311,16 +402,9 @@ fn testRandomIntLessThan() void {
assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1);
r.next_value = 0xff;
- assert(r.random.intRangeLessThan(i64, -0x8000000000000000, 0) == -1);
- r.next_value = 0xff;
assert(r.random.intRangeLessThan(i3, -4, 0) == -1);
r.next_value = 0xff;
assert(r.random.intRangeLessThan(i3, -2, 2) == 1);
-
- // test retrying and eventually getting a good value
- // start just out of bounds
- r.next_value = 0x81;
- assert(r.random.uintLessThan(u8, 0x81) == 0);
}
test "Random intAtMost" {
@@ -332,9 +416,14 @@ fn testRandomIntAtMost() void {
var r = SequentialPrng.init();
r.next_value = 0xff;
assert(r.random.uintAtMost(u8, 3) == 3);
- r.next_value = 0xff;
+ assert(r.next_value == 0);
+ assert(r.random.uintAtMost(u8, 3) == 0);
+
+ // trigger the bias rejection code path
+ r.next_value = 0;
assert(r.random.uintAtMost(u8, 2) == 0);
- assert(r.next_value == 1);
+ // verify we incremented twice
+ assert(r.next_value == 2);
r.next_value = 0xff;
assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);
@@ -349,16 +438,42 @@ fn testRandomIntAtMost() void {
assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1);
r.next_value = 0xff;
- assert(r.random.intRangeAtMost(i64, -0x8000000000000000, -1) == -1);
- r.next_value = 0xff;
assert(r.random.intRangeAtMost(i3, -4, -1) == -1);
r.next_value = 0xff;
assert(r.random.intRangeAtMost(i3, -2, 1) == 1);
- // test retrying and eventually getting a good value
- // start just out of bounds
- r.next_value = 0x81;
- assert(r.random.uintAtMost(u8, 0x80) == 0);
+ assert(r.random.uintAtMost(u0, 0) == 0);
+}
+
+test "Random Biased" {
+ var r = DefaultPrng.init(0);
+ // Not thoroughly checking the logic here.
+ // Just want to execute all the paths with different types.
+
+ assert(r.random.uintLessThanBiased(u1, 1) == 0);
+ assert(r.random.uintLessThanBiased(u32, 10) < 10);
+ assert(r.random.uintLessThanBiased(u64, 20) < 20);
+
+ assert(r.random.uintAtMostBiased(u0, 0) == 0);
+ assert(r.random.uintAtMostBiased(u1, 0) <= 0);
+ assert(r.random.uintAtMostBiased(u32, 10) <= 10);
+ assert(r.random.uintAtMostBiased(u64, 20) <= 20);
+
+ assert(r.random.intRangeLessThanBiased(u1, 0, 1) == 0);
+ assert(r.random.intRangeLessThanBiased(i1, -1, 0) == -1);
+ assert(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10);
+ assert(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10);
+ assert(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20);
+ assert(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20);
+
+ // uncomment for broken module error:
+ //assert(r.random.intRangeAtMostBiased(u0, 0, 0) == 0);
+ assert(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0);
+ assert(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1);
+ assert(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10);
+ assert(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10);
+ assert(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20);
+ assert(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20);
}
// Generator to extend 64-bit seed values into longer sequences.
@@ -870,12 +985,16 @@ test "Random range" {
}
fn testRange(r: *Random, start: i8, end: i8) void {
+ testRangeBias(r, start, end, true);
+ testRangeBias(r, start, end, false);
+}
+fn testRangeBias(r: *Random, start: i8, end: i8, biased: bool) void {
const count = @intCast(usize, i32(end) - i32(start));
var values_buffer = []bool{false} ** 0x100;
const values = values_buffer[0..count];
var i: usize = 0;
while (i < count) {
- const value: i32 = r.intRangeLessThan(i8, start, end);
+ const value: i32 = if (biased) r.intRangeLessThanBiased(i8, start, end) else r.intRangeLessThan(i8, start, end);
const index = @intCast(usize, value - start);
if (!values[index]) {
i += 1;
diff --git a/std/rand/ziggurat.zig b/std/rand/ziggurat.zig
index f7a1359f17..0636a5bfc4 100644
--- a/std/rand/ziggurat.zig
+++ b/std/rand/ziggurat.zig
@@ -12,7 +12,7 @@ const std = @import("../index.zig");
const math = std.math;
const Random = std.rand.Random;
-pub fn next_f64(random: *Random, comptime tables: *const ZigTable) f64 {
+pub fn next_f64(random: *Random, comptime tables: ZigTable) f64 {
while (true) {
// We manually construct a float from parts as we can avoid an extra random lookup here by
// using the unused exponent for the lookup table entry.
diff --git a/std/segmented_list.zig b/std/segmented_list.zig
index c7c39651c9..d786e0becd 100644
--- a/std/segmented_list.zig
+++ b/std/segmented_list.zig
@@ -201,6 +201,11 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
self.dynamic_segments = self.allocator.shrink([*]T, self.dynamic_segments, new_cap_shelf_count);
}
+ pub fn shrink(self: *Self, new_len: usize) void {
+ assert(new_len <= self.len);
+ self.len = new_len;
+ }
+
pub fn uncheckedAt(self: var, index: usize) AtType(@typeOf(self)) {
if (index < prealloc_item_count) {
return &self.prealloc_segment[index];
diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig
index 53c646abdc..a15be317ab 100644
--- a/std/special/bootstrap.zig
+++ b/std/special/bootstrap.zig
@@ -20,10 +20,17 @@ comptime {
nakedcc fn _start() noreturn {
switch (builtin.arch) {
- builtin.Arch.x86_64 => {
- argc_ptr = asm ("lea (%%rsp), %[argc]"
- : [argc] "=r" (-> [*]usize)
- );
+ builtin.Arch.x86_64 => switch (builtin.os) {
+ builtin.Os.freebsd => {
+ argc_ptr = asm ("lea (%%rdi), %[argc]"
+ : [argc] "=r" (-> [*]usize)
+ );
+ },
+ else => {
+ argc_ptr = asm ("lea (%%rsp), %[argc]"
+ : [argc] "=r" (-> [*]usize)
+ );
+ },
},
builtin.Arch.i386 => {
argc_ptr = asm ("lea (%%esp), %[argc]"
@@ -50,6 +57,9 @@ extern fn WinMainCRTStartup() noreturn {
// TODO https://github.com/ziglang/zig/issues/265
fn posixCallMainAndExit() noreturn {
+ if (builtin.os == builtin.Os.freebsd) {
+ @setAlignStack(16);
+ }
const argc = argc_ptr[0];
const argv = @ptrCast([*][*]u8, argc_ptr + 1);
diff --git a/std/special/build_runner.zig b/std/special/build_runner.zig
index 15e3534380..ff3b53619d 100644
--- a/std/special/build_runner.zig
+++ b/std/special/build_runner.zig
@@ -164,7 +164,6 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
\\
\\General Options:
\\ --help Print this help and exit
- \\ --init Generate a build.zig template
\\ --verbose Print commands before executing them
\\ --prefix [path] Override default install prefix
\\ --search-prefix [path] Add a path to look for binaries, libraries, headers
diff --git a/std/special/compiler_rt/fixdfdi.zig b/std/special/compiler_rt/fixdfdi.zig
new file mode 100644
index 0000000000..c108fd15aa
--- /dev/null
+++ b/std/special/compiler_rt/fixdfdi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixdfdi(a: f64) i64 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f64, i64, a);
+}
+
+test "import fixdfdi" {
+ _ = @import("fixdfdi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixdfdi_test.zig b/std/special/compiler_rt/fixdfdi_test.zig
new file mode 100644
index 0000000000..72bcf452d2
--- /dev/null
+++ b/std/special/compiler_rt/fixdfdi_test.zig
@@ -0,0 +1,66 @@
+const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
+const std = @import("std");
+const math = std.math;
+const assert = std.debug.assert;
+const warn = std.debug.warn;
+
+fn test__fixdfdi(a: f64, expected: i64) void {
+ const x = __fixdfdi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u64, expected));
+ assert(x == expected);
+}
+
+test "fixdfdi" {
+ //warn("\n");
+
+ test__fixdfdi(-math.f64_max, math.minInt(i64));
+
+ test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
+ test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
+
+ test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000);
+ test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
+ test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
+
+ test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000);
+ test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
+ test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
+
+ test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
+ test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
+
+ test__fixdfdi(-2.01, -2);
+ test__fixdfdi(-2.0, -2);
+ test__fixdfdi(-1.99, -1);
+ test__fixdfdi(-1.0, -1);
+ test__fixdfdi(-0.99, 0);
+ test__fixdfdi(-0.5, 0);
+ test__fixdfdi(-math.f64_min, 0);
+ test__fixdfdi(0.0, 0);
+ test__fixdfdi(math.f64_min, 0);
+ test__fixdfdi(0.5, 0);
+ test__fixdfdi(0.99, 0);
+ test__fixdfdi(1.0, 1);
+ test__fixdfdi(1.5, 1);
+ test__fixdfdi(1.99, 1);
+ test__fixdfdi(2.0, 2);
+ test__fixdfdi(2.01, 2);
+
+ test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+
+ test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
+ test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
+ test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
+ test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
+ test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
+
+ test__fixdfdi(math.f64_max, math.maxInt(i64));
+}
diff --git a/std/special/compiler_rt/fixdfsi.zig b/std/special/compiler_rt/fixdfsi.zig
new file mode 100644
index 0000000000..83a17b2b0d
--- /dev/null
+++ b/std/special/compiler_rt/fixdfsi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixdfsi(a: f64) i32 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f64, i32, a);
+}
+
+test "import fixdfsi" {
+ _ = @import("fixdfsi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixdfsi_test.zig b/std/special/compiler_rt/fixdfsi_test.zig
new file mode 100644
index 0000000000..147f46534a
--- /dev/null
+++ b/std/special/compiler_rt/fixdfsi_test.zig
@@ -0,0 +1,74 @@
+const __fixdfsi = @import("fixdfsi.zig").__fixdfsi;
+const std = @import("std");
+const math = std.math;
+const assert = std.debug.assert;
+const warn = std.debug.warn;
+
+fn test__fixdfsi(a: f64, expected: i32) void {
+ const x = __fixdfsi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u32, expected));
+ assert(x == expected);
+}
+
+test "fixdfsi" {
+ //warn("\n");
+
+ test__fixdfsi(-math.f64_max, math.minInt(i32));
+
+ test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
+ test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
+
+ test__fixdfsi(-0x1.0000000000000p+127, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
+
+ test__fixdfsi(-0x1.0000000000001p+63, -0x80000000);
+ test__fixdfsi(-0x1.0000000000000p+63, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
+
+ test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000);
+
+ test__fixdfsi(-0x1.000000p+31, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
+ test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
+
+ test__fixdfsi(-2.01, -2);
+ test__fixdfsi(-2.0, -2);
+ test__fixdfsi(-1.99, -1);
+ test__fixdfsi(-1.0, -1);
+ test__fixdfsi(-0.99, 0);
+ test__fixdfsi(-0.5, 0);
+ test__fixdfsi(-math.f64_min, 0);
+ test__fixdfsi(0.0, 0);
+ test__fixdfsi(math.f64_min, 0);
+ test__fixdfsi(0.5, 0);
+ test__fixdfsi(0.99, 0);
+ test__fixdfsi(1.0, 1);
+ test__fixdfsi(1.5, 1);
+ test__fixdfsi(1.99, 1);
+ test__fixdfsi(2.0, 2);
+ test__fixdfsi(2.01, 2);
+
+ test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
+ test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
+ test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF);
+
+ test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
+ test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
+
+ test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
+ test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
+ test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
+ test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
+
+ test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
+ test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
+ test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
+
+ test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
+ test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
+
+ test__fixdfsi(math.f64_max, math.maxInt(i32));
+}
diff --git a/std/special/compiler_rt/fixdfti.zig b/std/special/compiler_rt/fixdfti.zig
new file mode 100644
index 0000000000..e30f885cf6
--- /dev/null
+++ b/std/special/compiler_rt/fixdfti.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixdfti(a: f64) i128 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f64, i128, a);
+}
+
+test "import fixdfti" {
+ _ = @import("fixdfti_test.zig");
+}
diff --git a/std/special/compiler_rt/fixdfti_test.zig b/std/special/compiler_rt/fixdfti_test.zig
new file mode 100644
index 0000000000..5bb3a31a3f
--- /dev/null
+++ b/std/special/compiler_rt/fixdfti_test.zig
@@ -0,0 +1,66 @@
+const __fixdfti = @import("fixdfti.zig").__fixdfti;
+const std = @import("std");
+const math = std.math;
+const assert = std.debug.assert;
+const warn = std.debug.warn;
+
+fn test__fixdfti(a: f64, expected: i128) void {
+ const x = __fixdfti(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u128, expected));
+ assert(x == expected);
+}
+
+test "fixdfti" {
+ //warn("\n");
+
+ test__fixdfti(-math.f64_max, math.minInt(i128));
+
+ test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
+ test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
+
+ test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
+ test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
+ test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
+
+ test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800);
+ test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
+ test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
+
+ test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
+ test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
+
+ test__fixdfti(-2.01, -2);
+ test__fixdfti(-2.0, -2);
+ test__fixdfti(-1.99, -1);
+ test__fixdfti(-1.0, -1);
+ test__fixdfti(-0.99, 0);
+ test__fixdfti(-0.5, 0);
+ test__fixdfti(-math.f64_min, 0);
+ test__fixdfti(0.0, 0);
+ test__fixdfti(math.f64_min, 0);
+ test__fixdfti(0.5, 0);
+ test__fixdfti(0.99, 0);
+ test__fixdfti(1.0, 1);
+ test__fixdfti(1.5, 1);
+ test__fixdfti(1.99, 1);
+ test__fixdfti(2.0, 2);
+ test__fixdfti(2.01, 2);
+
+ test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+
+ test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
+ test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
+ test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000);
+ test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800);
+
+ test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
+ test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
+ test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+
+ test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
+
+ test__fixdfti(math.f64_max, math.maxInt(i128));
+}
diff --git a/std/special/compiler_rt/fixint.zig b/std/special/compiler_rt/fixint.zig
new file mode 100644
index 0000000000..fd31798cc2
--- /dev/null
+++ b/std/special/compiler_rt/fixint.zig
@@ -0,0 +1,74 @@
+const is_test = @import("builtin").is_test;
+const std = @import("std");
+const math = std.math;
+const Log2Int = std.math.Log2Int;
+const maxInt = std.math.maxInt;
+const minInt = std.math.minInt;
+
+const DBG = false;
+
+pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t {
+ @setRuntimeSafety(is_test);
+
+ const rep_t = switch (fp_t) {
+ f32 => u32,
+ f64 => u64,
+ f128 => u128,
+ else => unreachable,
+ };
+ const significandBits = switch (fp_t) {
+ f32 => 23,
+ f64 => 52,
+ f128 => 112,
+ else => unreachable,
+ };
+
+ const typeWidth = rep_t.bit_count;
+ const exponentBits = (typeWidth - significandBits - 1);
+ const signBit = (rep_t(1) << (significandBits + exponentBits));
+ const maxExponent = ((1 << exponentBits) - 1);
+ const exponentBias = (maxExponent >> 1);
+
+ const implicitBit = (rep_t(1) << significandBits);
+ const significandMask = (implicitBit - 1);
+
+ // Break a into sign, exponent, significand
+ const aRep: rep_t = @bitCast(rep_t, a);
+ const absMask = signBit - 1;
+ const aAbs: rep_t = aRep & absMask;
+
+ const negative = (aRep & signBit) != 0;
+ const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias;
+ const significand: rep_t = (aAbs & significandMask) | implicitBit;
+
+ // If exponent is negative, the uint_result is zero.
+ if (exponent < 0) return 0;
+
+ // The unsigned result needs to be large enough to handle an fixint_t or rep_t
+ const fixuint_t = @IntType(false, fixint_t.bit_count);
+ const UintResultType = if (fixint_t.bit_count > rep_t.bit_count) fixuint_t else rep_t;
+ var uint_result: UintResultType = undefined;
+
+ // If the value is too large for the integer type, saturate.
+ if (@intCast(usize, exponent) >= fixint_t.bit_count) {
+ return if (negative) fixint_t(minInt(fixint_t)) else fixint_t(maxInt(fixint_t));
+ }
+
+ // If 0 <= exponent < significandBits, right shift else left shift
+ if (exponent < significandBits) {
+ uint_result = @intCast(UintResultType, significand) >> @intCast(Log2Int(UintResultType), significandBits - exponent);
+ } else {
+ uint_result = @intCast(UintResultType, significand) << @intCast(Log2Int(UintResultType), exponent - significandBits);
+ }
+
+ // Cast to final signed result
+ if (negative) {
+ return if (uint_result >= -math.minInt(fixint_t)) math.minInt(fixint_t) else -@intCast(fixint_t, uint_result);
+ } else {
+ return if (uint_result >= math.maxInt(fixint_t)) math.maxInt(fixint_t) else @intCast(fixint_t, uint_result);
+ }
+}
+
+test "import fixint" {
+ _ = @import("fixint_test.zig");
+}
diff --git a/std/special/compiler_rt/fixint_test.zig b/std/special/compiler_rt/fixint_test.zig
new file mode 100644
index 0000000000..6676bddbee
--- /dev/null
+++ b/std/special/compiler_rt/fixint_test.zig
@@ -0,0 +1,152 @@
+const is_test = @import("builtin").is_test;
+const std = @import("std");
+const math = std.math;
+const assert = std.debug.assert;
+const warn = std.debug.warn;
+
+const fixint = @import("fixint.zig").fixint;
+
+fn test__fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t, expected: fixint_t) void {
+ const x = fixint(fp_t, fixint_t, a);
+ //warn("a={} x={}:{x} expected={}:{x})\n", a, x, x, expected, expected);
+ assert(x == expected);
+}
+
+test "fixint.i1" {
+ test__fixint(f32, i1, -math.inf_f32, -1);
+ test__fixint(f32, i1, -math.f32_max, -1);
+ test__fixint(f32, i1, -2.0, -1);
+ test__fixint(f32, i1, -1.1, -1);
+ test__fixint(f32, i1, -1.0, -1);
+ test__fixint(f32, i1, -0.9, 0);
+ test__fixint(f32, i1, -0.1, 0);
+ test__fixint(f32, i1, -math.f32_min, 0);
+ test__fixint(f32, i1, -0.0, 0);
+ test__fixint(f32, i1, 0.0, 0);
+ test__fixint(f32, i1, math.f32_min, 0);
+ test__fixint(f32, i1, 0.1, 0);
+ test__fixint(f32, i1, 0.9, 0);
+ test__fixint(f32, i1, 1.0, 0);
+ test__fixint(f32, i1, 2.0, 0);
+ test__fixint(f32, i1, math.f32_max, 0);
+ test__fixint(f32, i1, math.inf_f32, 0);
+}
+
+test "fixint.i2" {
+ test__fixint(f32, i2, -math.inf_f32, -2);
+ test__fixint(f32, i2, -math.f32_max, -2);
+ test__fixint(f32, i2, -2.0, -2);
+ test__fixint(f32, i2, -1.9, -1);
+ test__fixint(f32, i2, -1.1, -1);
+ test__fixint(f32, i2, -1.0, -1);
+ test__fixint(f32, i2, -0.9, 0);
+ test__fixint(f32, i2, -0.1, 0);
+ test__fixint(f32, i2, -math.f32_min, 0);
+ test__fixint(f32, i2, -0.0, 0);
+ test__fixint(f32, i2, 0.0, 0);
+ test__fixint(f32, i2, math.f32_min, 0);
+ test__fixint(f32, i2, 0.1, 0);
+ test__fixint(f32, i2, 0.9, 0);
+ test__fixint(f32, i2, 1.0, 1);
+ test__fixint(f32, i2, 2.0, 1);
+ test__fixint(f32, i2, math.f32_max, 1);
+ test__fixint(f32, i2, math.inf_f32, 1);
+}
+
+test "fixint.i3" {
+ test__fixint(f32, i3, -math.inf_f32, -4);
+ test__fixint(f32, i3, -math.f32_max, -4);
+ test__fixint(f32, i3, -4.0, -4);
+ test__fixint(f32, i3, -3.0, -3);
+ test__fixint(f32, i3, -2.0, -2);
+ test__fixint(f32, i3, -1.9, -1);
+ test__fixint(f32, i3, -1.1, -1);
+ test__fixint(f32, i3, -1.0, -1);
+ test__fixint(f32, i3, -0.9, 0);
+ test__fixint(f32, i3, -0.1, 0);
+ test__fixint(f32, i3, -math.f32_min, 0);
+ test__fixint(f32, i3, -0.0, 0);
+ test__fixint(f32, i3, 0.0, 0);
+ test__fixint(f32, i3, math.f32_min, 0);
+ test__fixint(f32, i3, 0.1, 0);
+ test__fixint(f32, i3, 0.9, 0);
+ test__fixint(f32, i3, 1.0, 1);
+ test__fixint(f32, i3, 2.0, 2);
+ test__fixint(f32, i3, 3.0, 3);
+ test__fixint(f32, i3, 4.0, 3);
+ test__fixint(f32, i3, math.f32_max, 3);
+ test__fixint(f32, i3, math.inf_f32, 3);
+}
+
+test "fixint.i32" {
+ test__fixint(f64, i32, -math.inf_f64, math.minInt(i32));
+ test__fixint(f64, i32, -math.f64_max, math.minInt(i32));
+ test__fixint(f64, i32, f64(math.minInt(i32)), math.minInt(i32));
+ test__fixint(f64, i32, f64(math.minInt(i32))+1, math.minInt(i32)+1);
+ test__fixint(f64, i32, -2.0, -2);
+ test__fixint(f64, i32, -1.9, -1);
+ test__fixint(f64, i32, -1.1, -1);
+ test__fixint(f64, i32, -1.0, -1);
+ test__fixint(f64, i32, -0.9, 0);
+ test__fixint(f64, i32, -0.1, 0);
+ test__fixint(f64, i32, -math.f32_min, 0);
+ test__fixint(f64, i32, -0.0, 0);
+ test__fixint(f64, i32, 0.0, 0);
+ test__fixint(f64, i32, math.f32_min, 0);
+ test__fixint(f64, i32, 0.1, 0);
+ test__fixint(f64, i32, 0.9, 0);
+ test__fixint(f64, i32, 1.0, 1);
+ test__fixint(f64, i32, f64(math.maxInt(i32))-1, math.maxInt(i32)-1);
+ test__fixint(f64, i32, f64(math.maxInt(i32)), math.maxInt(i32));
+ test__fixint(f64, i32, math.f64_max, math.maxInt(i32));
+ test__fixint(f64, i32, math.inf_f64, math.maxInt(i32));
+}
+
+test "fixint.i64" {
+ test__fixint(f64, i64, -math.inf_f64, math.minInt(i64));
+ test__fixint(f64, i64, -math.f64_max, math.minInt(i64));
+ test__fixint(f64, i64, f64(math.minInt(i64)), math.minInt(i64));
+ test__fixint(f64, i64, f64(math.minInt(i64))+1, math.minInt(i64));
+ test__fixint(f64, i64, f64(math.minInt(i64)/2), math.minInt(i64)/2);
+ test__fixint(f64, i64, -2.0, -2);
+ test__fixint(f64, i64, -1.9, -1);
+ test__fixint(f64, i64, -1.1, -1);
+ test__fixint(f64, i64, -1.0, -1);
+ test__fixint(f64, i64, -0.9, 0);
+ test__fixint(f64, i64, -0.1, 0);
+ test__fixint(f64, i64, -math.f32_min, 0);
+ test__fixint(f64, i64, -0.0, 0);
+ test__fixint(f64, i64, 0.0, 0);
+ test__fixint(f64, i64, math.f32_min, 0);
+ test__fixint(f64, i64, 0.1, 0);
+ test__fixint(f64, i64, 0.9, 0);
+ test__fixint(f64, i64, 1.0, 1);
+ test__fixint(f64, i64, f64(math.maxInt(i64))-1, math.maxInt(i64));
+ test__fixint(f64, i64, f64(math.maxInt(i64)), math.maxInt(i64));
+ test__fixint(f64, i64, math.f64_max, math.maxInt(i64));
+ test__fixint(f64, i64, math.inf_f64, math.maxInt(i64));
+}
+
+test "fixint.i128" {
+ test__fixint(f64, i128, -math.inf_f64, math.minInt(i128));
+ test__fixint(f64, i128, -math.f64_max, math.minInt(i128));
+ test__fixint(f64, i128, f64(math.minInt(i128)), math.minInt(i128));
+ test__fixint(f64, i128, f64(math.minInt(i128))+1, math.minInt(i128));
+ test__fixint(f64, i128, -2.0, -2);
+ test__fixint(f64, i128, -1.9, -1);
+ test__fixint(f64, i128, -1.1, -1);
+ test__fixint(f64, i128, -1.0, -1);
+ test__fixint(f64, i128, -0.9, 0);
+ test__fixint(f64, i128, -0.1, 0);
+ test__fixint(f64, i128, -math.f32_min, 0);
+ test__fixint(f64, i128, -0.0, 0);
+ test__fixint(f64, i128, 0.0, 0);
+ test__fixint(f64, i128, math.f32_min, 0);
+ test__fixint(f64, i128, 0.1, 0);
+ test__fixint(f64, i128, 0.9, 0);
+ test__fixint(f64, i128, 1.0, 1);
+ test__fixint(f64, i128, f64(math.maxInt(i128))-1, math.maxInt(i128));
+ test__fixint(f64, i128, f64(math.maxInt(i128)), math.maxInt(i128));
+ test__fixint(f64, i128, math.f64_max, math.maxInt(i128));
+ test__fixint(f64, i128, math.inf_f64, math.maxInt(i128));
+}
diff --git a/std/special/compiler_rt/fixsfdi.zig b/std/special/compiler_rt/fixsfdi.zig
new file mode 100644
index 0000000000..ffa81d13ab
--- /dev/null
+++ b/std/special/compiler_rt/fixsfdi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixsfdi(a: f32) i64 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f32, i64, a);
+}
+
+test "import fixsfdi" {
+ _ = @import("fixsfdi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixsfdi_test.zig b/std/special/compiler_rt/fixsfdi_test.zig
new file mode 100644
index 0000000000..ef8e50e38e
--- /dev/null
+++ b/std/special/compiler_rt/fixsfdi_test.zig
@@ -0,0 +1,68 @@
+const __fixsfdi = @import("fixsfdi.zig").__fixsfdi;
+const std = @import("std");
+const math = std.math;
+const assert = std.debug.assert;
+const warn = std.debug.warn;
+
+fn test__fixsfdi(a: f32, expected: i64) void {
+ const x = __fixsfdi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u64, expected));
+ assert(x == expected);
+}
+
+test "fixsfdi" {
+ //warn("\n");
+
+ test__fixsfdi(-math.f32_max, math.minInt(i64));
+
+ test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
+ test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
+
+ test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000);
+ test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
+ test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
+
+ test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000);
+ test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
+ test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
+
+ test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000);
+ test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
+ test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
+
+ test__fixsfdi(-2.01, -2);
+ test__fixsfdi(-2.0, -2);
+ test__fixsfdi(-1.99, -1);
+ test__fixsfdi(-1.0, -1);
+ test__fixsfdi(-0.99, 0);
+ test__fixsfdi(-0.5, 0);
+ test__fixsfdi(-math.f32_min, 0);
+ test__fixsfdi(0.0, 0);
+ test__fixsfdi(math.f32_min, 0);
+ test__fixsfdi(0.5, 0);
+ test__fixsfdi(0.99, 0);
+ test__fixsfdi(1.0, 1);
+ test__fixsfdi(1.5, 1);
+ test__fixsfdi(1.99, 1);
+ test__fixsfdi(2.0, 2);
+ test__fixsfdi(2.01, 2);
+
+ test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+ test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
+
+ test__fixsfdi(math.f64_max, math.maxInt(i64));
+}
diff --git a/std/special/compiler_rt/fixsfsi.zig b/std/special/compiler_rt/fixsfsi.zig
new file mode 100644
index 0000000000..9a94b4395b
--- /dev/null
+++ b/std/special/compiler_rt/fixsfsi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixsfsi(a: f32) i32 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f32, i32, a);
+}
+
+test "import fixsfsi" {
+ _ = @import("fixsfsi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixsfsi_test.zig b/std/special/compiler_rt/fixsfsi_test.zig
new file mode 100644
index 0000000000..d5c0ba5c2a
--- /dev/null
+++ b/std/special/compiler_rt/fixsfsi_test.zig
@@ -0,0 +1,76 @@
+const __fixsfsi = @import("fixsfsi.zig").__fixsfsi;
+const std = @import("std");
+const math = std.math;
+const assert = std.debug.assert;
+const warn = std.debug.warn;
+
+fn test__fixsfsi(a: f32, expected: i32) void {
+ const x = __fixsfsi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u32, expected));
+ assert(x == expected);
+}
+
+test "fixsfsi" {
+ //warn("\n");
+
+ test__fixsfsi(-math.f32_max, math.minInt(i32));
+
+ test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
+ test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
+
+ test__fixsfsi(-0x1.0000000000000p+127, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
+
+ test__fixsfsi(-0x1.0000000000001p+63, -0x80000000);
+ test__fixsfsi(-0x1.0000000000000p+63, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
+
+ test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000);
+
+ test__fixsfsi(-0x1.000000p+31, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
+ test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);
+
+ test__fixsfsi(-2.01, -2);
+ test__fixsfsi(-2.0, -2);
+ test__fixsfsi(-1.99, -1);
+ test__fixsfsi(-1.0, -1);
+ test__fixsfsi(-0.99, 0);
+ test__fixsfsi(-0.5, 0);
+ test__fixsfsi(-math.f32_min, 0);
+ test__fixsfsi(0.0, 0);
+ test__fixsfsi(math.f32_min, 0);
+ test__fixsfsi(0.5, 0);
+ test__fixsfsi(0.99, 0);
+ test__fixsfsi(1.0, 1);
+ test__fixsfsi(1.5, 1);
+ test__fixsfsi(1.99, 1);
+ test__fixsfsi(2.0, 2);
+ test__fixsfsi(2.01, 2);
+
+ test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
+ test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
+ test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF);
+ test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF);
+
+ test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
+ test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
+
+ test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
+ test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
+ test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
+ test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
+
+ test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
+ test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
+ test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
+
+ test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
+ test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
+
+ test__fixsfsi(math.f32_max, math.maxInt(i32));
+}
diff --git a/std/special/compiler_rt/fixsfti.zig b/std/special/compiler_rt/fixsfti.zig
new file mode 100644
index 0000000000..806a1678aa
--- /dev/null
+++ b/std/special/compiler_rt/fixsfti.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixsfti(a: f32) i128 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f32, i128, a);
+}
+
+test "import fixsfti" {
+ _ = @import("fixsfti_test.zig");
+}
diff --git a/std/special/compiler_rt/fixsfti_test.zig b/std/special/compiler_rt/fixsfti_test.zig
new file mode 100644
index 0000000000..d693143b18
--- /dev/null
+++ b/std/special/compiler_rt/fixsfti_test.zig
@@ -0,0 +1,84 @@
+const __fixsfti = @import("fixsfti.zig").__fixsfti;
+const std = @import("std");
+const math = std.math;
+const assert = std.debug.assert;
+const warn = std.debug.warn;
+
+fn test__fixsfti(a: f32, expected: i128) void {
+ const x = __fixsfti(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u128({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u128, expected));
+ assert(x == expected);
+}
+
+test "fixsfti" {
+ //warn("\n");
+
+ test__fixsfti(-math.f32_max, math.minInt(i128));
+
+ test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
+ test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
+
+ test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
+ test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000);
+ test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000);
+ test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000);
+ test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000);
+ test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000);
+
+ test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000);
+ test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
+ test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
+
+ test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000);
+ test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
+ test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
+
+ test__fixsfti(-0x1.000000p+31, -0x80000000);
+ test__fixsfti(-0x1.FFFFFFp+30, -0x80000000);
+ test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80);
+ test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00);
+
+ test__fixsfti(-2.01, -2);
+ test__fixsfti(-2.0, -2);
+ test__fixsfti(-1.99, -1);
+ test__fixsfti(-1.0, -1);
+ test__fixsfti(-0.99, 0);
+ test__fixsfti(-0.5, 0);
+ test__fixsfti(-math.f32_min, 0);
+ test__fixsfti(0.0, 0);
+ test__fixsfti(math.f32_min, 0);
+ test__fixsfti(0.5, 0);
+ test__fixsfti(0.99, 0);
+ test__fixsfti(1.0, 1);
+ test__fixsfti(1.5, 1);
+ test__fixsfti(1.99, 1);
+ test__fixsfti(2.0, 2);
+ test__fixsfti(2.01, 2);
+
+ test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00);
+ test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80);
+ test__fixsfti(0x1.FFFFFFp+30, 0x80000000);
+ test__fixsfti(0x1.000000p+31, 0x80000000);
+
+ test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+ test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000);
+
+ test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000);
+ test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000);
+ test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000);
+ test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000);
+
+ test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000);
+ test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000);
+ test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+
+ test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
+
+ test__fixsfti(math.f32_max, math.maxInt(i128));
+}
diff --git a/std/special/compiler_rt/fixtfdi.zig b/std/special/compiler_rt/fixtfdi.zig
new file mode 100644
index 0000000000..8d99231b74
--- /dev/null
+++ b/std/special/compiler_rt/fixtfdi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixtfdi(a: f128) i64 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f128, i64, a);
+}
+
+test "import fixtfdi" {
+ _ = @import("fixtfdi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixtfdi_test.zig b/std/special/compiler_rt/fixtfdi_test.zig
new file mode 100644
index 0000000000..58ccbc5832
--- /dev/null
+++ b/std/special/compiler_rt/fixtfdi_test.zig
@@ -0,0 +1,76 @@
+const __fixtfdi = @import("fixtfdi.zig").__fixtfdi;
+const std = @import("std");
+const math = std.math;
+const assert = std.debug.assert;
+const warn = std.debug.warn;
+
+fn test__fixtfdi(a: f128, expected: i64) void {
+ const x = __fixtfdi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u64, expected));
+ assert(x == expected);
+}
+
+test "fixtfdi" {
+ //warn("\n");
+
+ test__fixtfdi(-math.f128_max, math.minInt(i64));
+
+ test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
+ test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
+
+ test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000);
+ test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
+ test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
+
+ test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000);
+ test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
+ test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
+
+ test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000);
+ test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000);
+
+ test__fixtfdi(-0x1.000000p+31, -0x80000000);
+ test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
+ test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80);
+ test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00);
+
+ test__fixtfdi(-2.01, -2);
+ test__fixtfdi(-2.0, -2);
+ test__fixtfdi(-1.99, -1);
+ test__fixtfdi(-1.0, -1);
+ test__fixtfdi(-0.99, 0);
+ test__fixtfdi(-0.5, 0);
+ test__fixtfdi(-math.f64_min, 0);
+ test__fixtfdi(0.0, 0);
+ test__fixtfdi(math.f64_min, 0);
+ test__fixtfdi(0.5, 0);
+ test__fixtfdi(0.99, 0);
+ test__fixtfdi(1.0, 1);
+ test__fixtfdi(1.5, 1);
+ test__fixtfdi(1.99, 1);
+ test__fixtfdi(2.0, 2);
+ test__fixtfdi(2.01, 2);
+
+ test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00);
+ test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80);
+ test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0);
+ test__fixtfdi(0x1.000000p+31, 0x80000000);
+
+ test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+
+ test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
+ test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
+ test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
+ test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
+ test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
+
+ test__fixtfdi(math.f128_max, math.maxInt(i64));
+}
diff --git a/std/special/compiler_rt/fixtfsi.zig b/std/special/compiler_rt/fixtfsi.zig
new file mode 100644
index 0000000000..f3f83634b2
--- /dev/null
+++ b/std/special/compiler_rt/fixtfsi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixtfsi(a: f128) i32 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f128, i32, a);
+}
+
+test "import fixtfsi" {
+ _ = @import("fixtfsi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixtfsi_test.zig b/std/special/compiler_rt/fixtfsi_test.zig
new file mode 100644
index 0000000000..7a3cc7f46c
--- /dev/null
+++ b/std/special/compiler_rt/fixtfsi_test.zig
@@ -0,0 +1,76 @@
+const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;
+const std = @import("std");
+const math = std.math;
+const assert = std.debug.assert;
+const warn = std.debug.warn;
+
+fn test__fixtfsi(a: f128, expected: i32) void {
+ const x = __fixtfsi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u32, expected));
+ assert(x == expected);
+}
+
+test "fixtfsi" {
+ //warn("\n");
+
+ test__fixtfsi(-math.f128_max, math.minInt(i32));
+
+ test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
+ test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
+
+ test__fixtfsi(-0x1.0000000000000p+127, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
+
+ test__fixtfsi(-0x1.0000000000001p+63, -0x80000000);
+ test__fixtfsi(-0x1.0000000000000p+63, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
+
+ test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000);
+
+ test__fixtfsi(-0x1.000000p+31, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
+ test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
+ test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);
+
+ test__fixtfsi(-2.01, -2);
+ test__fixtfsi(-2.0, -2);
+ test__fixtfsi(-1.99, -1);
+ test__fixtfsi(-1.0, -1);
+ test__fixtfsi(-0.99, 0);
+ test__fixtfsi(-0.5, 0);
+ test__fixtfsi(-math.f32_min, 0);
+ test__fixtfsi(0.0, 0);
+ test__fixtfsi(math.f32_min, 0);
+ test__fixtfsi(0.5, 0);
+ test__fixtfsi(0.99, 0);
+ test__fixtfsi(1.0, 1);
+ test__fixtfsi(1.5, 1);
+ test__fixtfsi(1.99, 1);
+ test__fixtfsi(2.0, 2);
+ test__fixtfsi(2.01, 2);
+
+ test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
+ test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
+ test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
+ test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF);
+
+ test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
+ test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
+
+ test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
+ test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
+ test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
+ test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
+
+ test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
+ test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
+ test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
+
+ test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
+ test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
+
+ test__fixtfsi(math.f128_max, math.maxInt(i32));
+}
diff --git a/std/special/compiler_rt/fixtfti.zig b/std/special/compiler_rt/fixtfti.zig
new file mode 100644
index 0000000000..07d38f2c3b
--- /dev/null
+++ b/std/special/compiler_rt/fixtfti.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixtfti(a: f128) i128 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f128, i128, a);
+}
+
+test "import fixtfti" {
+ _ = @import("fixtfti_test.zig");
+}
diff --git a/std/special/compiler_rt/fixtfti_test.zig b/std/special/compiler_rt/fixtfti_test.zig
new file mode 100644
index 0000000000..520009486a
--- /dev/null
+++ b/std/special/compiler_rt/fixtfti_test.zig
@@ -0,0 +1,66 @@
+const __fixtfti = @import("fixtfti.zig").__fixtfti;
+const std = @import("std");
+const math = std.math;
+const assert = std.debug.assert;
+const warn = std.debug.warn;
+
+fn test__fixtfti(a: f128, expected: i128) void {
+ const x = __fixtfti(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u128({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u128, expected));
+ assert(x == expected);
+}
+
+test "fixtfti" {
+ //warn("\n");
+
+ test__fixtfti(-math.f128_max, math.minInt(i128));
+
+ test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
+ test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
+
+ test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
+ test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
+ test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
+
+ test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800);
+ test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
+ test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
+
+ test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
+ test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
+
+ test__fixtfti(-2.01, -2);
+ test__fixtfti(-2.0, -2);
+ test__fixtfti(-1.99, -1);
+ test__fixtfti(-1.0, -1);
+ test__fixtfti(-0.99, 0);
+ test__fixtfti(-0.5, 0);
+ test__fixtfti(-math.f128_min, 0);
+ test__fixtfti(0.0, 0);
+ test__fixtfti(math.f128_min, 0);
+ test__fixtfti(0.5, 0);
+ test__fixtfti(0.99, 0);
+ test__fixtfti(1.0, 1);
+ test__fixtfti(1.5, 1);
+ test__fixtfti(1.99, 1);
+ test__fixtfti(2.0, 2);
+ test__fixtfti(2.01, 2);
+
+ test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+
+ test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
+ test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
+ test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000);
+ test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800);
+
+ test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
+ test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
+ test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+
+ test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
+
+ test__fixtfti(math.f128_max, math.maxInt(i128));
+}
diff --git a/std/special/compiler_rt/index.zig b/std/special/compiler_rt/index.zig
index c826af83bc..4bbfc2b290 100644
--- a/std/special/compiler_rt/index.zig
+++ b/std/special/compiler_rt/index.zig
@@ -52,6 +52,16 @@ comptime {
@export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage);
@export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage);
+ @export("__fixdfdi", @import("fixdfdi.zig").__fixdfdi, linkage);
+ @export("__fixdfsi", @import("fixdfsi.zig").__fixdfsi, linkage);
+ @export("__fixdfti", @import("fixdfti.zig").__fixdfti, linkage);
+ @export("__fixsfdi", @import("fixsfdi.zig").__fixsfdi, linkage);
+ @export("__fixsfsi", @import("fixsfsi.zig").__fixsfsi, linkage);
+ @export("__fixsfti", @import("fixsfti.zig").__fixsfti, linkage);
+ @export("__fixtfdi", @import("fixtfdi.zig").__fixtfdi, linkage);
+ @export("__fixtfsi", @import("fixtfsi.zig").__fixtfsi, linkage);
+ @export("__fixtfti", @import("fixtfti.zig").__fixtfti, linkage);
+
@export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage);
@export("__udivsi3", __udivsi3, linkage);
@@ -59,7 +69,7 @@ comptime {
@export("__umoddi3", __umoddi3, linkage);
@export("__udivmodsi4", __udivmodsi4, linkage);
- if (isArmArch()) {
+ if (is_arm_arch and !is_arm_64) {
@export("__aeabi_uldivmod", __aeabi_uldivmod, linkage);
@export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);
@export("__aeabi_uidiv", __udivsi3, linkage);
@@ -149,68 +159,85 @@ extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult
return result;
}
-fn isArmArch() bool {
- return switch (builtin.arch) {
- builtin.Arch.armv8_3a,
- builtin.Arch.armv8_2a,
- builtin.Arch.armv8_1a,
- builtin.Arch.armv8,
- builtin.Arch.armv8r,
- builtin.Arch.armv8m_baseline,
- builtin.Arch.armv8m_mainline,
- builtin.Arch.armv7,
- builtin.Arch.armv7em,
- builtin.Arch.armv7m,
- builtin.Arch.armv7s,
- builtin.Arch.armv7k,
- builtin.Arch.armv7ve,
- builtin.Arch.armv6,
- builtin.Arch.armv6m,
- builtin.Arch.armv6k,
- builtin.Arch.armv6t2,
- builtin.Arch.armv5,
- builtin.Arch.armv5te,
- builtin.Arch.armv4t,
- builtin.Arch.armebv8_3a,
- builtin.Arch.armebv8_2a,
- builtin.Arch.armebv8_1a,
- builtin.Arch.armebv8,
- builtin.Arch.armebv8r,
- builtin.Arch.armebv8m_baseline,
- builtin.Arch.armebv8m_mainline,
- builtin.Arch.armebv7,
- builtin.Arch.armebv7em,
- builtin.Arch.armebv7m,
- builtin.Arch.armebv7s,
- builtin.Arch.armebv7k,
- builtin.Arch.armebv7ve,
- builtin.Arch.armebv6,
- builtin.Arch.armebv6m,
- builtin.Arch.armebv6k,
- builtin.Arch.armebv6t2,
- builtin.Arch.armebv5,
- builtin.Arch.armebv5te,
- builtin.Arch.armebv4t,
- builtin.Arch.aarch64v8_3a,
- builtin.Arch.aarch64v8_2a,
- builtin.Arch.aarch64v8_1a,
- builtin.Arch.aarch64v8,
- builtin.Arch.aarch64v8r,
- builtin.Arch.aarch64v8m_baseline,
- builtin.Arch.aarch64v8m_mainline,
- builtin.Arch.aarch64_bev8_3a,
- builtin.Arch.aarch64_bev8_2a,
- builtin.Arch.aarch64_bev8_1a,
- builtin.Arch.aarch64_bev8,
- builtin.Arch.aarch64_bev8r,
- builtin.Arch.aarch64_bev8m_baseline,
- builtin.Arch.aarch64_bev8m_mainline,
- builtin.Arch.thumb,
- builtin.Arch.thumbeb,
- => true,
- else => false,
- };
-}
+const is_arm_64 = switch (builtin.arch) {
+ builtin.Arch.aarch64v8_3a,
+ builtin.Arch.aarch64v8_2a,
+ builtin.Arch.aarch64v8_1a,
+ builtin.Arch.aarch64v8,
+ builtin.Arch.aarch64v8r,
+ builtin.Arch.aarch64v8m_baseline,
+ builtin.Arch.aarch64v8m_mainline,
+ builtin.Arch.aarch64_bev8_3a,
+ builtin.Arch.aarch64_bev8_2a,
+ builtin.Arch.aarch64_bev8_1a,
+ builtin.Arch.aarch64_bev8,
+ builtin.Arch.aarch64_bev8r,
+ builtin.Arch.aarch64_bev8m_baseline,
+ builtin.Arch.aarch64_bev8m_mainline,
+ => true,
+ else => false,
+};
+
+const is_arm_arch = switch (builtin.arch) {
+ builtin.Arch.armv8_3a,
+ builtin.Arch.armv8_2a,
+ builtin.Arch.armv8_1a,
+ builtin.Arch.armv8,
+ builtin.Arch.armv8r,
+ builtin.Arch.armv8m_baseline,
+ builtin.Arch.armv8m_mainline,
+ builtin.Arch.armv7,
+ builtin.Arch.armv7em,
+ builtin.Arch.armv7m,
+ builtin.Arch.armv7s,
+ builtin.Arch.armv7k,
+ builtin.Arch.armv7ve,
+ builtin.Arch.armv6,
+ builtin.Arch.armv6m,
+ builtin.Arch.armv6k,
+ builtin.Arch.armv6t2,
+ builtin.Arch.armv5,
+ builtin.Arch.armv5te,
+ builtin.Arch.armv4t,
+ builtin.Arch.armebv8_3a,
+ builtin.Arch.armebv8_2a,
+ builtin.Arch.armebv8_1a,
+ builtin.Arch.armebv8,
+ builtin.Arch.armebv8r,
+ builtin.Arch.armebv8m_baseline,
+ builtin.Arch.armebv8m_mainline,
+ builtin.Arch.armebv7,
+ builtin.Arch.armebv7em,
+ builtin.Arch.armebv7m,
+ builtin.Arch.armebv7s,
+ builtin.Arch.armebv7k,
+ builtin.Arch.armebv7ve,
+ builtin.Arch.armebv6,
+ builtin.Arch.armebv6m,
+ builtin.Arch.armebv6k,
+ builtin.Arch.armebv6t2,
+ builtin.Arch.armebv5,
+ builtin.Arch.armebv5te,
+ builtin.Arch.armebv4t,
+ builtin.Arch.aarch64v8_3a,
+ builtin.Arch.aarch64v8_2a,
+ builtin.Arch.aarch64v8_1a,
+ builtin.Arch.aarch64v8,
+ builtin.Arch.aarch64v8r,
+ builtin.Arch.aarch64v8m_baseline,
+ builtin.Arch.aarch64v8m_mainline,
+ builtin.Arch.aarch64_bev8_3a,
+ builtin.Arch.aarch64_bev8_2a,
+ builtin.Arch.aarch64_bev8_1a,
+ builtin.Arch.aarch64_bev8,
+ builtin.Arch.aarch64_bev8r,
+ builtin.Arch.aarch64_bev8m_baseline,
+ builtin.Arch.aarch64_bev8m_mainline,
+ builtin.Arch.thumb,
+ builtin.Arch.thumbeb,
+ => true,
+ else => false,
+};
nakedcc fn __aeabi_uidivmod() void {
@setRuntimeSafety(false);
diff --git a/std/unicode.zig b/std/unicode.zig
index 559a2e739a..2e542bcb19 100644
--- a/std/unicode.zig
+++ b/std/unicode.zig
@@ -208,7 +208,7 @@ pub const Utf8View = struct {
}
};
-const Utf8Iterator = struct {
+pub const Utf8Iterator = struct {
bytes: []const u8,
i: usize,
@@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct {
pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 {
assert(it.i <= it.bytes.len);
if (it.i == it.bytes.len) return null;
- const c0: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]);
+ const c0: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
if (c0 & ~u32(0x03ff) == 0xd800) {
// surrogate pair
it.i += 2;
if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;
- const c1: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]);
+ const c1: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;
it.i += 2;
return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));
@@ -510,46 +510,46 @@ test "utf16leToUtf8" {
const utf16le_as_bytes = @sliceToBytes(utf16le[0..]);
{
- mem.writeInt(utf16le_as_bytes[0..], u16('A'), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16('a'), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A');
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a');
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
assert(mem.eql(u8, utf8, "Aa"));
}
{
- mem.writeInt(utf16le_as_bytes[0..], u16(0x80), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16(0xffff), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff);
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));
}
{
// the values just outside the surrogate half range
- mem.writeInt(utf16le_as_bytes[0..], u16(0xd7ff), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16(0xe000), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000);
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));
}
{
// smallest surrogate pair
- mem.writeInt(utf16le_as_bytes[0..], u16(0xd800), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));
}
{
// largest surrogate pair
- mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16(0xdfff), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff);
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));
}
{
- mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));
}
@@ -583,7 +583,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize {
while (it.nextCodepoint()) |codepoint| {
if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1;
// TODO surrogate pairs
- mem.writeInt(utf16le_as_bytes[end_index..], @intCast(u16, codepoint), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[end_index..], @intCast(u16, codepoint));
end_index += 2;
}
return end_index / 2;