aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-12-04 15:28:17 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-12-04 15:28:17 -0500
commit42004f9013ba2d06b457f858e0e269ef4ad23554 (patch)
treeee99dd89c9ce7e7c30a76e7bf0d9f7da7c0c64c7 /std
parentafe3aae582d5051406832e32fc01374f2a0029b7 (diff)
parenta966275e509670e750ef54a37f7202078aa4cf07 (diff)
downloadzig-42004f9013ba2d06b457f858e0e269ef4ad23554.tar.gz
zig-42004f9013ba2d06b457f858e0e269ef4ad23554.zip
Merge branch 'master' into llvm6
Diffstat (limited to 'std')
-rw-r--r--std/buffer.zig6
-rw-r--r--std/build.zig42
-rw-r--r--std/debug.zig46
-rw-r--r--std/elf.zig79
-rw-r--r--std/endian.zig4
-rw-r--r--std/io.zig14
-rw-r--r--std/mem.zig111
-rw-r--r--std/os/child_process.zig18
-rw-r--r--std/os/index.zig5
-rw-r--r--std/os/path.zig2
-rw-r--r--std/rand.zig6
-rw-r--r--std/sort.zig70
-rw-r--r--std/special/compiler_rt/udivmod.zig2
13 files changed, 264 insertions, 141 deletions
diff --git a/std/buffer.zig b/std/buffer.zig
index a1aa8faf9d..96abaeb762 100644
--- a/std/buffer.zig
+++ b/std/buffer.zig
@@ -4,6 +4,8 @@ const Allocator = mem.Allocator;
const assert = debug.assert;
const ArrayList = @import("array_list.zig").ArrayList;
+const fmt = @import("fmt/index.zig");
+
/// A buffer that allocates memory and maintains a null byte at the end.
pub const Buffer = struct {
list: ArrayList(u8),
@@ -96,6 +98,10 @@ pub const Buffer = struct {
mem.copy(u8, self.list.toSlice()[old_len..], m);
}
+ pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) -> %void {
+ return fmt.format(self, append, format, args);
+ }
+
pub fn appendByte(self: &Buffer, byte: u8) -> %void {
return self.appendByteNTimes(byte, 1);
}
diff --git a/std/build.zig b/std/build.zig
index 009295c6ad..9bdc4b3076 100644
--- a/std/build.zig
+++ b/std/build.zig
@@ -69,8 +69,8 @@ pub const Builder = struct {
used: bool,
};
- const UserValue = enum {
- Flag,
+ const UserValue = union(enum) {
+ Flag: void,
Scalar: []const u8,
List: ArrayList([]const u8),
};
@@ -450,7 +450,7 @@ pub const Builder = struct {
pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {
if (%%self.user_input_options.put(name, UserInputOption {
.name = name,
- .value = UserValue.Scalar { value },
+ .value = UserValue { .Scalar = value },
.used = false,
})) |*prev_value| {
// option already exists
@@ -462,7 +462,7 @@ pub const Builder = struct {
%%list.append(value);
_ = %%self.user_input_options.put(name, UserInputOption {
.name = name,
- .value = UserValue.List { list },
+ .value = UserValue { .List = list },
.used = false,
});
},
@@ -471,7 +471,7 @@ pub const Builder = struct {
%%list.append(value);
_ = %%self.user_input_options.put(name, UserInputOption {
.name = name,
- .value = UserValue.List { *list },
+ .value = UserValue { .List = *list },
.used = false,
});
},
@@ -487,7 +487,7 @@ pub const Builder = struct {
pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool {
if (%%self.user_input_options.put(name, UserInputOption {
.name = name,
- .value = UserValue.Flag,
+ .value = UserValue {.Flag = {} },
.used = false,
})) |*prev_value| {
switch (prev_value.value) {
@@ -685,8 +685,8 @@ const CrossTarget = struct {
environ: builtin.Environ,
};
-const Target = enum {
- Native,
+const Target = union(enum) {
+ Native: void,
Cross: CrossTarget,
pub fn oFileExt(self: &const Target) -> []const u8 {
@@ -844,7 +844,7 @@ pub const LibExeObjStep = struct {
.kind = kind,
.root_src = root_src,
.name = name,
- .target = Target.Native,
+ .target = Target { .Native = {} },
.linker_script = null,
.link_libs = BufSet.init(builder.allocator),
.frameworks = BufSet.init(builder.allocator),
@@ -879,7 +879,7 @@ pub const LibExeObjStep = struct {
.kind = kind,
.version = *version,
.static = static,
- .target = Target.Native,
+ .target = Target { .Native = {} },
.cflags = ArrayList([]const u8).init(builder.allocator),
.source_files = ArrayList([]const u8).init(builder.allocator),
.object_files = ArrayList([]const u8).init(builder.allocator),
@@ -948,8 +948,8 @@ pub const LibExeObjStep = struct {
pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os,
target_environ: builtin.Environ)
{
- self.target = Target.Cross {
- CrossTarget {
+ self.target = Target {
+ .Cross = CrossTarget {
.arch = target_arch,
.os = target_os,
.environ = target_environ,
@@ -1186,13 +1186,13 @@ pub const LibExeObjStep = struct {
Target.Native => {},
Target.Cross => |cross_target| {
%%zig_args.append("--target-arch");
- %%zig_args.append(@enumTagName(cross_target.arch));
+ %%zig_args.append(@tagName(cross_target.arch));
%%zig_args.append("--target-os");
- %%zig_args.append(@enumTagName(cross_target.os));
+ %%zig_args.append(@tagName(cross_target.os));
%%zig_args.append("--target-environ");
- %%zig_args.append(@enumTagName(cross_target.environ));
+ %%zig_args.append(@tagName(cross_target.environ));
},
}
@@ -1553,7 +1553,7 @@ pub const TestStep = struct {
.name_prefix = "",
.filter = null,
.link_libs = BufSet.init(builder.allocator),
- .target = Target.Native,
+ .target = Target { .Native = {} },
.exec_cmd_args = null,
}
}
@@ -1581,8 +1581,8 @@ pub const TestStep = struct {
pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os,
target_environ: builtin.Environ)
{
- self.target = Target.Cross {
- CrossTarget {
+ self.target = Target {
+ .Cross = CrossTarget {
.arch = target_arch,
.os = target_os,
.environ = target_environ,
@@ -1620,13 +1620,13 @@ pub const TestStep = struct {
Target.Native => {},
Target.Cross => |cross_target| {
%%zig_args.append("--target-arch");
- %%zig_args.append(@enumTagName(cross_target.arch));
+ %%zig_args.append(@tagName(cross_target.arch));
%%zig_args.append("--target-os");
- %%zig_args.append(@enumTagName(cross_target.os));
+ %%zig_args.append(@tagName(cross_target.os));
%%zig_args.append("--target-environ");
- %%zig_args.append(@enumTagName(cross_target.environ));
+ %%zig_args.append(@tagName(cross_target.environ));
},
}
diff --git a/std/debug.zig b/std/debug.zig
index 50322024c3..a2bea9eddd 100644
--- a/std/debug.zig
+++ b/std/debug.zig
@@ -280,7 +280,7 @@ const AbbrevAttr = struct {
form_id: u64,
};
-const FormValue = enum {
+const FormValue = union(enum) {
Address: u64,
Block: []u8,
Const: Constant,
@@ -303,7 +303,7 @@ const Constant = struct {
return error.InvalidDebugInfo;
if (self.signed)
return error.InvalidDebugInfo;
- return mem.readInt(self.payload, u64, false);
+ return mem.readInt(self.payload, u64, builtin.Endian.Little);
}
};
@@ -475,16 +475,16 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usiz
fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
const buf = %return readAllocBytes(allocator, in_stream, size);
- return FormValue.Block { buf };
+ return FormValue { .Block = buf };
}
fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
- const block_len = %return in_stream.readVarInt(false, usize, size);
+ const block_len = %return in_stream.readVarInt(builtin.Endian.Little, usize, size);
return parseFormValueBlockLen(allocator, in_stream, block_len);
}
fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue {
- FormValue.Const { Constant {
+ FormValue { .Const = Constant {
.signed = signed,
.payload = %return readAllocBytes(allocator, in_stream, size),
}}
@@ -510,7 +510,7 @@ fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 {
fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
const buf = %return readAllocBytes(allocator, in_stream, size);
- return FormValue.Ref { buf };
+ return FormValue { .Ref = buf };
}
fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue {
@@ -520,7 +520,7 @@ fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptim
fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue {
return switch (form_id) {
- DW.FORM_addr => FormValue.Address { %return parseFormValueTargetAddrSize(in_stream) },
+ DW.FORM_addr => FormValue { .Address = %return parseFormValueTargetAddrSize(in_stream) },
DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
@@ -540,13 +540,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
DW.FORM_exprloc => {
const size = %return readULeb128(in_stream);
const buf = %return readAllocBytes(allocator, in_stream, size);
- return FormValue.ExprLoc { buf };
- },
- DW.FORM_flag => FormValue.Flag { (%return in_stream.readByte()) != 0 },
- DW.FORM_flag_present => FormValue.Flag { true },
- DW.FORM_sec_offset => FormValue.SecOffset {
- %return parseFormValueDwarfOffsetSize(in_stream, is_64)
+ return FormValue { .ExprLoc = buf };
},
+ DW.FORM_flag => FormValue { .Flag = (%return in_stream.readByte()) != 0 },
+ DW.FORM_flag_present => FormValue { .Flag = true },
+ DW.FORM_sec_offset => FormValue { .SecOffset = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8),
DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16),
@@ -557,11 +555,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
parseFormValueRefLen(allocator, in_stream, ref_len)
},
- DW.FORM_ref_addr => FormValue.RefAddr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
- DW.FORM_ref_sig8 => FormValue.RefSig8 { %return in_stream.readIntLe(u64) },
+ DW.FORM_ref_addr => FormValue { .RefAddr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
+ DW.FORM_ref_sig8 => FormValue { .RefSig8 = %return in_stream.readIntLe(u64) },
- DW.FORM_string => FormValue.String { %return readStringRaw(allocator, in_stream) },
- DW.FORM_strp => FormValue.StrPtr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
+ DW.FORM_string => FormValue { .String = %return readStringRaw(allocator, in_stream) },
+ DW.FORM_strp => FormValue { .StrPtr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_indirect => {
const child_form_id = %return readULeb128(in_stream);
parseFormValue(allocator, in_stream, child_form_id, is_64)
@@ -671,10 +669,10 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
continue;
}
- const version = %return in_stream.readInt(st.elf.is_big_endian, u16);
+ const version = %return in_stream.readInt(st.elf.endian, u16);
if (version != 2) return error.InvalidDebugInfo;
- const prologue_length = %return in_stream.readInt(st.elf.is_big_endian, u32);
+ const prologue_length = %return in_stream.readInt(st.elf.endian, u32);
const prog_start_offset = (%return in_file.getPos()) + prologue_length;
const minimum_instruction_length = %return in_stream.readByte();
@@ -741,7 +739,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
return error.MissingDebugInfo;
},
DW.LNE_set_address => {
- const addr = %return in_stream.readInt(st.elf.is_big_endian, usize);
+ const addr = %return in_stream.readInt(st.elf.endian, usize);
prog.address = addr;
},
DW.LNE_define_file => {
@@ -803,7 +801,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
prog.address += inc_addr;
},
DW.LNS_fixed_advance_pc => {
- const arg = %return in_stream.readInt(st.elf.is_big_endian, u16);
+ const arg = %return in_stream.readInt(st.elf.endian, u16);
prog.address += arg;
},
DW.LNS_set_prologue_end => {
@@ -841,13 +839,13 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
return;
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
- const version = %return in_stream.readInt(st.elf.is_big_endian, u16);
+ const version = %return in_stream.readInt(st.elf.endian, u16);
if (version < 2 or version > 5) return error.InvalidDebugInfo;
const debug_abbrev_offset = if (is_64) {
- %return in_stream.readInt(st.elf.is_big_endian, u64)
+ %return in_stream.readInt(st.elf.endian, u64)
} else {
- %return in_stream.readInt(st.elf.is_big_endian, u32)
+ %return in_stream.readInt(st.elf.endian, u32)
};
const address_size = %return in_stream.readByte();
diff --git a/std/elf.zig b/std/elf.zig
index f3f7de512f..f7be236d15 100644
--- a/std/elf.zig
+++ b/std/elf.zig
@@ -1,3 +1,4 @@
+const builtin = @import("builtin");
const std = @import("index.zig");
const io = std.io;
const math = std.math;
@@ -67,7 +68,7 @@ pub const Elf = struct {
in_file: &io.File,
auto_close_stream: bool,
is_64: bool,
- is_big_endian: bool,
+ endian: builtin.Endian,
file_type: FileType,
arch: Arch,
entry_addr: u64,
@@ -105,9 +106,9 @@ pub const Elf = struct {
else => return error.InvalidFormat,
};
- elf.is_big_endian = switch (%return in.readByte()) {
- 1 => false,
- 2 => true,
+ elf.endian = switch (%return in.readByte()) {
+ 1 => builtin.Endian.Little,
+ 2 => builtin.Endian.Big,
else => return error.InvalidFormat,
};
@@ -117,7 +118,7 @@ pub const Elf = struct {
// skip over padding
%return elf.in_file.seekForward(9);
- elf.file_type = switch (%return in.readInt(elf.is_big_endian, u16)) {
+ elf.file_type = switch (%return in.readInt(elf.endian, u16)) {
1 => FileType.Relocatable,
2 => FileType.Executable,
3 => FileType.Shared,
@@ -125,7 +126,7 @@ pub const Elf = struct {
else => return error.InvalidFormat,
};
- elf.arch = switch (%return in.readInt(elf.is_big_endian, u16)) {
+ elf.arch = switch (%return in.readInt(elf.endian, u16)) {
0x02 => Arch.Sparc,
0x03 => Arch.x86,
0x08 => Arch.Mips,
@@ -138,34 +139,34 @@ pub const Elf = struct {
else => return error.InvalidFormat,
};
- const elf_version = %return in.readInt(elf.is_big_endian, u32);
+ const elf_version = %return in.readInt(elf.endian, u32);
if (elf_version != 1) return error.InvalidFormat;
if (elf.is_64) {
- elf.entry_addr = %return in.readInt(elf.is_big_endian, u64);
- elf.program_header_offset = %return in.readInt(elf.is_big_endian, u64);
- elf.section_header_offset = %return in.readInt(elf.is_big_endian, u64);
+ elf.entry_addr = %return in.readInt(elf.endian, u64);
+ elf.program_header_offset = %return in.readInt(elf.endian, u64);
+ elf.section_header_offset = %return in.readInt(elf.endian, u64);
} else {
- elf.entry_addr = u64(%return in.readInt(elf.is_big_endian, u32));
- elf.program_header_offset = u64(%return in.readInt(elf.is_big_endian, u32));
- elf.section_header_offset = u64(%return in.readInt(elf.is_big_endian, u32));
+ elf.entry_addr = u64(%return in.readInt(elf.endian, u32));
+ elf.program_header_offset = u64(%return in.readInt(elf.endian, u32));
+ elf.section_header_offset = u64(%return in.readInt(elf.endian, u32));
}
// skip over flags
%return elf.in_file.seekForward(4);
- const header_size = %return in.readInt(elf.is_big_endian, u16);
+ const header_size = %return in.readInt(elf.endian, u16);
if ((elf.is_64 and header_size != 64) or
(!elf.is_64 and header_size != 52))
{
return error.InvalidFormat;
}
- const ph_entry_size = %return in.readInt(elf.is_big_endian, u16);
- const ph_entry_count = %return in.readInt(elf.is_big_endian, u16);
- const sh_entry_size = %return in.readInt(elf.is_big_endian, u16);
- const sh_entry_count = %return in.readInt(elf.is_big_endian, u16);
- elf.string_section_index = u64(%return in.readInt(elf.is_big_endian, u16));
+ const ph_entry_size = %return in.readInt(elf.endian, u16);
+ const ph_entry_count = %return in.readInt(elf.endian, u16);
+ const sh_entry_size = %return in.readInt(elf.endian, u16);
+ const sh_entry_count = %return in.readInt(elf.endian, u16);
+ elf.string_section_index = u64(%return in.readInt(elf.endian, u16));
if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
@@ -188,32 +189,32 @@ pub const Elf = struct {
if (sh_entry_size != 64) return error.InvalidFormat;
for (elf.section_headers) |*section| {
- section.name = %return in.readInt(elf.is_big_endian, u32);
- section.sh_type = %return in.readInt(elf.is_big_endian, u32);
- section.flags = %return in.readInt(elf.is_big_endian, u64);
- section.addr = %return in.readInt(elf.is_big_endian, u64);
- section.offset = %return in.readInt(elf.is_big_endian, u64);
- section.size = %return in.readInt(elf.is_big_endian, u64);
- section.link = %return in.readInt(elf.is_big_endian, u32);
- section.info = %return in.readInt(elf.is_big_endian, u32);
- section.addr_align = %return in.readInt(elf.is_big_endian, u64);
- section.ent_size = %return in.readInt(elf.is_big_endian, u64);
+ section.name = %return in.readInt(elf.endian, u32);
+ section.sh_type = %return in.readInt(elf.endian, u32);
+ section.flags = %return in.readInt(elf.endian, u64);
+ section.addr = %return in.readInt(elf.endian, u64);
+ section.offset = %return in.readInt(elf.endian, u64);
+ section.size = %return in.readInt(elf.endian, u64);
+ section.link = %return in.readInt(elf.endian, u32);
+ section.info = %return in.readInt(elf.endian, u32);
+ section.addr_align = %return in.readInt(elf.endian, u64);
+ section.ent_size = %return in.readInt(elf.endian, u64);
}
} else {
if (sh_entry_size != 40) return error.InvalidFormat;
for (elf.section_headers) |*section| {
// TODO (multiple occurences) allow implicit cast from %u32 -> %u64 ?
- section.name = %return in.readInt(elf.is_big_endian, u32);
- section.sh_type = %return in.readInt(elf.is_big_endian, u32);
- section.flags = u64(%return in.readInt(elf.is_big_endian, u32));
- section.addr = u64(%return in.readInt(elf.is_big_endian, u32));
- section.offset = u64(%return in.readInt(elf.is_big_endian, u32));
- section.size = u64(%return in.readInt(elf.is_big_endian, u32));
- section.link = %return in.readInt(elf.is_big_endian, u32);
- section.info = %return in.readInt(elf.is_big_endian, u32);
- section.addr_align = u64(%return in.readInt(elf.is_big_endian, u32));
- section.ent_size = u64(%return in.readInt(elf.is_big_endian, u32));
+ section.name = %return in.readInt(elf.endian, u32);
+ section.sh_type = %return in.readInt(elf.endian, u32);
+ section.flags = u64(%return in.readInt(elf.endian, u32));
+ section.addr = u64(%return in.readInt(elf.endian, u32));
+ section.offset = u64(%return in.readInt(elf.endian, u32));
+ section.size = u64(%return in.readInt(elf.endian, u32));
+ section.link = %return in.readInt(elf.endian, u32);
+ section.info = %return in.readInt(elf.endian, u32);
+ section.addr_align = u64(%return in.readInt(elf.endian, u32));
+ section.ent_size = u64(%return in.readInt(elf.endian, u32));
}
}
diff --git a/std/endian.zig b/std/endian.zig
index 8ae8ae22f8..2dc6b8d34e 100644
--- a/std/endian.zig
+++ b/std/endian.zig
@@ -9,8 +9,8 @@ pub fn swapIfBe(comptime T: type, x: T) -> T {
swapIf(true, T, x)
}
-pub fn swapIf(is_be: bool, comptime T: type, x: T) -> T {
- if (builtin.is_big_endian == is_be) swap(T, x) else x
+pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T {
+ if (builtin.endian == endian) swap(T, x) else x
}
pub fn swap(comptime T: type, x: T) -> T {
diff --git a/std/io.zig b/std/io.zig
index d570927488..c86ebed326 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -259,7 +259,7 @@ pub const File = struct {
if (err > 0) {
return switch (err) {
system.EBADF => error.BadFd,
- system.ENOMEM => error.OutOfMemory,
+ system.ENOMEM => error.SystemResources,
else => os.unexpectedErrorPosix(err),
}
}
@@ -441,26 +441,26 @@ pub const InStream = struct {
}
pub fn readIntLe(self: &InStream, comptime T: type) -> %T {
- return self.readInt(false, T);
+ return self.readInt(builtin.Endian.Little, T);
}
pub fn readIntBe(self: &InStream, comptime T: type) -> %T {
- return self.readInt(true, T);
+ return self.readInt(builtin.Endian.Big, T);
}
- pub fn readInt(self: &InStream, is_be: bool, comptime T: type) -> %T {
+ pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) -> %T {
var bytes: [@sizeOf(T)]u8 = undefined;
%return self.readNoEof(bytes[0..]);
- return mem.readInt(bytes, T, is_be);
+ return mem.readInt(bytes, T, endian);
}
- pub fn readVarInt(self: &InStream, is_be: bool, comptime T: type, size: usize) -> %T {
+ pub fn readVarInt(self: &InStream, 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];
%return self.readNoEof(input_slice);
- return mem.readInt(input_slice, T, is_be);
+ return mem.readInt(input_slice, T, endian);
}
diff --git a/std/mem.zig b/std/mem.zig
index 3cfdb25b35..815e122812 100644
--- a/std/mem.zig
+++ b/std/mem.zig
@@ -1,6 +1,7 @@
const debug = @import("debug.zig");
const assert = debug.assert;
const math = @import("math/index.zig");
+const builtin = @import("builtin");
pub const Cmp = math.Cmp;
@@ -180,43 +181,78 @@ 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.
-pub fn readInt(bytes: []const u8, comptime T: type, big_endian: bool) -> T {
+/// 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;
- if (big_endian) {
- for (bytes) |b| {
- result = (result << 8) | b;
- }
- } else {
- const ShiftType = math.Log2Int(T);
- for (bytes) |b, index| {
- result = result | (T(b) << ShiftType(index * 8));
- }
+ switch (endian) {
+ builtin.Endian.Big => {
+ for (bytes) |b| {
+ result = (result << 8) | b;
+ }
+ },
+ builtin.Endian.Little => {
+ const ShiftType = math.Log2Int(T);
+ for (bytes) |b, index| {
+ result = result | (T(b) << 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));
+ var result: T = 0;
+ {comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) {
+ result = (result << 8) | T(bytes[i]);
+ }}
+ 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));
+ }
+ assert(bytes.len == @sizeOf(T));
+ var result: T = 0;
+ {comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) {
+ result |= T(bytes[i]) << i * 8;
+ }}
+ return result;
+}
+
/// 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, big_endian: bool) {
+pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) {
const uint = @IntType(false, @typeOf(value).bit_count);
var bits = @truncate(uint, value);
- if (big_endian) {
- var index: usize = buf.len;
- while (index != 0) {
- index -= 1;
-
- buf[index] = @truncate(u8, bits);
- bits >>= 8;
- }
- } else {
- for (buf) |*b| {
- *b = @truncate(u8, bits);
- bits >>= 8;
- }
+ switch (endian) {
+ builtin.Endian.Big => {
+ var index: usize = buf.len;
+ while (index != 0) {
+ index -= 1;
+
+ buf[index] = @truncate(u8, bits);
+ bits >>= 8;
+ }
+ },
+ builtin.Endian.Little => {
+ for (buf) |*b| {
+ *b = @truncate(u8, bits);
+ bits >>= 8;
+ }
+ },
}
assert(bits == 0);
}
@@ -348,19 +384,30 @@ test "testReadInt" {
fn testReadIntImpl() {
{
const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 };
- assert(readInt(bytes, u32, true) == 0x12345678);
- assert(readInt(bytes, u32, false) == 0x78563412);
+ 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);
}
{
const buf = []u8{0x00, 0x00, 0x12, 0x34};
- const answer = readInt(buf, u64, true);
+ const answer = readInt(buf, u64, builtin.Endian.Big);
assert(answer == 0x00001234);
}
{
const buf = []u8{0x12, 0x34, 0x00, 0x00};
- const answer = readInt(buf, u64, false);
+ const answer = readInt(buf, u64, builtin.Endian.Little);
assert(answer == 0x00003412);
}
+ {
+ const bytes = []u8{0xff, 0xfe};
+ assert(readIntBE(u16, bytes) == 0xfffe);
+ assert(readIntBE(i16, bytes) == -0x0002);
+ assert(readIntLE(u16, bytes) == 0xfeff);
+ assert(readIntLE(i16, bytes) == -0x0101);
+ }
}
test "testWriteInt" {
@@ -370,16 +417,16 @@ test "testWriteInt" {
fn testWriteIntImpl() {
var bytes: [4]u8 = undefined;
- writeInt(bytes[0..], u32(0x12345678), true);
+ writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 }));
- writeInt(bytes[0..], u32(0x78563412), false);
+ writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);
assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 }));
- writeInt(bytes[0..], u16(0x1234), true);
+ writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);
assert(eql(u8, bytes, []u8{ 0x00, 0x00, 0x12, 0x34 }));
- writeInt(bytes[0..], u16(0x1234), false);
+ writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);
assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 }));
}
diff --git a/std/os/child_process.zig b/std/os/child_process.zig
index 005d9772e4..75a2dcf24d 100644
--- a/std/os/child_process.zig
+++ b/std/os/child_process.zig
@@ -58,7 +58,7 @@ pub const ChildProcess = struct {
err_pipe: if (is_windows) void else [2]i32,
llnode: if (is_windows) void else LinkedList(&ChildProcess).Node,
- pub const Term = enum {
+ pub const Term = union(enum) {
Exited: i32,
Signal: i32,
Stopped: i32,
@@ -213,9 +213,9 @@ pub const ChildProcess = struct {
self.term = (%Term)({
var exit_code: windows.DWORD = undefined;
if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) {
- Term.Unknown{0}
+ Term { .Unknown = 0 }
} else {
- Term.Exited {@bitCast(i32, exit_code)}
+ Term { .Exited = @bitCast(i32, exit_code)}
}
});
@@ -281,13 +281,13 @@ pub const ChildProcess = struct {
fn statusToTerm(status: i32) -> Term {
return if (posix.WIFEXITED(status)) {
- Term.Exited { posix.WEXITSTATUS(status) }
+ Term { .Exited = posix.WEXITSTATUS(status) }
} else if (posix.WIFSIGNALED(status)) {
- Term.Signal { posix.WTERMSIG(status) }
+ Term { .Signal = posix.WTERMSIG(status) }
} else if (posix.WIFSTOPPED(status)) {
- Term.Stopped { posix.WSTOPSIG(status) }
+ Term { .Stopped = posix.WSTOPSIG(status) }
} else {
- Term.Unknown { status }
+ Term { .Unknown = status }
};
}
@@ -722,14 +722,14 @@ const ErrInt = @IntType(false, @sizeOf(error) * 8);
fn writeIntFd(fd: i32, value: ErrInt) -> %void {
var bytes: [@sizeOf(ErrInt)]u8 = undefined;
- mem.writeInt(bytes[0..], value, true);
+ mem.writeInt(bytes[0..], value, builtin.endian);
os.posixWrite(fd, bytes[0..]) %% return error.SystemResources;
}
fn readIntFd(fd: i32) -> %ErrInt {
var bytes: [@sizeOf(ErrInt)]u8 = undefined;
os.posixRead(fd, bytes[0..]) %% return error.SystemResources;
- return mem.readInt(bytes[0..], ErrInt, true);
+ return mem.readInt(bytes[0..], ErrInt, builtin.endian);
}
extern fn sigchld_handler(_: i32) {
diff --git a/std/os/index.zig b/std/os/index.zig
index e6a5fc4d15..361750aedc 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -939,6 +939,7 @@ start_over:
}
pub const Dir = struct {
+ // See man getdents
fd: i32,
allocator: &Allocator,
buf: []u8,
@@ -981,7 +982,7 @@ pub const Dir = struct {
pub fn close(self: &Dir) {
self.allocator.free(self.buf);
- close(self.fd);
+ os.close(self.fd);
}
/// Memory such as file names referenced in this returned entry becomes invalid
@@ -1013,7 +1014,7 @@ pub const Dir = struct {
break;
}
}
- const linux_entry = @ptrCast(&LinuxEntry, &self.buf[self.index]);
+ const linux_entry = @ptrCast(& align(1) LinuxEntry, &self.buf[self.index]);
const next_index = self.index + linux_entry.d_reclen;
self.index = next_index;
diff --git a/std/os/path.zig b/std/os/path.zig
index a372b5b077..3fd7b5e2db 100644
--- a/std/os/path.zig
+++ b/std/os/path.zig
@@ -1016,7 +1016,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
return os.readLink(allocator, proc_path);
},
- else => @compileError("TODO implement os.path.real for " ++ @enumTagName(builtin.os)),
+ else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
}
}
diff --git a/std/rand.zig b/std/rand.zig
index d7798df3da..09e0c8ac78 100644
--- a/std/rand.zig
+++ b/std/rand.zig
@@ -50,12 +50,12 @@ pub const Rand = struct {
pub fn fillBytes(r: &Rand, buf: []u8) {
var bytes_left = buf.len;
while (bytes_left >= @sizeOf(usize)) {
- mem.writeInt(buf[buf.len - bytes_left..], r.rng.get(), false);
+ mem.writeInt(buf[buf.len - bytes_left..], r.rng.get(), builtin.Endian.Little);
bytes_left -= @sizeOf(usize);
}
if (bytes_left > 0) {
var rand_val_array: [@sizeOf(usize)]u8 = undefined;
- mem.writeInt(rand_val_array[0..], r.rng.get(), false);
+ mem.writeInt(rand_val_array[0..], r.rng.get(), builtin.Endian.Little);
while (bytes_left > 0) {
buf[buf.len - bytes_left] = rand_val_array[@sizeOf(usize) - bytes_left];
bytes_left -= 1;
@@ -98,7 +98,7 @@ pub const Rand = struct {
while (true) {
r.fillBytes(rand_val_array[0..]);
- const rand_val = mem.readInt(rand_val_array, T, false);
+ const rand_val = mem.readInt(rand_val_array, T, builtin.Endian.Little);
if (rand_val < upper_bound) {
return start + (rand_val % total_range);
}
diff --git a/std/sort.zig b/std/sort.zig
index 1d7ca507ee..d02d685e07 100644
--- a/std/sort.zig
+++ b/std/sort.zig
@@ -4,6 +4,19 @@ const math = @import("math/index.zig");
pub const Cmp = math.Cmp;
+/// Stable sort using O(1) space. Currently implemented as insertion sort.
+pub fn sort_stable(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) {
+ {var i: usize = 1; while (i < array.len) : (i += 1) {
+ const x = array[i];
+ var j: usize = i;
+ while (j > 0 and cmp(array[j - 1], x) == Cmp.Greater) : (j -= 1) {
+ array[j] = array[j - 1];
+ }
+ array[j] = x;
+ }}
+}
+
+/// Unstable sort using O(n) stack space. Currently implemented as quicksort.
pub fn sort(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) {
if (array.len > 0) {
quicksort(T, array, 0, array.len - 1, cmp);
@@ -58,6 +71,63 @@ fn reverse(was: Cmp) -> Cmp {
// ---------------------------------------
// tests
+test "stable sort" {
+ testStableSort();
+ // TODO: uncomment this after https://github.com/zig-lang/zig/issues/639
+ //comptime testStableSort();
+}
+fn testStableSort() {
+ var expected = []IdAndValue {
+ IdAndValue{.id = 0, .value = 0},
+ IdAndValue{.id = 1, .value = 0},
+ IdAndValue{.id = 2, .value = 0},
+ IdAndValue{.id = 0, .value = 1},
+ IdAndValue{.id = 1, .value = 1},
+ IdAndValue{.id = 2, .value = 1},
+ IdAndValue{.id = 0, .value = 2},
+ IdAndValue{.id = 1, .value = 2},
+ IdAndValue{.id = 2, .value = 2},
+ };
+ var cases = [][9]IdAndValue {
+ []IdAndValue {
+ IdAndValue{.id = 0, .value = 0},
+ IdAndValue{.id = 0, .value = 1},
+ IdAndValue{.id = 0, .value = 2},
+ IdAndValue{.id = 1, .value = 0},
+ IdAndValue{.id = 1, .value = 1},
+ IdAndValue{.id = 1, .value = 2},
+ IdAndValue{.id = 2, .value = 0},
+ IdAndValue{.id = 2, .value = 1},
+ IdAndValue{.id = 2, .value = 2},
+ },
+ []IdAndValue {
+ IdAndValue{.id = 0, .value = 2},
+ IdAndValue{.id = 0, .value = 1},
+ IdAndValue{.id = 0, .value = 0},
+ IdAndValue{.id = 1, .value = 2},
+ IdAndValue{.id = 1, .value = 1},
+ IdAndValue{.id = 1, .value = 0},
+ IdAndValue{.id = 2, .value = 2},
+ IdAndValue{.id = 2, .value = 1},
+ IdAndValue{.id = 2, .value = 0},
+ },
+ };
+ for (cases) |*case| {
+ sort_stable(IdAndValue, (*case)[0..], cmpByValue);
+ for (*case) |item, i| {
+ assert(item.id == expected[i].id);
+ assert(item.value == expected[i].value);
+ }
+ }
+}
+const IdAndValue = struct {
+ id: i32,
+ value: i32,
+};
+fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) -> Cmp {
+ return i32asc(a.value, b.value);
+}
+
test "testSort" {
const u8cases = [][]const []const u8 {
[][]const u8{"", ""},
diff --git a/std/special/compiler_rt/udivmod.zig b/std/special/compiler_rt/udivmod.zig
index c6a2babbf6..7e09c3d4d7 100644
--- a/std/special/compiler_rt/udivmod.zig
+++ b/std/special/compiler_rt/udivmod.zig
@@ -1,7 +1,7 @@
const builtin = @import("builtin");
const is_test = builtin.is_test;
-const low = if (builtin.is_big_endian) 1 else 0;
+const low = switch (builtin.endian) { builtin.Endian.Big => 1, builtin.Endian.Little => 0 };
const high = 1 - low;
pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?&DoubleInt) -> DoubleInt {